In the book in question the program fmt_vuln.c (you can find it here on github) suffers from a format string vulnerability that the author decided to exploit to explain .dtors
hacking and in this case overwriting __DTOR_END__
address with the address of a shellcode environment variable. On page 183 however he writes:
"The ability to overwrite arbitrary memory addresses implies the ability to control the execution flow of the program. One option is to overwrite the return address of the most recent stack frame, as done with the stack-based overflows.[...]".
As said before, he did not choose this option, but I decided to test my understanding of exploitation and try myself. The conclusion is of course that I don't understand a thing. This is the disassembly from gdb (I run everything on the book companion Ubuntu inside a VM):
(gdb) disass main
Dump of assembler code for function main:
0x080483e4 <main+0>: push ebp
0x080483e5 <main+1>: mov ebp,esp
0x080483e7 <main+3>: sub esp,0x418
0x080483ed <main+9>: and esp,0xfffffff0
0x080483f0 <main+12>: mov eax,0x0
0x080483f5 <main+17>: sub esp,eax
0x080483f7 <main+19>: cmp DWORD PTR [ebp+8],0x1
0x080483fb <main+23>: jg 0x804841e <main+58>
0x080483fd <main+25>: mov eax,DWORD PTR [ebp+12]
0x08048400 <main+28>: mov eax,DWORD PTR [eax]
0x08048402 <main+30>: mov DWORD PTR [esp+4],eax
0x08048406 <main+34>: mov DWORD PTR [esp],0x80485c0
0x0804840d <main+41>: call 0x80482f8 <printf@plt>
0x08048412 <main+46>: mov DWORD PTR [esp],0x0
0x08048419 <main+53>: call 0x8048308 <exit@plt>
0x0804841e <main+58>: mov eax,DWORD PTR [ebp+12]
0x08048421 <main+61>: add eax,0x4
0x08048424 <main+64>: mov eax,DWORD PTR [eax]
0x08048426 <main+66>: mov DWORD PTR [esp+4],eax
0x0804842a <main+70>: lea eax,[ebp-0x408]
0x08048430 <main+76>: mov DWORD PTR [esp],eax
0x08048433 <main+79>: call 0x80482e8 <strcpy@plt>
---Type <return> to continue, or q <return> to quit---
0x08048438 <main+84>: mov DWORD PTR [esp],0x80485e0
0x0804843f <main+91>: call 0x80482f8 <printf@plt>
0x08048444 <main+96>: lea eax,[ebp-0x408]
0x0804844a <main+102>: mov DWORD PTR [esp+4],eax
0x0804844e <main+106>: mov DWORD PTR [esp],0x804860f
0x08048455 <main+113>: call 0x80482f8 <printf@plt>
0x0804845a <main+118>: mov DWORD PTR [esp],0x8048620
0x08048461 <main+125>: call 0x80482f8 <printf@plt>
0x08048466 <main+130>: lea eax,[ebp-0x408]
0x0804846c <main+136>: mov DWORD PTR [esp],eax
0x0804846f <main+139>: call 0x80482f8 <printf@plt>
0x08048474 <main+144>: mov DWORD PTR [esp],0x8048650
0x0804847b <main+151>: call 0x80482f8 <printf@plt>
0x08048480 <main+156>: mov eax,ds:0x8049794
0x08048485 <main+161>: mov DWORD PTR [esp+12],eax
0x08048489 <main+165>: mov eax,ds:0x8049794
0x0804848e <main+170>: mov DWORD PTR [esp+8],eax
0x08048492 <main+174>: mov DWORD PTR [esp+4],0x8049794
0x0804849a <main+182>: mov DWORD PTR [esp],0x8048660
0x080484a1 <main+189>: call 0x80482f8 <printf@plt>
0x080484a6 <main+194>: mov DWORD PTR [esp],0x0
0x080484ad <main+201>: call 0x8048308 <exit@plt>
End of assembler dump.
I expected to find the return address 0x08048474
somewhere around esp (it was my impression that the return addresses were at StackPointer + 4 for 32-bit systems) so as done previously in the book, (and this is only one example to show you what I was thinking, I did search basically everywhere esp related) something like
Starting program: /home/hack/booksrc/fmt_vuln hello
Breakpoint 6, main (argc=2, argv=0xbffff8c4) at fmt_vuln.c:9
9 if(argc < 2) {
(gdb) c
Continuing.
The right way to print user-controlled input:
hello
The wrong way to print user-controlled input:
Breakpoint 4, main (argc=2, argv=0xbffff8c4) at fmt_vuln.c:22
22 printf("\n");
(gdb) x/32xw $esp
0xbffff420: 0xbffff430 0xbffff430 0xb7fe75fc 0x00000000
0xbffff430: 0x6c6c6568 0x0000006f 0x00000000 0xb7fe7468
0xbffff440: 0xb7fe7298 0xb7e996c0 0x0000000f 0xbffff460
0xbffff450: 0xb7ffa715 0x00000008 0x00000088 0xb8000ff4
0xbffff460: 0xbffff470 0xb7fe75fc 0xb7fe7298 0xb7fff434
0xbffff470: 0xbffff48c 0xb7ff6fa8 0x00000011 0x00000008
0xbffff480: 0xb7fe7468 0xb7e996c0 0xb7e99000 0x00000001
0xbffff490: 0xbffff4c0 0xbffff4dc 0x00000000 0xb7e9968c
should have shown 0x08048474
. Not only this is not the case, but I "x/anylenghtxw $esp - manyvalues
"-ed (and $ebp too) literally at any single single point of the execution stepping all the program and 0x08048474
just isn't there. I then tried other things, but in the end I simply could not figure out the memory location where eip gets the address. So I began reading other things and now I am even more confused because I am starting to think that it depends on the fact that printf@plt
is in .plt
and i don't know how shared library works. Or another option is that the
the return address in the most recent stack frame
is the return addres of main because (I'm not sure) there is only the main stack frame (again my understanding of stack frames is nothing more specific than a section on the stack where you put parameters, variables, and the return address).
So I have two questions: where is 0x08048474
(if that's the right return address) and how should have I proceded to find it?
User contributions licensed under CC BY-SA 3.0