Didier Stevens

Wednesday 27 December 2017

Cracking Encrypted PDFs – Part 2

Filed under: Encryption,Forensics,Hacking,PDF — Didier Stevens @ 0:00

After cracking the “easy” PDF of John’s challenge, I’m cracking the “tough” PDF (harder_encryption).

Using the same steps as for the “easy” PDF, I confirm the PDF is encrypted with a user password using 40-bit encryption, and I extract the hash.

Since the password is a long random password, a brute-force attack on the password like I did in the first part will take too long. That’s why I’m going to perform a brute-force attack on the key: using 40-bit encryption means that the key is just 5 bytes long, and that will take about 2 hours on my machine. The key is derived from the password.

I’m using hashcat again, but this time with hash mode 10410 in stead of 10400.
This is the command I’m using:

hashcat-4.0.0\hashcat64.exe --potfile-path=harder_encryption.pot -m 10410 -a 3 -w 3 "harder_encryption - CONFIDENTIAL.hash" ?b?b?b?b?b

I’m using the following options:

  • –potfile-path=harder_encryption.pot : I prefer using a dedicated pot file, but this is optional
  • -m 10410 : this hash mode is suitable to crack the key used for 40-bit PDF encryption
  • -a 3 : I perform a brute force attack (since it’s a key, not a password)
  • -w 3 : I’m using a workload profile that is supposed to speed up cracking on my machine
  • ?b?b?b?b?b : I’m providing a mask for 5 bytes (I want to brute-force keys that are 40 bits long, i.e. 5 bytes)

And here is the result:

The recovered key is 27ce78c81a. I was lucky, it took about 15 minutes to recover this key (again, using GPU GeForce GTX 980M, 2048/8192 MB allocatable, 12MCU). Checking the complete keyspace whould take a bit more than 2 hours.

Now, how can we decrypt a PDF with the key (in stead of the password)? I’ll explain that in the next blog post.

Want a hint? Take a look at my Tweet!

Update: this is the complete blog post series:

Tuesday 26 December 2017

Cracking Encrypted PDFs – Part 1

Filed under: Encryption,Forensics,Hacking,PDF — Didier Stevens @ 17:15

In this series of blog posts, I’ll explain how I decrypted the encrypted PDFs shared by John August (John wanted to know how easy it is to crack encrypted PDFs, and started a challenge).

Here is how I decrypted the “easy” PDF (encryption_test).

From John’s blog post, I know the password is random and short. So first, let’s check out how the PDF is encrypted.

pdfid.py confirms the PDF is encrypted (name /Encrypt):

pdf-parser.py can tell us more:

The encryption info is in object 26:

From this I can conclude that the standard encryption filter was used. This encryption method uses a 40-bit key (usually indicated by a dictionary entry: /Length 40, but this is missing here).

PDFs can be encrypted for confidentiality (requiring a so-called user password /U) or for DRM (using a so-called owner password /O). PDFs encrypted with a user password can only be opened by providing this password. PDFs encrypted with a owner password can be opened without providing a password, but some restrictions will apply (for example, printing could be disabled).

QPDF can be used to determine if the PDF is protected with a user password or an owner password:

This output (invalid password) tells us the PDF document is encrypted with a user password.

I’ve written some blog posts about decrypting PDFs, but because we need to perform a brute-force attack here (it’s a short random password), this time I’m going to use hashcat to crack the password.

First we need to extract the hash to crack from the PDF. I’m using pdf2john.py to do this. Remark that John the Ripper (Jumbo version) is now using pdf2john.pl (a Perl program), because there were some issues with the Python program (pdf2john.py). For example, it would not properly generate a hash for 40-bit keys when the /Length name was not specified (like is the case here). However, I use a patched version of pdf2john.py that properly handles default 40-bit keys.

Here’s how we extract the hash:

This format is suitable for John the Ripper, but not for hashcat. For hashcat, just the hash is needed (field 2), and no other fields.

Let’s extract field 2 (you can use awk instead of csv-cut.py):

I’m storing the output in file “encryption_test – CONFIDENTIAL.hash”.

And now we can finally use hashcat. This is the command I’m using:

hashcat-4.0.0\hashcat64.exe --potfile-path=encryption_test.pot -m 10400 -a 3 -i "encryption_test - CONFIDENTIAL.hash" ?a?a?a?a?a?a

I’m using the following options:

  • –potfile-path=encryption_test.pot : I prefer using a dedicated pot file, but this is optional
  • -m 10400 : this hash mode is suitable to crack the password used for 40-bit PDF encryption
  • -a 3 : I perform a brute force attack (since it’s a random password)
  • ?a?a?a?a?a?a : I’m providing a mask for 6 alphanumeric characters (I want to brute-force passwords up to 6 alphanumeric characters, I’m assuming when John mentions a short password, it’s not longer than 6 characters)
  • -i : this incremental option makes that the set of generated password is not only 6 characters long, but also 1, 2, 3, 4 and 5 characters long

And here is the result:

The recovered password is 1806. We can confirm this with QPDF:

