Saturday, 21 October 2017

CTF Writeup - Flare-On 2017 - 04: notepad.exe

  1. Name - notepad.exe
  2. Category - Reverse Engineering
  3. Points - 1
  4. Binary - Download here

Running the binary notepad.exe we get:

Expected anything else from a binary called notepad.exe? When the binary is loaded into IDA, we even get the prompt to apply MS symbols to it! Interesting, so what's different from the normal notepad.exe? For starters, the Entry Point points at an executable .rsrc section at the bottom of the PE which also contains other functions. Additionally, the binary loads several strings onto the stack in the start() function, usually an indication that it is trying to hide some functionality:

The start() function looks a bit daunting so I've decided to take a different approach with this challenge and use ProcMon to deduce (guess?) it's inner workings. Filtering on notepad.exe and File System Activity we get the following:

The executable searches for path C:\Users\<user>\flareon2016challenge which is not present on the machine. Create the folder and put a dummy file in, say an empty text file called testing.txt. The function that searches for this file path is sub_1013F30() which does the following:
  1. Constructs the string 'C:\Users\<user>\flareon2016challenge'
  2. Calls FindFirstFileA on the path
  3. For each file found in the folder, invokes sub_1014E20() on it's file path
The first bit of function sub_1014E20() does some validation on the input file:

It performs the following:
  1. Checks that the file starts with 'MZ' (Green)
  2. Ensures that 'PE' offset is less than the size of the binary (Red)
  3. Checks that the file has 'PE' in the right place (Yellow)
  4. Ensures that the Target Machine is for Intel 386 and later (Blue)
  5. Passes the binary mapping to sub_10146C0()
The function sub_10146C0() then takes the timestamp of the input file and the timestamp of notepad.exe and branches the execution flow depending on these 2 values:

The blue basic blocks deal with notepad.exe whilst the yellow ones deal with the input file. Depending on these 2 variables, the execution flow will take 1 of the 5 relevant paths shown below:

Notice that 4 of them are very similar to each other. Let's go through one of them taking the 1st one (left most) as an example. The basic block does the following:
  1. Sub_1014350 converts 0x57D1B2A2 into the Date and Time: 2016/09/08 18:49:06 UTC
  2. Call ECX pops a message box with the resultant Date and Time
  3. Sub_10145B0 takes first 8 bytes from binary at offset 0x400 and writes them to key.bin
The other basic block (2nd from the right) reads the contents of key.bin, checks if it is 32 bytes long and XOR's it with another 32 bytes. The big question at this point is, what should key.bin contain? And hence what should the 4 PE files in 'C:\Users\<user>\flareon2016challenge' be?

The hint is in the folder name 'flareon2016challenge'. Download last year's Flare-On challenges and notice that challenge1.exe has a Date Modified of 08/09/2016 19:49 which matches with the timestamp we've analysed. Copying the challenge1.exe binary in the flareon2016challenge folder and running notepad.exe again we get the following Message Box and the first 8 bytes of the key in key.bin:

Cutting to the chase, the following are the 4 binaries from last year's challenge that match the 4 timestamps required by notepad.exe:
  1. challenge1.exe
  2. DudeLocker.exe
  3. khaki.exe
  4. unknown
We can now complete the challenge by placing these 4 binaries in the flareon2016challenge folder and run notepad.exe. Note that this requires us to change the timestamp of notepad.exe or to change the control flow during execution to ensure that all the branches are taken in the right order.

Alternatively we can extract the 8 bytes key from each binary at offsets 0x400, 0x410, 0x420 and 0x430 respectively (refer to image above). This will give us the key and we can create a small python script to print the solution:

key1 = '\x55\x8b\xec\x8b\x4d\x0c\x56\x57\x8B\x55\x08\x52\xFF\x15\x30\x20\xC0\x40\x50\xFF\xD6\x83\xC4\x08\x00\x83\xC4\x08\x5D\xC3\xCC\xCC'
key2 = '\x37\xE7\xd8\xbe\x7a\x53\x30\x25\xbb\x38\x57\x26\x97\x26\x6f\x50\xf4\x75\x67\xbf\xb0\xef\xa5\x7a\x65\xae\xab\x66\x73\xa0\xa3\xa1'

print ''.join([chr(ord(a) ^ ord(b)) for a,b in zip(key2,key1)])

Running the script:

Command Prompt
C:\>python C:\>

No comments:

Post a comment