Here is a short and simple proof-of-concept tutorial on how you can manually add shellcode to common Windows executables, without using msfconsole or the backdoor-factory scripts to generate the binaries. In this example, we will be using putty.exe, downloaded from: here.
Firstly, add a new code section to the executable using a PE editor such as LordPE. Remember to allocate enough space. In the example below, a size of 1000 bytes is allocated to the .NewSec section. Save the modified binary and try running it. You should get an error and the application crashes.
Next, open the modified binary in a hex editor and allocate the ‘1000’ byte value at the end of the file. Save the binary, and you should notice that the application now runs as per normal.
The binary is now ready for ‘backdoor code insertion’. Open the binary in a debugger such as OllyDBG or Immunity, whichever is your preference. Notice the first 5 instructions in the application:
Copy and paste the instructions somewhere, as we will need to refer to this later.
In the debugger, open the ‘memory view’ to view the address of ‘.NewSec’, which we added in the earlier steps. In this case the starting address to the section we created earlier is @ memory address ‘00484000’. We want the code execution of the binary to jump to this address, as this is where we will be placing our shellcode.
Now that we got the starting address of our new code section, we can proceed to modify the instructions. Modify the first instruction of the application to ‘JMP 00484000’.
Double-click the newly modified instruction to move to the ‘.NewSec’ section. You should see a lot of ‘free’ space.
Next, we proceed to add 2 instructions, PUSHAD, PUSHFD to ‘preserve’ the current registers and flags.
Now that we have push the current registers to the stack, we can start adding the shellcode from address ‘00484002’ onwards. The shellcode can be generated using msfpayload. Paste the shellcode as ‘binary paste’ in the debugger from address ‘00484002’ and you are all set. Note the ESP address when the binary execution is at address ‘00484002’. In the below case, it is pointing to ‘0012FF68’. We will need this address to re-align the ESP register to its original position later.
The addresses will vary depending on what shellcode you decided to use. Next, you have to manually step through the pasted code to see which line actually spawns the shell. Opening a netcat listener will greatly help to determine this, and it is usually at a ‘CALL’ instruction. In the below case, the shell is spawned after the ‘CALL EBP’ instruction at the memory address ‘0048411B’. Note the ESP register value at ‘0048411D’ when the binary is executed. In this case, it is pointing to ‘0012FD70’. To re-align the ESP register to its original position, we will have to find the difference, which is ‘0012FF68’ – ‘0012FD70’ and that gives us a value of ‘1F8’. Edit the instruction after ‘CALL EBP’ to ‘ADD ESP,1F8’ in order to align the ESP register. Now that the ESP register is aligned, we can also restore the other registers and flags with the ‘POPFD’ and ‘POPAD’ instruction as shown below. Now to enable the application to function as intended, we need to replace the instructions that were removed at the beginning of the binary. Proceed to do that as shown below.
Save the changes and attempt to run the executable, remembering to setup a netcat listener. You should receive your shell.
In my case, the application did not run as intended although the shell is spawned. After debugging, I realized that the shellcode that was generated by metasploit passed an argument of value ‘-1’ to the ‘WaitForSingleObject’ method which caused the putty program to not run until the shell is terminated. Changing the value of ‘-1’ to ‘0’ does the trick. In my case, replacing 1 instruction in the shell code fixed the issue.
Now you have a putty.exe binary that has a ‘backdoor’ shellcode that still functions as intended. Most AVs will detect this though, so it really depends on how you try to ‘obfuscate’ the shellcode, as the ones generated by metasploit are detected by most AV software out there.
Summarized Application Flow
Application flow ---------------- [Original Code] [Original Code] .... [Original Code] [Code Cave with PUSHAD; PUSHFD] [Start of MSFVenom code] // Set a break-point here and note the value of ESP. 0012FD70 in this example. [End of MSFVenom code; ending will CALL EBP] [Address to align the offset of ESP] // Set a break-point, hit it and note the ESP register, example 0012FF68. So, 0012FF68–0012FD70 and that gives us an offset of 1F8. So for this example you will change this instruction to ADD ESP, 1F8. [POPFD] [POPAD] [Restored instructions that were overwritten at entry point]