Conclusion: PDFs protected with a 4 character user password using 40-bit encryption can be cracked in a couple of seconds using free, open-source tools.

FYI, I used the following GPU: GeForce GTX 980M, 2048/8192 MB allocatable, 12MCU

Update: this is the complete blog post series:

Monday 10 July 2017

Select Parent Process from VBA

Filed under: Forensics,Hacking,maldoc,Malware,My Software — Didier Stevens @ 0:00

Years ago I wrote a C program to create a new process with a chosen parent process: selectmyparent. And recently I showed what process monitor and system monitor report when you use this tool.

Starting a new process with a chosen parent process can be done from VBA too, as shown in this video (I’m not sharing the VBA code):

Monday 20 March 2017

That Is Not My Child Process!

Filed under: Forensics,Hacking — Didier Stevens @ 0:00

Years ago I released a tool to create a Windows process with selected parent process: SelectMyParent.

You can not blindly trust parent-child process relations in Windows: the parent of a process can be different from the process that created that process.

Here I start selectmyparent from cmd.exe to launch notepad.exe with parent explorer.exe (PID 328):

Process Explorer reports explorer.exe as the parent (and not selectmyparent.exe):

Process Monitor also reports explorer.exe as the parent:

If we look in the call stack of the process creation of notepad.exe, we see 2 frames (6 and 7) with unknown modules:

We should see entries in the call stack for explorer.exe if notepad.exe was started by explorer.exe, but we don’t.

The <unknown> module is actually selectmyparent.exe.

0x11b1461 is the address of the instruction after the call to _main in ___tmainCRTStarup in selectmyparent.exe.

0x11b12a8 is the address of the instruction after the call to CreateProcessW in _main in selectmyparent.exe.

 

System Monitor also reports explorer.exe as the parent:

Finally, Volatility’s pstree command also reports explorer.exe as the parent:

Monday 30 January 2017

Quickpost: Dropbox & Alternate Data Streams

Filed under: Forensics,Quickpost,Reverse Engineering — Didier Stevens @ 0:00

When I got this popup while moving a file from a Dropbox folder, I immediately thought Alternate Data Stream:

20170124-221042

I ran my filescanner on the file, and found an ADS with name com.dropbox.attributes:

20170128-094319

From the Magic HEX value, we can see that the content of the stream (frozen-sea-foam.mp4:com.dropbox.attributes) starts with 0x78 (and the streamsize is 83 bytes). 0x78 hints at zlib deflated data.

If you are not that familiar with magic values, you can use my file-magic tool:

20170128-224649

Trying to decompress the ADS with translate.py gives us JSON data {“dropbox_fileid_local”: {“machineid_attr”: {“data”: “aa4xliox7z5n0qewxOlT3Q==”}}}:

20170128-102645

The data field looks like BASE64, so let’s try to decode it with base64dump.py:

20170128-104110

It decodes with BASE64 to data that looks random. From the names in the JSON data, we can deduce that this is probably a machine ID.

Remark 1: as it could well be my unique machine ID, I altered the value of the ID.

Remark 2: my file-magic.py tool is beta.

Remark 3: if you wonder what the video frozen-sea-foam is, I have it on Instragram.

 


Quickpost info


Sunday 13 December 2015

Windows Backup Privilege: CMD.EXE

Filed under: Forensics,My Software — Didier Stevens @ 0:00

You probably encountered the situation where you could not access a file, even as an administrator. For example hiberfil.sys.

There is a way in Windows to read any file regardless of DACLs: the backup privilege.

I updated ReactOS’ cmd.exe shell to use the backup privilege.

I added a new command: privilege. This command enables the backup privilege. To be able to enable a privilege, you need to have the privilege: you have the backup privilege if you’re an administrator and elevate the process (cmd.exe).

And I updated the copy and type command to make use of the enabled backup privilege.

Finally, there’s yet another new command: info. This command gives the MAC timestamps, file attributes and SDDL of the given file/folder.

cmd-dll_v0_0_4.zip (https)
MD5: D9D75A10F2C328B708303F9BD24B9AD3
SHA256: 952CFB833D4F22093D7DF837372239A1199C1738FFFFED76124AF8668F4D3877

Tuesday 1 September 2015

nsrl.py: Using the Reference Data Set of the National Software Reference Library

Filed under: Forensics,My Software — Didier Stevens @ 0:00

When I scan executables on a Windows machine looking for malware or suspicious files, I often use the Reference Data Set of the National Software Reference Library to filter out known benign files.

nsrl.py is the program I wrote to do this. nsrl.py can read the Reference Data Set directly from the ZIP file provided by the NSRL, no need to unzip it.

20150831-230251

Usage: nsrl.py [options] filemd5 [NSRL-file]
NSRL tool

Options:
–version             show program’s version number and exit
-h, –help            show this help message and exit
-s SEPARATOR, –separator=SEPARATOR
separator to use (default is ; )
-H HASH, –hash=HASH  NSRL hash to use, options: SHA-1, MD5, CRC32 (default
MD5)
-f, –foundonly       only report found hashes
-n, –notfoundonly    only report missing hashes
-a, –allfinds        report all matching hashes, not just first one
-q, –quiet           do not produce console output
-o OUTPUT, –output=OUTPUT
output to file
-m, –man             Print manual

