<-- Flare-On 2015 Index / FLARE-On 2015 Challenge #1 
1
FLARE-On 2015 Challenge #1

Date: Aug 5, 2015

CHALLENGE MATERIALS:

filename:    Flare-On_start_2015.exe    DOWNLOAD
md5f812bf4e535409e60ea95213421db3ab
size182 k (186,880 bytes)
typex64 GUI Installer/Extractor
Original FLARE AuthorNick Harbour
 
filename:    i_am_happy_you_are_to_playing_the_flareon_challenge.exe    DOWNLOAD
md57c0f16de595ae03e2928d3fa6b73b235
size2 k (1,536 bytes)
typeWin32 Console App
(this is the the same file provided by the installer above,
but made available for those who don't want to run the
installer)
 
tool:    SysInternals Strings / String Dumper for Binary files    Visit Website
tool:    OllyDbg 2.01 / Debugger    Visit Website
tool:    Hex Editor
tool:    xorit / simple xor processor    INFO / DOWNLOAD

SUMMARY:
The first crackme is a basic console application that prompts the user for a password. The only thing this application does is tell us if we entered the correct password or not. The application was likely written in assembler because it is extremely small and was trimmed to the barebone essentials. This actually simplifies our job when disassembling because we don't have to wade through the usual compiler generated code.

INSTALLING THE FIRST CHALLENGE:
If you are running 64-bit version of Windows, you can download the first link above that is essentially a mini-installer GUI as originally provided by the FLARE website. After accepting the license agreement, you will be prompted to specify the path to extract challenge #1's executable file. If you don't want boot into 64-bit Windows for whatever reason (Olly claims to have odd problems running under 64-bit Windows and the challenges are all primarily 32-bit executables), I provided a second download link above which contains the same file extracted by the installer. The file supplied for challenge #1 is: i_am_happy_you_are_to_playing_the_flareon_challenge.exe.

Flare-On 2015 Setup - License Agreement   Flare-On 2015 Setup - Challenge Save Path

FIRST LAUNCH:
When dealing with unknown executables, you typically want to run the program in a debugger, a sandbox environment (such as on a virtual machine), a user with limited access rights, a machine with the network cable unplugged, or combinations of the above. Despite the warnings about potential malicious code in the FLARE license displayed in the installer, these challenges are safe and none will cause harm to your system.

With that out of the way, lets always start the programs from a console window (cmd.exe) to ensure we don't miss any messages that may be displayed:

Flare-On 2015 Challenge #1 - First Launch

Intentionally typing "spaz" as the password, we now know how the app responds to an incorrect password.

EXTRACT STRINGS FROM EXE:
Let's use the Windows "strings" utility (a free tool from www.sysinternals.com) to dump plaintext character sequences from our executable, limiting the output to strings of at least 5 characters in length. Since we know the password is an e-mail address, we should be able to spot anything with an "@" symbol rather easily.

NOTE: you may also use the functionally-equivalent "strings" tool that comes with most Linux distributions.

Flare-On 2015 Challenge #1 - Strings Tool Output

