Search code examples
cgdbshellcode

Overwriting the stored return address on the stack doesn't work


I'm trying to take control of a C program's execution by overwriting the stored return address (saved eip) on the stack:

(gdb) info frame
Stack level 0, frame at 0xbffff550:
 eip = 0x8048831 in main (6.c:52); saved eip = 0xbffffdef
 source language c.
 Arglist at 0xbffff538, args: argc=6, argv=0xbffff5e4
 Locals at 0xbffff538, Previous frame's sp is 0xbffff550
 Saved registers:
  ebx at 0xbffff534, ebp at 0xbffff538, eip at 0xbffff54c

The value 0xbffffdef is the address of a "Hello, world!" shellcode which has been assembled, checked for any null bytes and put in an environment variable SHELLCODE:

(gdb) x/s *((char **)environ + 7)
0xbffffdef: "SHELLCODE=\353\023Y1\300\260\004\061\333C1Ҳ\017̀\260\001K̀\350\350\377\377\377Hello, world!\n\r"

Unfortunately the program fails to print the expected greeting:

Program received signal SIGSEGV, Segmentation fault.
0xbffffdfd in ?? ()

Why did it crash and how to solve the problem?

Notes:

gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
// program was compiled with the following flags:
-m32 -fno-stack-protector -z execstack -fno-PIE -no-pie -g

program source: link


Solution

  • Credits to @Nate Eldredge

    The reason behind this specific crash is the incorrect return address 0xbffffdef. The location of the environment variable SHELLCODE actually points to the beginning of the string "SHELLCODE=..."

    (gdb) x/s *((char **)environ + 7)
    0xbffffdef: "SHELLCODE=\353\023Y1\300\260\004\061\333C1Ҳ\017̀\260\001K̀\350\350\377\377\377Hello, world!\n\r"
    

    In order to fix the issue, we have to adjust the address by skipping the first 10 characters and point to the "\353\023Y1\300...":

    0xbffffdef + 0xa = 0xbffffdf9
    

    When overwriting the stored return address with this value 0xbffffdf9, the program is coerced into greeting the world:

    (gdb) info frame
    Stack level 0, frame at 0xbffff550:
     eip = 0x8048831 in main (6.c:52); saved eip = 0xbffffdf9
     source language c.
     Arglist at 0xbffff538, args: argc=6, argv=0xbffff5e4
     Locals at 0xbffff538, Previous frame's sp is 0xbffff550
     Saved registers:
      ebx at 0xbffff534, ebp at 0xbffff538, eip at 0xbffff54c
    (gdb) cont
    Continuing.
    Hello, world!
    [Inferior 1 (process 28591) exited normally]