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?