Static code injection (PE)

In general

  1. Use either available space in an existing section or add a new one.
  2. Add your code either directly or load a dll that contains your code.

By example

$ .\crackme.exe
Can you add another output?
  1. Let’s add a new PE section (with CEF Explorer)
    1. Open the PE file
    2. Click on ‘Section Header’ -> Right click -> Click on ‘Add Section (Empty Space)’ -> Enter size -> Click on ‘OK’
    3. Double click on the ‘Name’ cell of the new row (section) to enter a name
    4. Click on new row (section) -> Right click -> Click on ‘Change Section Flags’ -> Enable: is executable/readable/writeable, contains code/un-/initialized data
    5. Save (overwrite) the PE file

    Hint: If the section isn’t empty (like in my case) use a hex editor to make it empty (…0x00…).

  2. Let’s detour the code (with Cutter/Radare2)
    1. Our new section starts at 0x00412000. So let’s add a new string there.

                 | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F |
                 |-------------------------------------------------------------------------------------------------|
      0x00412000 | 59 65 73 20 49 20 63 61 6e 2c 20 63 61 75 73 65 20 49 27 6d 20 61 20 70 72 6f 2e 00 00 00 00 00 | Yes I can, cause I'm a pro.\x00\x00\x00\x00\x00
      0x00412020 | 00 00 00 ...
      
    2. Let’s modify the main function to jump behind the new string.

      36: int main (int argc, char **argv, char **envp);
      0x00401550      push    rbp
      0x00401551      mov     rbp, rsp
      0x00401554      sub     rsp, 0x20
      0x00401558      call    __main     ; sym.__main
      0x0040155d      lea     rcx, str.Can_you_add_another_output ; section..rdata
                                         ; 0x404000 ; const char *s
      0x00401564      call    puts       ; sym.puts ; int puts(const char *s)
      0x00401569      mov     eax, 0
      0x0040156e      add     rsp, 0x20
      0x00401572      pop     rbp
      0x00401573      ret
      

      Replace ‘mov eax, 0’ with ‘jmp 0x41201d’. Both instructions consume the same amount of bytes. So we don’t have to add ‘nop’ instructions.

    3. Let’s print out the new string, excecute the replaced instruction and jump back.

      0x0041201d      lea rcx, 0x412000
      0x00412024      call puts          ; sym.puts ; int puts(const char *s)
      0x00412029      mov eax, 0
      0x0041202e      jmp 0x40156e       ; sym.main+0x1e
      
    $ .\crackme.exe
    Can you add another output?
    Yes I can, cause I'm a pro.