Intro to Reversing Windows Portable Executibles
Hello again geeks and ghosts. In the past few weeks, I've been playing in all kinds of CTFs: Codegate2013, pCTF2013, SecuinsideCTF, ebCTF, UnalocCTF, BSides SF CTF, BSides Chicago CTF, and BSides Quebec CTF. All have varied in difficulty and directive, ranging in any task from web or network exploitation to reverse engineering executables or crypto-grams. Some CTFs can be highly difficult and invloved, requiring you to write ROP buffer overflows, navigating around ASLR and DEP, while others are more basic, with some challenges as simple as viewing the source code to a web page. The following will be a quick primer on how to go about reversing Windows PEs, getting them to execute in the desired manner, and walking away with the flag every time. This is far from all inclusive, and should merely serve as a jumping point for your reverse engineering journey!
The first one we will discus is SecuinsideCTF's GAME150.
^^ This game was a riot. You fly around as Neo blasting tiny heads until the boss head comes out (Don't take it from me, download and reverse it yourself). The boss clearly has too much life to take down in a head to head fight (999,999 hp!), so we have to do some cheating to get this flag. Note: It's usually wise to do all reversing inside a virtual machine, for stability sake. The first step in messing with any file, that anyone gives you, is throw it at a file and malware analytics engine such as virustotal. Virustotal provides tons of extra, helpful information for our PE analysis as well. It will extract several of the header values, giving us useful info such as the target machine, the compile timestamp, the entry point, imports, and details on the various PE sections (such as .text, .data, etc...). Virustotal will also run ExifTool on the binary, giving us that useful header information and saving us the trouble. Another uber tool for Windows PE reverse engineering is PEiD, which will provides some additional information, including any packers, crypters, or compilers it can recognize.
For this reverse engineering exercise we are going to use a GNU tool called ObjDump. Using 'ObjDump -x filename.exe' will provide all of the header information, giving us a wealth of information right from the start. For this exercise, the most useful pieces will 'Sections' at the bottom. Note, Window's PEs are divided up into '.text' sections, where the code instructions reside, and '.data' sections, where hardcoded data sections resides (there are other sections as well, but they will not be covered in this post). We can jump the contents of a specific location with the flags "-s -j.'section'", therefore the command we want to dump the contents of our .data section is 'objdump -s -j.data -x filename.exe'. Now we just need to locate the bosses start health. 999,999 in hex is F423F, but in little-endian is 3F420F. Using the tool hexedit, we can find this value at 0x6440/0x444000 (Simply hit 'enter' to search for a memory location, such as 6440; You can also search for a value '/' and then the value, such as 3F420F). Change this value to 01000000. You can get the shimmed version of this game here, however I highly encourage you to reverse it yourself.
The ebCTF BIN100 Dice Game was another fun one and should be mentioned.
^^ This game (Feel free to download it and reverse it yourself), was a great learning exercise as well. The goal of this game is to roll five numbers in a specific order, 3 - 1 - 3 - 3 - 7, using the same random roll function each time. But there's a catch, you have to roll a 7 with a six sided die. We used the following tools to locate and patch five functions in the code, allowing us to roll any value and still win (including a 7 on a six sided die!). The tools we used for this disassemble were IdaProFree and OllyDebug to patch the application.
For starters, open up IdaPro, start a new project and load up your executable as a Windows PE. Run the default analysis settings and let it do it's thing. It's best to make it full screen, keeping your IDA View-A window the main focus. If I go over to the Strings Window on the right, I can find a string that says '[*] You rolled a three! Good!' (Line 11 of 173). Double clicking this string will take me to it's location in memory. Right below that string in memory, we can see "DATA XREF: sub_401390+5D↑o", clicking the "sub_" string will take you to the location of memory that called this piece of text. In the graph view, we now see the function that is called after a successful dice roll. Following the red line that comes into the top of this function, we can see the previous function that branched here, the red line shows that it branched based on a FALSE condition (as opposed to something evaluating true and following a different execution path). The function that branched to the piece of code we want, was a JNZ evaluating to false (meaning it didn't 'jump if not zero'). Therefore, if we want this piece of code to always follow this execution flow, we can simply remove that JNZ, ensuring that our code will never jump away from saying we rolled the correct number (Note: the function still rolls any number, and we still compare this number to an expected result, however removing this JNZ (we will replace it with a NOP) will simply do nothing with the CMP (compare) result, essentially hard coding the same control flow every time as opposed to jumping based on the result). To do this, we need the exact memory location of that JNZ instruction, so right click on the JNZ in graph view, and select 'text view'. On the far left, the piece of data that reads ".text: 0040192B" is the memory location of the instruction that we want to change from JNZ to NOP. Next, fire up Olydbg.
Once Olydbg has booted, select file open, and load the executable. We will be focusing on the top left pane, CPU - main thread. Here, scroll down the list of memory addresses, on the left, till you reach '0040192B'. Notice it's our friend JNZ! Double click the string 'JNZ SHORT ebCTF-Te.0040198B' and replace everything in that text box with a single 'NOP', click Assemble, click Cancel. You should now see two red NOP instructions in your file. Next, right click on the file, mouse over 'Copy to executable', and select 'All modifications'. Select 'Copy all' at the prompt. This will launch a pop-up of the new executable. Closing out of this pop-up will let you save this new executable to any where you like. Wa-la, you just patched a Windows portable executable's runtime instructions.
To finish getting the flag from this dice executable, continue patching the instructions at the remaining four compares. There are other ways to accomplish getting the flag, for example you could simply try to extract the flag from memory, however this may prove more difficult as the program seems to assemble the flag throughout runtime. You can also check out the fully shimmed version here, to compare results or simply see how it executes once it's been successfully reversed.
Happy Hacking!
ADB
The first one we will discus is SecuinsideCTF's GAME150.
^^ This game was a riot. You fly around as Neo blasting tiny heads until the boss head comes out (Don't take it from me, download and reverse it yourself). The boss clearly has too much life to take down in a head to head fight (999,999 hp!), so we have to do some cheating to get this flag. Note: It's usually wise to do all reversing inside a virtual machine, for stability sake. The first step in messing with any file, that anyone gives you, is throw it at a file and malware analytics engine such as virustotal. Virustotal provides tons of extra, helpful information for our PE analysis as well. It will extract several of the header values, giving us useful info such as the target machine, the compile timestamp, the entry point, imports, and details on the various PE sections (such as .text, .data, etc...). Virustotal will also run ExifTool on the binary, giving us that useful header information and saving us the trouble. Another uber tool for Windows PE reverse engineering is PEiD, which will provides some additional information, including any packers, crypters, or compilers it can recognize.
For this reverse engineering exercise we are going to use a GNU tool called ObjDump. Using 'ObjDump -x filename.exe' will provide all of the header information, giving us a wealth of information right from the start. For this exercise, the most useful pieces will 'Sections' at the bottom. Note, Window's PEs are divided up into '.text' sections, where the code instructions reside, and '.data' sections, where hardcoded data sections resides (there are other sections as well, but they will not be covered in this post). We can jump the contents of a specific location with the flags "-s -j.'section'", therefore the command we want to dump the contents of our .data section is 'objdump -s -j.data -x filename.exe'. Now we just need to locate the bosses start health. 999,999 in hex is F423F, but in little-endian is 3F420F. Using the tool hexedit, we can find this value at 0x6440/0x444000 (Simply hit 'enter' to search for a memory location, such as 6440; You can also search for a value '/' and then the value, such as 3F420F). Change this value to 01000000. You can get the shimmed version of this game here, however I highly encourage you to reverse it yourself.
The ebCTF BIN100 Dice Game was another fun one and should be mentioned.
^^ This game (Feel free to download it and reverse it yourself), was a great learning exercise as well. The goal of this game is to roll five numbers in a specific order, 3 - 1 - 3 - 3 - 7, using the same random roll function each time. But there's a catch, you have to roll a 7 with a six sided die. We used the following tools to locate and patch five functions in the code, allowing us to roll any value and still win (including a 7 on a six sided die!). The tools we used for this disassemble were IdaProFree and OllyDebug to patch the application.
For starters, open up IdaPro, start a new project and load up your executable as a Windows PE. Run the default analysis settings and let it do it's thing. It's best to make it full screen, keeping your IDA View-A window the main focus. If I go over to the Strings Window on the right, I can find a string that says '[*] You rolled a three! Good!' (Line 11 of 173). Double clicking this string will take me to it's location in memory. Right below that string in memory, we can see "DATA XREF: sub_401390+5D↑o", clicking the "sub_" string will take you to the location of memory that called this piece of text. In the graph view, we now see the function that is called after a successful dice roll. Following the red line that comes into the top of this function, we can see the previous function that branched here, the red line shows that it branched based on a FALSE condition (as opposed to something evaluating true and following a different execution path). The function that branched to the piece of code we want, was a JNZ evaluating to false (meaning it didn't 'jump if not zero'). Therefore, if we want this piece of code to always follow this execution flow, we can simply remove that JNZ, ensuring that our code will never jump away from saying we rolled the correct number (Note: the function still rolls any number, and we still compare this number to an expected result, however removing this JNZ (we will replace it with a NOP) will simply do nothing with the CMP (compare) result, essentially hard coding the same control flow every time as opposed to jumping based on the result). To do this, we need the exact memory location of that JNZ instruction, so right click on the JNZ in graph view, and select 'text view'. On the far left, the piece of data that reads ".text: 0040192B" is the memory location of the instruction that we want to change from JNZ to NOP. Next, fire up Olydbg.
Once Olydbg has booted, select file open, and load the executable. We will be focusing on the top left pane, CPU - main thread. Here, scroll down the list of memory addresses, on the left, till you reach '0040192B'. Notice it's our friend JNZ! Double click the string 'JNZ SHORT ebCTF-Te.0040198B' and replace everything in that text box with a single 'NOP', click Assemble, click Cancel. You should now see two red NOP instructions in your file. Next, right click on the file, mouse over 'Copy to executable', and select 'All modifications'. Select 'Copy all' at the prompt. This will launch a pop-up of the new executable. Closing out of this pop-up will let you save this new executable to any where you like. Wa-la, you just patched a Windows portable executable's runtime instructions.
To finish getting the flag from this dice executable, continue patching the instructions at the remaining four compares. There are other ways to accomplish getting the flag, for example you could simply try to extract the flag from memory, however this may prove more difficult as the program seems to assemble the flag throughout runtime. You can also check out the fully shimmed version here, to compare results or simply see how it executes once it's been successfully reversed.
Happy Hacking!
ADB