2

This is my first post, and I am new to assembly and debugging, so bear with me please.

I was trying to inject some code (a little call to MessageBoxA) into the Windows 7 Notepad executable. However, I ran into the problem of addresses. First, I opened up the exe in OllyDbg, then I went to the line that contains the ASCII text of “notepad.pdb.” Then I put an ASCII string below that (For example, “INJECTED NOTEPAD”). Next, below that, I entered this asm code:

PUSH 0
PUSH address_of_ASCII_string ; In this case, 00A6B668C
PUSH address_of_ASCII_string ; In this case, 00A6B668C
PUSH 0
CALL MessageBoxA

Next, I went to the first line of code in the program (simply by right clicking and pressing Go to Origin (or just press * on the number pad)) Then I replaced the first line with a JMP instruction to the address of the first PUSH 0 in my injected code. Then, I put the instruction that I replaced at the end of my injected code. After that, I put a JMP instruction to the line of code after my JMP instruction that jumps to my injected code (yes, I just described a codecave or sort of). It all works fine when I run it. However, when I save the modified code to a new executable and run it with OllyDbg again, it doesn’t work. When I try to reference the ASCII string that I put in, the address is completely wrong. Example is in pictures below:

As you can see, I push the string onto the stack, but when I reload the modified program into the debugger again, the address of the string changes, but my code doesn’t. So when I call the MessageBoxA function, it errors out because I have loaded the wrong address for the Text and Caption arguments. How do I fix this?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
DD314
  • 59
  • 1
  • 5
  • 1
    Well yeah, you are trying to use absolute addresses when you should be using relative addresses. The base address of the executable is randomized each time the process is started, so a fixed address will not be valid across multiple invocations. (Also: welcome to Stack Overflow! Thanks for a well-asked and nicely-presented question.) – Cody Gray - on strike Dec 23 '16 at 16:03
  • Thank you. How would I use a relative address then? – DD314 Dec 23 '16 at 16:10
  • I be say that you try not inject code but patch exe. you of course need use not relative but absolute addresses - but all absolute addresses must be described in `.relocs` section. one way do your patch working - disable relocs on exe. for this you need set flag `IMAGE_FILE_RELOCS_STRIPPED` in `IMAGE_FILE_HEADER.Characteristics` - after this exe always will be loaded on constant address, and possible hardcode absolute addresses – RbMm Dec 23 '16 at 16:24
  • I tried RbMm's suggestion and it worked! I simply opened notepad up in CFF Explorer and went to the "File Header" section. Then I edited the "Characteristics" entry by checking the "Relocation info stripped from file" box. I assume that this makes the executable use absolute addressing instead of using the base address right? Will doing this modification break anything in a nor executable? It doesn't break notepad, but my goal is to attach some code to explorer.exe. I don't know if this would break explorer or not. However, it works for note pad. Thanks. – DD314 Dec 23 '16 at 16:48
  • Any other suggestions? – DD314 Dec 23 '16 at 16:50
  • @DD314 - "I assume that this makes the executable use absolute addressing instead of using the base address right?" - no. you mistake. this disable `ASLR`. exe will be always load at self base address. this is nothing break in any exe. but you way of patching.. – RbMm Dec 23 '16 at 18:29

1 Answers1

5

What you've encountered are the effects of ASLR. In short, this means that an executable running on an OS (in this example Windows) will not have the same base address across multiple executions.

So there are a few ways to inject your code into another binary, I will address 2 here and I will also guess (after reading the comments) that you are trying to patch the binary that's on the disk.

  1. Patching the binary on disk:

    a. The first way to go about this is strip the relocation table from the PE. I would definitely not recommend this way as it may crash the executable in the future in case it doesn't get loaded into its favored base address (OptionalHeader.ImageBase) which is the default that all instructions needing relocation will use as a base to add an offset to.

    Let's say you have a string at offset 0x600 from the image base, in case the executable is mapped to its preferred base address (usually 0x00400000) the string will be held at address 0x00400000. The way your compiler will link the file will be with an address of 0x00400000 + 0x600 so 0x00400600. Then what happens when an executable is loaded into a different base address? In that case the windows executable loader will add the offset of the base address (effectively the one mapped minus the preferred base address) to each relocation entry (the example above will need one). So in case the executable will be loaded into 0x00500000 the loader will add 0x00100000 to that relocation entry leading to the absolute address of 0x00500600.

    b. The second way to go would be to add a relocation entry to the binary. This way, as opposed to the way described in (a) you will not harm the binary and will only add a relocation entry, which upon loading the executable the loader will change the address to the correct one (if you've added a correct entry).

    c. Write position independent code and patch the binary using this code. Example:

    sub     esp, 10*4
    mov     byte [esp], 0x68 ; 'h'
    mov     byte [esp + 1], 0x69 ; 'i'
    mov     byte [esp + 2], 0x00 ; null byte
    mov     byte [esp + 3], 0x79 ; 'y'
    mov     byte [esp + 4], 0x6f ; 'o'
    mov     byte [esp + 5], 0x75 ; 'u'
    mov     byte [esp + 6], 0x00 ; null byte
    mov     eax, esp
    push    0
    push    eax
    add     eax, 3
    push    eax
    push    0
    call    [MessageBoxA]  
    

    This code will write the 2 needed strings to the stack and push the pointers to the strings on the stack, this way the code doesn't need any relocation since its a piece of poisiton independent code.

  2. Patching the binary in memory:

    a. Position independent code (see above)

    b. Use VirtualAllocEx, this API will, after calling it, return an address to which you can write, this way you simply have the mapped address in memory and know where and how to inject your code.

papadp
  • 891
  • 8
  • 14
  • Thank you for your very good answer. I am either going to use option C or B. However, how would I add a relocation entry to the binary? I have no clue how to do that. – DD314 Dec 23 '16 at 18:56
  • I wouldn't recommend this is as it's not the most trivial way. In short, you would find the relocation directory. In the relocation directory you will find relocation tables for each section/1kb in the executable you will find a table populated by entries, each entry telling you the offset from the start of the specific section/1kb chunk and the relocation type. You can find the nitty gritty specifics here: https://msdn.microsoft.com/en-us/library/ms809762.aspx – papadp Dec 24 '16 at 11:43