VIEWING EXE IN HEX VIEWER:
Okay, so we can see the console messages were embedded in plaintext, but nothing that looks like a password showed up. There was only one string that contained the "@" symbol, but it certainly didn't look like an e-mail address. We're going to have to dig a bit deeper. The next step we're going to try is to view the executable in a hex viewer or editor. Maybe the strings tool missed something that will catch our eye. The hex representation of the executable file should look something like this when viewed in your favorite hex viewer or editor (I used the Linux tool xxd to generate the dump below: e.g. xxd -g 1 -c 24 <filename>):
0000000: 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 b8 00 00 00 00 00 00 00  MZ......................
0000018: 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  @.......................
0000030: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 50 45 00 00 4c 01 02 00  ............@...PE..L...
0000048: 00 00 00 00 00 00 00 00 00 00 00 00 e0 00 03 01 0b 01 08 00 00 02 00 00  ........................
0000060: 00 02 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 00 40 00  ......................@.
0000078: 00 10 00 00 00 02 00 00 05 00 01 00 05 00 01 00 04 00 00 00 00 00 00 00  ........................
0000090: 00 30 00 00 00 02 00 00 00 00 00 00 03 00 00 00 00 00 10 00 00 10 00 00  .0......................
00000a8: 00 00 10 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00  ........................
00000c0: 00 20 00 00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  . ..(...................
00000d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000108: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4c 20 00 00 14 00 00 00  ................L ......
0000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000138: 2e 74 65 78 74 00 00 00 00 10 00 00 00 10 00 00 00 02 00 00 00 02 00 00  .text...................
0000150: 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 e0 2e 64 61 74 61 00 00 00  ............`....data...
0000168: 00 10 00 00 00 20 00 00 00 02 00 00 00 04 00 00 00 00 00 00 00 00 00 00  ..... ..................
0000180: 00 00 00 00 40 00 00 c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....@...................
0000198: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00001c8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00001f8: 00 00 00 00 00 00 00 00 55 89 e5 83 ec 10 89 45 f0 6a f6 ff 15 58 20 40  ........U......E.j...X @
0000210: 00 89 45 f4 6a f5 ff 15 58 20 40 00 89 45 f8 6a 00 8d 45 fc 50 6a 2a 68  ..E.j...X @..E.j..E.Pj*h
0000228: f2 20 40 00 ff 75 f8 ff 15 64 20 40 00 6a 00 8d 45 fc 50 6a 32 68 58 21  . @..u...d @.j..E.Pj2hX!
0000240: 40 00 ff 75 f4 ff 15 68 20 40 00 31 c9 8a 81 58 21 40 00 34 7d 3a 81 40  @..u...h @.1...X!@.4}:.@
0000258: 21 40 00 75 1e 41 83 f9 18 7c ea 6a 00 8d 45 fc 50 6a 12 68 1c 21 40 00  !@.u.A...|.j..E.Pj.h.!@.
0000270: ff 75 f8 ff 15 64 20 40 00 eb 16 6a 00 8d 45 fc 50 6a 12 68 2e 21 40 00  .u...d @...j..E.Pj.h.!@.
0000288: ff 75 f8 ff 15 64 20 40 00 89 ec 5d c3 00 00 00 00 00 00 00 00 00 00 00  .u...d @...]............
00002a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00002b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00002d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00002e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000348: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000378: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00003a8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00003c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00003d8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00003f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 20 00 00 00 00 00 00  ................( ......
0000408: 00 00 00 00 70 20 00 00 4c 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....p ..L ..............
0000420: 00 00 00 00 00 00 00 00 7d 20 00 00 8c 20 00 00 9d 20 00 00 ac 20 00 00  ........} ... ... ... ..
0000438: bb 20 00 00 cb 20 00 00 db 20 00 00 e7 20 00 00 00 00 00 00 7d 20 00 00  . ... ... ... ......} ..
0000450: 8c 20 00 00 9d 20 00 00 ac 20 00 00 bb 20 00 00 cb 20 00 00 db 20 00 00  . ... ... ... ... ... ..
0000468: e7 20 00 00 00 00 00 00 6b 65 72 6e 65 6c 33 32 2e 64 6c 6c 00 00 00 4c  . ......kernel32.dll...L
0000480: 6f 61 64 4c 69 62 72 61 72 79 41 00 00 00 47 65 74 50 72 6f 63 41 64 64  oadLibraryA...GetProcAdd
0000498: 72 65 73 73 00 00 00 47 65 74 4c 61 73 74 45 72 72 6f 72 00 00 00 47 65  ress...GetLastError...Ge
00004b0: 74 53 74 64 48 61 6e 64 6c 65 00 00 00 41 74 74 61 63 68 43 6f 6e 73 6f  tStdHandle...AttachConso
00004c8: 6c 65 00 00 00 57 72 69 74 65 43 6f 6e 73 6f 6c 65 41 00 00 00 57 72 69  le...WriteConsoleA...Wri
00004e0: 74 65 46 69 6c 65 00 00 00 52 65 61 64 46 69 6c 65 00 4c 65 74 27 73 20  teFile...ReadFile.Let's 
00004f8: 73 74 61 72 74 20 6f 75 74 20 65 61 73 79 0d 0a 45 6e 74 65 72 20 74 68  start out easy..Enter th
0000510: 65 20 70 61 73 73 77 6f 72 64 3e 00 59 6f 75 20 61 72 65 20 73 75 63 63  e password>.You are succ
0000528: 65 73 73 0d 0a 00 59 6f 75 20 61 72 65 20 66 61 69 6c 75 72 65 0d 0a 00  ess...You are failure...
0000540: 1f 08 13 13 04 22 0e 11 4d 0d 18 3d 1b 11 1c 0f 18 50 12 13 53 1e 12 10  ....."..M..=.....P..S...
0000558: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
0000588: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00005a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00005b8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00005d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
00005e8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
As you can see, there isn't anything that looks like an e-mail address. At this point, its clear that the password is somehow hidden.

RUNNING APP UNDER DEBUGGER:
Lets fire up a debugger to see what the code is doing. I used OllyDbg 2.01, launched with the following command line:
ollydbg.exe i_am_happy_you_are_to_playing_the_flareon_challenge.exe
If you have OllyDbg configured to break on module entry points during application startup (Options -> Debugging -> Start), you should find yourself at breakpoint 401000 / PUSH EBP. This is the module's entry point. I also recommend setting the environment variable _NT_SYMBOL_PATH to the location of the symbols for the version of Windows you are running and enabling the "Allow access to Microsoft Symbol Server" option in OllyDbg so you can see the names of the API calls rather than just addresses.

NOTE: If you are safely running this executable (along with OllyDbg) under VMWare or VirtualBox and you still don't find yourself at this instruction or the app simply exits without a debugger break (look for the red-text Terminated at the bottom right corner), ensure your processor supports virtualization and it is enabled in the BIOS/UEFI. If your host machine is Linux, you can run "cat /proc/cpuinfo|grep -i vmx" (Intel) or "cat /proc/cpuinfo|grep -i svm" (AMD) to see if virtualization is enabled (grep will return one of these flags). Under Windows, you can use a CPU identification tool like CPU-Z and look for "VT-x" under CPU -> Instructions. If you don't have virtualization support, you can use the "System breakpoint" option in OllyDbg instead, but you'll need to step through some userland Windows loader code that runs in the context of your process before you reach the first instruction in your module.

Flare-On 2015 Challenge #1 - OllyDbg Startup

FIND LOCATION WHERE USER INPUT IS PROCESSED:
For those of you with Windows API experience, you know that you must open console file handles to input or output text. The standard C library functions such as printf() and puts() wrap these same API calls (under Windows that is). Since symbols are set up, we can see in the right pane of the CPU window the two calls to GetStdHandle(). These calls get our console output and input handles, followed by a call to WriteFile() to output the password prompt. Finally we see a call to ReadFile() to accept our input.

For this particular app, we care most about what the instructions are doing to whatever value we type in for a password and are not really concerned with the rest. So lets step-over instructions (F8 key) until EIP (the instruction pointer) is at the XOR instruction immediately following the ReadFile() call.

You'll notice the debugger seems to freeze once you try to advance past the ReadFile() call. This is because ReadFile() is waiting for user input and has not returned to the caller. When this happens, switch to the window containing the app being debugged and type in a string value followed by <ENTER>. Once this is done, the debugger regains control at the XOR instruction following the ReadFile() call.

If you look at the PUSH instructions just prior to the ReadFile(), you can see that the address 402158 is passed as the buffer to store the user input. Lets display this buffer in the memory dump window. Select the PUSH instruction at address 40103D, then right-click and select "Follow in Dump" -> "Immediate constant". You should now see the string you typed in the dump window. In the sample below, you can see I typed "spaz" again:

Flare-On 2015 Challenge #1 - ReadFile input buffer

ANALYZE INPUT LOOP:
Notice how OllyDbg seems to group the instructions with a bracket at 40104D thru 401061. This is actually showing the conditional jump JL instruction jumping back to 40104D if the condition is satisfied. the XOR instruction we're currently at sets ECX to zero which happens to be the loop counter. The "CMP ECX, 18" just prior to the JL instruction means to keep looping back until we've counted 18 times. Since Olly shows operands in hex, this is decimal 24. So lets analyze this loop to see what it is doing:

0040104B XOR ECX, ECX ;reset loop counter to zero 0040104D MOV AL, BYTE PTR DS:[ECX+402158] ;pull next char from input buffer into AL 00401053 XOR AL, 7D ;encrypt input char by XORing with 0x7D 00401055 CMP AL, BYTE PTR DS:[ECX+402140] ;hmmm, we're comparing encrypted input characters with this other buffer? 0040105B JNE SHORT 0040107B ;does not match, exit loop to display a message 0040105D INC ECX ;increment loop counter 0040105E CMP ECX, 18 ;have we looked at 0x18 (24) chars? 00401061 JL SHORT 0040104D ;if not, keep looping until we have 00401063 PUSH 0 ; 00401065 LEA EAX, [LOCAL.1] ;if we get here, we matched all 24 chars 00401068 PUSH EAX ; 00401069 PUSH 12 ; 0040106B PUSH OFFSET 0040211C ;pointer to success message 00401070 PUSH DWORD PTR SS:[LOCAL.2] ; 00401073 CALL DWORD PTR DS:[<&kernel32.WriteFile>] ;output success message 00401079 JMP SHORT 00401091 ;skip over failure message 0040107B PUSH 0 ; 0040107D LEA EAX, [LOCAL.1] ;if we get here, the loop jumped here because of a mismatch 00401080 PUSH EAX ; 00401081 PUSH 12 ; 00401083 PUSH OFFSET 0040212E ;pointer to failure message 00401088 PUSH DWORD PTR SS:[LOCAL.2] ; 0040108B CALL DWORD PTR DS:[<&kernel32.WriteFile>] ;output failure message

The most important thing to notice is that this code is looping through each character in our input string, XORing each character with a value and then comparing the result with another character. We exit after looking at 24 characters so we know the correct password is 24 characters. If at any point the character doesn't match what is expected, we jump out to the failure branch and exit the program.

We now know that the XOR operation is the encryption technique employed by this app explaining why the password was not visible in the hex dump. We also know the encryption key is the byte value 0x7D, but we still need some way to determine the password.

Notice how the CMP instruction at 401055 compares one of our encrypted input characters against a value at the base address of 402140 indexed by the current counter. This base address seems to be the beginning of a series of values that correspond to each input character. At each iteration of the loop, the program is comparing an encrypted input character with the corresponding character in this buffer. Taking this one step further, because we know how long the password is, we can infer that we are comparing our input characters against the encrypted password located between 402140 thru 402157 inclusive (0x402140+0x18-1). If you look back at the EXE hex dump above, this corresponds to file offset 0x540 (just after the "You are failure" string). Because the password was encrypted/obfuscated, this range of bytes in the hex dump didn't look particularly meaningful at the time:
0000510: 65 20 70 61 73 73 77 6f 72 64 3e 00 59 6f 75 20 61 72 65 20 73 75 63 63  e password>.You are succ
0000528: 65 73 73 0d 0a 00 59 6f 75 20 61 72 65 20 66 61 69 6c 75 72 65 0d 0a 00  ess...You are failure...
0000540: 1f 08 13 13 04 22 0e 11 4d 0d 18 3d 1b 11 1c 0f 18 50 12 13 53 1e 12 10  ....."..M..=.....P..S...  <--- ENCRYPTED PASSWORD STORED HERE
0000558: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ........................
Select the CMP instruction at 401055, then right click on it and then select "Follow in Dump" -> "Memory address". This scrolls the dump window to the address in the instruction's memory address operand which happens to be 402140. The memory dump window should now display the portion of memory containing the encrypted password in the upper right portion followed by whatever else is in memory. This is why it is important that we already know (from the code) how much of this data is part of the encrypted password as portions directly after may belong to another part of the program. Notice the encrypted password happens to be directly adjacent to our input buffer:

Flare-On 2015 Challenge #1 - Encrypted Password Buffer

NOTE: The hex dump character column may not display the characters the same way OllyDbg is displaying them in the memory dump window; that's ok, because hex dumps customarily only display characters in the range of 32 thru 126 and everything else with period characters ".". Its the hex values that are important.

EXTRACT ENCRYPTED PASSWORD INTO SEPARATE FILE:
Since XOR is a symmetric operation (XOR plaintext char with key to encrypt, XOR encrypted char with same key to decrypt), all we need to do is XOR each encrypted byte with our key value of 0x7D to get back to each plaintext character. One method is to patch the program in place, such as to read from the encrypted buffer instead of our input buffer and then the XOR operation ends up decrypting the character. We then can step through the loop, writing down the value of each decrypted character as it appears in the AL register immediately following the XOR instruction.

But, I find it better to extract a copy of the encrypted key buffer into a separate file. This way we can work with it in isolation using other programs and techniques. To do this, click and select the 24 characters in the memory dump, then press CTRL-Insert (or right-click the selection and choose "Edit" -> "Binary copy"). This will copy the hex values to the clipboard. Now we need to fire up a hex editor that supports pasting hex values from the clipboard. Pasting hex values into a hex editor ensures we'll get an exact binary copy of the data we want, no more and no less. Copying and pasting binary characters into a text editor like notepad will not give us an exact binary copy as text editors will interpret the non-printable characters and convert line feeds.

In this case, I happen to be using an ancient version of Hex Workshop that still works great. Hex Workshop is nice because it supports pasting the raw hex values OllyDbg places on the clipboard to ensure an exact copy of a memory selection. In Hex Workshop, select from the menu "File" -> "New". Then select from the "Edit" menu -> "Paste Special...". Click the "Paste" button, leaving CF_TEXT as the default. The hex editor now has an exact copy of the bytes you selected in OllyDbg. The data can now be saved as a separate file using the "File" menu.

Hex Workshop

Another alternative is the FlexHEX editor, although with more steps. Before opening FlexHEX, paste the hex codes from OllyDbg into a plain text editor such as notepad and save the file. In FlexHEX, select from the menu bar "Edit" -> "Read/Write Data" -> "Import...". From the import dialog, choose the path to the file you just created and set "Format" to "Hex Bytes". You can leave "Separators" with the default value of " ," (spaces and commas). Finally click OK to import the hex codes as raw bytes. Now you can save off the binary file.

FlexHEX Import

CRACKING THE PASSWORD:
Now save the file and exit the hex editor. I named it password.bin. At this point, you could throw together a tool in your favorite programming language to open password.bin, loop through each byte to XOR it with 0x7D and finally output each resulting byte. This crackme is simple enough that I could just use the xorit tool to perform the operation just described.

Since the value of 0x7D is the close curly brace character "}", we'll run the following command to decrypt the password:
    xorit -q -kd "}" password.bin
Now that certainly looks like an e-mail address! Running the program again and using our cracked password as the input confirms that we got it right.

Flare-On 2015 Challenge #1 - Cracking the password

CONCLUSION:
The official solution used IDA to statically analyze the file to get a similar disassembly listing and ultimately arrive at the same conclusion. It also illustrated a neat IDA Python script to perform the XOR decryption.

E-MAIL RESPONSE:
Response from bunny_sl0pe@flare-on.com:
Subject: FLARE-On Challenge #1 Completed! From: bunny_sl0pe@flare-on.com To: <HIDDEN> Date: Wed, 05 Aug 2015 13:19:20 -0400 Congrats! I've attached the next challenge for your reversing pleasure. The password to this zip archive is "flare". This challenge looks a lot like the last one so hopefully you'll knock this one out too, Good luck! -FLARE attachment_filename="599EA8F84AD975CFB07E0E5732C9BA14.zip"

<< Flare-On 2015 Index  --  Go on to Challenge #2 >>

 1:1