Manual:

nsrl.py looks up a list of hashes in the NSRL database and reports the
results as a CSV file.

The program takes as input a list of hashes (a text file). By default,
the hash used for lookup in the NSRL database is MD5. You can use
option -H to select hash algorithm sha-1 or crc32. The list of hashes
is read into memory, and then the NSRL database is read and compared
with the list of hashes. If there is a match, a line is added to the
CSV report for this hash. The list of hashes is deduplicated before
matching occurs. So if a hash appears more than once in the list of
hashes, it is only matched once. If a hash has more than one entry in
the NSRL database, then only the first occurrence will be reported.
Unless option -a is used to report all matching entries of the same
hash. The first part of the CSV report contains all matching hashes,
and the second part all non-matching hashes (hashes that were not
found in the NSRL database). Use option -f to report only matching
hashes, and option -n to report only non-matching hashes.

The CSV file is outputted to console and written to a CSV file with
the same name has the list of hashes, but with a timestamp appended.
To prevent output to the console, use option -q. T choose the output
filename, use option -o. The separator used in the CSV file is ;. This
can be changed with option -s.

The second argument given to nsrl.py is the NSRL database. This can be
the NSRL database text file (NSRLFile.txt), the gzip compressed NSRL
database text file or the ZIP file containing the NSRL database text
file. I use the “reduced set” or minimal hashset (each hash appears
only once) found on http://www.nsrl.nist.gov/Downloads.htm. The second
argument can be omitted if a gzip compressed NSRL database text file
NSRLFile.txt.gz is stored in the same directory as nsrl.py.

nsrl_V0_0_1.zip (https)
MD5: 5063EEEF7345C65D012F65463754A97C
SHA256: ADD3E82EDABA7F956CDEBE93135096963B0B11BB48473EEC2C45FC21CFB32BAA

Monday 3 August 2015

Jump List Forensics

Filed under: Forensics,My Software — Didier Stevens @ 0:00

Jump List files are actually OLE files. These files (introduced with Windows 7) give access to recently accessed applications and files. They have forensic value. You can find them in C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations and C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Recent\CustomDestinations.

The AutomaticDestinations files are the OLE files, so you can analyze them with oledump. There are a couple of tools that can extract information from these files.

Here you can see oledump analyzing an automatic Jump List file:

20150712-190918

The stream DestList contains the Jump List data:

20150712-191030

There are several sites on the Internet explaining the format of this data, like this one. I used this information to code a plugin for Jump List files:

20150712-191130

The plugin takes an option (-f) to condense the information to just filenames:

20150712-191215

Wednesday 22 July 2015

“Analysing Malicious Documents” Training At 44CON London

Filed under: Announcement,Didier Stevens Labs,Forensics,My Software — Didier Stevens @ 0:00

I’m teaching a 2-day class “Analysing Malicious Documents” at 44CON London.

Here is my promo video:

Monday 13 July 2015

Extracting Dyre Configuration From A Process Dump

Filed under: Forensics,My Software,Reverse Engineering — Didier Stevens @ 0:00

There are a couple of scripts and programs available on the Internet to extract the configuration of the Dyre banking malware from a memory dump. What I’m showing here is a method using a generic regular expression tool I developed (re-search).

Here is the Dyre configuration extracted from the strings found inside the memory dump:

2015-07-12_14-47-24

I want to produce a list of the domains found as first item in an <litem> element. re-search is a bit like grep -o, it doesn’t select lines but it selects matches of the provided regular expression. Here I’m looking for tag <litem>:

2015-07-12_15-10-39

By default, re-search will process text files line-by-line, like grep. But since the process memory dump is not a text file but a binary file, it’s best not to try to process it line-by-line, but process it in one go. This is done with option -f (fullread).

Next I’m extending my regular expression to include the newline characters following <litem>:

2015-07-12_15-17-35

And now I extend it with the domain (remark that the Dyre configuration supports asterisks (*) in the domain names):

2015-07-12_15-19-58

If you include a group () in your regular expression, re-search will only output the matched group, and not the complete regex match. So by surrounding the regex for the domain with parentheses, I extract the domains:

2015-07-12_15-24-44

This gives me 1632 domains, but many domains appear more than once in the list. I use option -u (unique) to produce a list of unique domain names (683 domains):

2015-07-12_15-28-06

Producing a sorted list of domain names is not simple when they have subdomains:

2015-07-12_15-30-09

That’s why I have a tool to sort domains by tld first, then domain, then subdomain, …

2015-07-12_15-32-28
re-search_V0_0_1.zip (https)
MD5: 5700D814CE5DD5B47F9C09CD819256BD
SHA256: 8CCF0117444A2F28BAEA6281200805A07445E9A061D301CC385965F3D0E8B1AF

« Previous PageNext Page »

Blog at WordPress.com.