cassemblystack-overflowexploitpwntools

Unable to inject valid instruction pointer during exploit


I am trying to exploit a given program and I can't figure out what I doing wrong. Long story short I manage to inject code to overwrite the RIP. This means that I should be able to redirect the code execution, but the problem is, I get SIGSEGV. Do I have to design the injected stack in a special way in order to not get SIGSEGV?

My game plan is to exploit the function mainloop and change the return adress. The stack for the function mainloop has the following values:

0000| 0x7fffffffdff0 --> 0xa7400ffffe010 
0008| 0x7fffffffdff8 --> 0xf423f55758260 
0016| 0x7fffffffe000 --> 0x7fffffffe010 --> 0x5555555550b0 (<__libc_csu_init>:  push   r15)
0024| 0x7fffffffe008 --> 0x5555555550a4 (<main+66>: mov    eax,0x0)

So the return adress is stored at 0x7fffffffe008 and I have managed to overwrite that value with the adress pointing to the code that I want to execute. In this case the adress 0x555555554e6e.

The backtrace of the program is as follows:

#6  0x0000555555554fab in mainloop ()
#7  0x00005555555550a4 in main ()
#8  0x00007ffff7e1109b in __libc_start_main (main=0x555555555062 <main>, argc=0x1, argv=0x7fffffffe0f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
stack_end=0x7fffffffe0e8) at ../csu/libc-start.c:308
#9  0x000055555555486a in _start () 

As you can see, when I exit mainloop I will be returned to main, and when I quit main I go to a bunch of libc-functions so that the program exits cleanly (?).

So what happens when I run my exploit-code? This:

0000| 0x7ffe1b3d4150 --> 0x424142001b3d4170 
0008| 0x7ffe1b3d4158 ("ABABABABABABABABnNUUUU")
0016| 0x7ffe1b3d4160 ("ABABABABnNUUUU")
0024| 0x7ffe1b3d4168 --> 0x555555554e6e ('nNUUUU')
0032| 0x7ffe1b3d4170 --> 0x55a34784000a 
0040| 0x7ffe1b3d4178 --> 0x7f7c156c409b (<__libc_start_main+235>:      mov    edi,eax)
0048| 0x7ffe1b3d4180 --> 0x0 
0056| 0x7ffe1b3d4188 --> 0x7ffe1b3d4258 --> 0x7ffe1b3d5474 ("./device")

What you are seeing is the stack. I added some bytes so you can get more context. But I think I managed to hit the right size of the filler for my exploit. I have managed to change the value at byte 24.

But my PEDA/GDB doesn't seem to regard that value as a instruction pointer, which is weird. It seems to regard it as a C-string(?). The backtrace looks like this:

#6  0x000055a347849fab in mainloop ()
#7  0x0000555555554e6e in ?? ()
#8  0x000055a34784000a in ?? ()
#9  0x00007f7c156c409b in __libc_start_main (main=0x55a34784a062 <main>, argc=0x1, argv=0x7ffe1b3d4258, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
stack_end=0x7ffe1b3d4248) at ../csu/libc-start.c:308
#10 0x000055a34784986a in _start () 

And when I exit mainloop I get the following in PEDA/GDB:

Stopped reason: SIGSEGV
0x0000555555554e6e in ?? ()

And if I run the command i f in GDB I get:

Stack level 0, frame at 0x7ffe1b3d4178:
 rip = 0x555555554e6e; saved rip = 0x55a34784000a
 called by frame at 0x7ffe1b3d4180
 Arglist at 0x7ffe1b3d4168, args: 
  Locals at 0x7ffe1b3d4168, Previous frame's sp is 0x7ffe1b3d4178
 Saved registers:
  rip at 0x7ffe1b3d4170 

At adress 0x0000555555554e6e the program executes the following ASM:

0x0000555555554e6e <+172>:  lea    rdi,[rip+0x20126b]        #    0x5555557560e0 <flag2>

So I seem to have the right RIP, but that's about it. Guys, what's going on?


Solution

  • GDB (by default) disables ASLR when you start a program from within GDB. In a PIE executable, static code/data addresses are randomized. Injecting a return address only works if you know the right absolute address.

    But apparently you're sometimes starting your program outside GDB, where addresses aren't the same every time. This obviously leads to a segfault, and your question doesn't show disassembly from the actual 0x0000555555554e6e in the actual process that segfaulted, contrary to what you're claimed / assumed.

    (GCC making PIE executables by default is a recent thing on Linux; if you were following an old tutorial, it might have assumed that the executable itself was position-dependent, and only libraries + stack would be ASLRed. 32-bit absolute addresses no longer allowed in x86-64 Linux?)

    See Disable randomization of memory addresses for a system-wide or per-process way to disable ASLR, or build non-PIE executables.