Backdooring Notepad

In Part 1 of this tutorial series, we added a little extra assembly code to notepad in order to make it beep each time we loaded it. In this example, we will be examining how to add some code that is a bit more useful, by creating a reverse shell which will connect back to a listening client on 127.0.0.1:666 (ever wonder why the day after you downloaded that cracked software weird stuff started happening to your computer? Hmmm...). Additionally, we will be examining the PE header, as Part 1 ignored it for simplicity's sake.

Tools/Resources

[~] Metasploit - Used to generate reverse shellcode
[~] LordPE - Used to view and modify notepad's PE headers
[~] OllyDbg - Our debugger, same as in the previous tutorial
[~] Hex Workshop - A great hex editor
[~] win32.hlp - Used to look up Win32 API function parameters
[~] Shellform.pl - Perl script to remove formatting characters from our generated shellcode
[~] Netcat - To listen for a connection from our reverse shellcode

You can also download my copy of the modified notepad.exe if you want to follow the code along with the tutorial.

Getting the Shellcode

We first need to write some code to create a reverse shell. Luckily, there is a ton of great shellcode out there, and one of my favorite repositories is Metasploit. Follow the Metasploit link above and click on the 'Windows Shellcode' link, then select 'Windows Reverse Shell'. This brings you to a page with several options to choose from. Clear the EXITFUNC box, set LHOST to '127.0.0.1', and LPORT to '666'. Remove all restricted characters (we don't need to worry about null bytes and the like because we won't be injecting our code into any character buffers), and set the encoder to 'Msf::Encoder::None':

Copy the resulting shellcode into a text file named 'shellcode.txt', and run shellform.pl. This will create a new file, dump.txt, containing the unformatted shellcode. Copy this shellcode into the clipboard (Ctl+A, Ctl+C) and open up notepad.exe with Olly.

Let's go back to the code cave we used in the previous tutorial (0100874A), and this time select a large amount of space in the program (enough to hold the 287 byte shellcode), 'Right Click -> Binary -> Paste'. Now that our shellcode resides inside notepad, let's try to save our changes by 'Right Click -> Copy to executable -> All modifications'. We get an error from Olly stating that it is “Unable to locate data in executable file". To find out why, let's analyze notepad's PE headers.

PE Headers

Exit out of olly and fire up LordPE. LordPE is a great PE viewer/editor which we will use to view and modify notepad's PE header. Click on 'PE Editor' and select your copy of notepad.exe to open. Click 'Sections' to view the code sections as they are defined in the PE header. The .text section contains the executable code, which is the section we are trying to add our code to, so let's take a look at the values there:

The values to take note of are:

VOffset - The memory offset at which the section begins when it is loaded into memory
VSize - The size of actual data in the section
ROffest - The offset at which the data in the actual executable file begins
Rsize – The total size of the section

The text section starts at 00001000, has an absolute size of 00007800, and the code inside it actually stops at 00007748. This means that there are only 184 bytes of free space in the section:

 00007800
-00007748
--------------
000000B8 = 184

But Olly showed much more than just 184 bytes; why? When notepad is loaded into memory, the text section ends at 00008800 (VOffset + Rsize), but the next section doesn't start until offset 00009000. This means that there are 2048 bytes between sections when the executable is loaded into memory. We can write to this extra area of memory, but because it is not part of a section in the executable, Olly cannot write it back to notepad. In order to add our code to the program permanently, we need to modify the PE headers so that they reflect a larger amount of code space, then add that space and insert our code there. However, we cannot extend the size of the .text section without also changing all the other sections, plus any relative addresses in the code, etc. The easiest way to add our code is to append it to the very last section, in this case, .rsrc (we could also add a new section at the end of the section table, provided there is enough room in the section table to hold the 40 bytes needed for an additional section entry.).

I will add 1024 bytes (0x400) onto the end of the .rsrc section. This is a bit overkill for what we need, so if you want to add less than 1024, you may. To do this, we will modify the VSize and Rsize values to 00008E00 (00008A00 + 400 = 00008E00). Right click on .rsrc in LordPE's section table window and select 'edit section header'. Modify the values as specified, and be sure to change the Flags value to E0000040, indicating that the data in .rsrc is executable, readable and writable. Click OK and save your changes:

If we try to run our modified notepad now, we will receive an error stating that it is not a valid Win32 application. This is because we have specified that the .rsrc section is 1024 bytes larger than it really is, so we'll have to add 1024 bytes onto the end of the section. Open up the file in Hex Workshop and scroll down to the end of the hex dump. Since .rsrc is the last section in the executable, we can just tack our extra bytes onto the very end. Be sure the cursor is at the end of the hex dump, right click and select 'Insert'. Set the number of bytes to 400 (hex) and the hex byte to zero and click OK:

Save your changes and close Hex Workshop; try running notepad again and if you've done everything right, it will load up as usual.

Adding The Backdoor

Now that there is enough space in the executable to hold our code, we are ready to add our backdoor to notepad. Open the program up again in Olly and go to address 0100B000 (the beginning of the .rsrc section). Scroll down to the bottom and you will see our section of 0's starting at 0101393F. At 0101394D enter the standard pushad and pushfd instructions; you can probably enter these starting at 0101393F, but we have plenty of room to work with and I like to leave a little padding between the program's code and mine. Immediately afterwards, select a large enough section of memory to hold our shellcode and copy it there as before. Select all of the new code and you should be able to copy and save all modifications to the binary. Next, let's hijack the program's execution flow at 010073A4 by changing 'CALL 01007568' to 'JMP 0101394D'. Open up a command prompt and set netcat to listen for a connection ('nc -l -p 666'), then run the program in Olly. It works! Now we need to modify the shellcode so that it will return to notepad's regularly scheduled execution flow.

Restart notepad in Olly, be sure to add the JMP patch again (go ahead and save this to the executable while you're there), but this time we'll single step through the code (F8) to see what's going on. Stepping through the shellcode you will see references to some familiar API calls (if you've ever done Winsock programming anyway), such as WSAStartup, WSASocket, etc. However, once it creates a connection, it pauses at 01008850, which is a call to WaitForSingleObject. Looking this API call up in Win32.hlp, we see that it takes two arguments: a handle and a timeout period. Looking at the assembly code in Olly, we can see that the timeout period pushed onto the stack prior to calling WaitForSingleObject is -1, aka FF, aka, INFINATE. So, if we change the push -1 to a push 0, this function should return immediately, allowing execution to continue without waiting for the connection to end (be sure to save your changes!).

We have one final change to make: we need to return to notepad's original code. In Part 1, we just restored the registers and flags, then called the function which we replaced with the jump to our shellcode, then jumped back to notepad's next instruction. However, our shellcode has pushed a lot more data onto the stack, so we'll have to pop it all off before calling popfd/popad. Restart notepad in Olly and single step until you reach our 'pushfd' instruction. Note the memory address on the stack where the register's values are placed (in my case, 0006FF98). Set a breakpoint on the last instruction of our shellcode('CALL EAX') and press F9. When it breaks note the top memory address in the stack window; mine is 0006FEF4. This means that we have to pop 160 bytes off the stack before calling popfd/popad; since each pop instruction removes 4 bytes from the stack, we have to call pop 40 times. Just assemble 'POP EAX' 40 times immediately after our shellcode, then add the following code (see screenshot here):

popfd <---Restore the flags
popad <----- Restore the registers
call 01007568 <---- The call we replaced with 'JMP 0101394D'
jmp 010073a9 <---- The next instruction in notepad's original code

Select all your new changes, save them to the executable and exit out of Olly; set up netcat as before and run our modified notepad.exe. Congratulations, you've just backdoored notepad.

Conclusion

You should now be able to add as much code as you like to any unpacked/unprotected windows executable. For more detailed information on PE headers, be sure to check out Iczelion's PE Tutorial and Matt Pietrek's PE tutorial on MSDN. In Part 3 we will be looking at some different ways of making notepad load a custom DLL using very little or no assembly language, allowing us to write our code in a more human-friendly language such as C.