Due to ASLR, you may notice the first half of memory address (e.g.: 014A1234) will change everytime when you start Immunity debugger. Please adjust your memory address accordingly.

What You Need


To modify a Windows EXE file and save an altered version containing Trojan code in a new PE section without breaking the program.


Task 1: Add a Section with LordPE

Duplicate putty.exe and change the file name to putty-mod1.exe

Use LordPE to add new section to putty-mod1.exe For details, please refer to task 1 in

Please note the ROffset of new section is BA000.

Task 2: Redirecting Code Execution with Immunity Debugger

In Immunity, open putty-mod1.exe.

Using Immunity Debugger to Examine the NewSec Section. Go to View > Memory.

It shows the memory layout of putty. As outlined in blue in the image below, the NewSec section begins at address 0x014A3000.

Please right click the section and choose Dump in CPU as shown below.

You will be redirected back to CPU window. Please note program entry point is 0x01477FD6 (CALL putty-mo.01478265)

Double click CALL putty-mo.01478265 and change it to CALL 014A3000 (The starting address of the new section)

Right click 01477FD6 again and go to Copy to execute > All Modifications

A new window pops up, right-click in the new window and click Save file.

Save the file with file name putty-mod2.exe

Task 3: Insert code into new section

You need to insert the following assembly in the new section.

Assembly Code Usage
To preserve the register/flag values before shellcode execution
Shellcode generated by msfvenom Shellcode generated by msfvenom
Align Stack (e.g.: ADD ESP,200) ESP is changed by shell code.
Align stack value for POPFD and POPAD.


To restore register/flag values before shellcode execution

CALL putty-mo.01478265 (The original assembly begin replaced)
JMP 01477FDB

Restore program flow

PUSHAD, PUSHFD and Shellcode

Generate your favourite shellcode using msfvenom. If you generate reverse shell shellcode, please setup handler on your "attacker" machine.

Go to offset BA000 (ROffset of new section) by go to View > Goto

Overwrite the data with 609C[Your shellcode] starting from offset BA000.

For example:


Save the file as putty-mod3.exe.

Task 4: Align Stack

Back to Immunity Debugger and open putty-mod3.exe.

If you generate reverse shell shellcode, please setup handler on your "attacker" machine.

This next part can be tricky, but what we essentially want to do is start to step through the newly introduced code (by pressing F7), however stop and make note of the value of ESP after our PUSHFD, and as always, save it for later. (i.e.: 0029FD74)

Please also note that PUSHAD and PUSHFD push register value and Flag value to stack respectively.

Please scroll down to end of shellcode (or you can leverage search function to search last few bytes of your shellcode)

Toggle breakpoint just after the shellcode. Choose Yes when you see Suspicious breakpoint popup.

Continue the program execution and hit the breakpoint.

Please connect/disconnect the reverse shell and let the shellcode being exeucted.

Note the ESP is now 0029FB74. The ESP before shellcode is 0029FD74.

We have two ESP values. We will use them to restore our stack and access our saved values. To do this though, we will first need to work out the difference between the two values. (The difference between 0029FB74 to 0029FD74 is 0x200)

We need to restore (or re-align) the ESP value to original ESP value before shellcode. To do this, we need to add ADD  ESP, 200 just after the shellcode.

Double click code in address 01433146 and change it to ADD ESP, 200.

Press F7 to step over the ADD ESP, 200. We verified the ESP has been restored to 0029FD74.

Task 5: POPFD and POPAD

We need to restore the registers and flags to before shellcode state. To do this, we need to add POPFD and POPAD.

Add POPFD and POPAD after ADD ESP,200 as shown below.

Task 6: Restore Replaced Code and Original Program Flow

To restore the original program flow. You need to insert the following code in the new section. We need to add the replaced code (CALL putty-mo.01478265) and jump to the instruction after the original replaced instruction.

  • CALL putty-mo.01478265
  • JMP 01477FDB

You may notice first half of memory address is changed from 0147 to 0140 in screenshot. Due to ASLR, the memory will be different for each Immunity debugger session. You need to adjust your memory address accordingly.

Highlight the new add code starting from ADD ESP,200 to JMP putty-mo.01477FDB.

Right click the selection and go to Copy to execute > Selection.

A new window pops up, right-click in the new window and click Save file. Save the file with name putty-mod4.exe.

Please exit Immunity debugger.

Task 7: Fix the "Continue after exiting shell" Problem

You can test your shellcode outside Immunity debugger. You will notice you need to disconnect the shell in order to continue the program execution.

It is due to msfvenom payload calling WaitForSingleObject with parameter dwMilliseconds = -1 (Infinite wait). For WaitForSingleObject details, please refer to

In order to resolve this problem, you need to make sure the parameter value dwMilliseconds=0 by replacing the instruction DEC ESI with NOP.

In Immunity debugger, open putty-mod4.exe. (Please start a new Immunity debugger session if you didn't exit Immunity debugger in previous step)

The DEC ESI instruction appears around 10~20 assembly codes above ADD ESP,200.

If you want to locate WaitForSingleObject call, you may refer to this website

You can also step through the code to inspect WaitForSingleObject call.

Right click code change and go to Copy to execute > Selection.

A new window pops up, right-click in the new window and click Save file. Save the file with file name putty-mod5.exe.

Final Testing

Test your putty-mod5.exe outside Immunity Debugger and the Putty will be executed normally and reverse shell has been established.