Finding frame return address to exploit format string vulnerability (Hacking The Art of Epxloitation, fmt_vuln)

1

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?

c
linux
format-string
stack-frame
asked on Stack Overflow Oct 16, 2020 by user12786599

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0