简体   繁体   中英

Unable to understand a format string exploitation code

I came across this code showing format string exploitation while reading this article.

#include <stdio.h>

int main(void)
{
char secret[]="hack.se is lame";
char buffer[512];
char target[512];

printf("secret = %pn",&secret);

fgets(buffer,512,stdin);
snprintf(target,512,buffer);
printf("%s",target);
}

Executing it with following input

[root@knark]$ ./a.out
secret = 0xbffffc68
AAAA%x %x %x %x %x %x %x //Input given
AAAA4013fe20 0 0 0 41414141 33313034 30326566
- [root@knark]$ 

What I understand till now is the sequence of %x 's will keep on printing the values at addresses above current %esp (I'm assuming that stack is growing downwards towards lower address).

What I'm unable to understand is the input given is stored in buffer array which can't be less than 512 bytes away from current %esp . So, how can the output contain 41414141 (the hex representation of AAAA ) just after the 4 %x , ie, just above the 4 addresses of current %esp . I tried hard to stare at assembly code too but I think I couldn't follow the manipulation of strings on stack.

On entry to snprintf , the stack has the following:

0xbfd257d0:     0xxxxxxxxx      0xxxxxxxxx      0xxxxxxxxx      0x080484d5
0xbfd257e0:     0xbfd25800      0x00000200      0xbfd25a00      0x00000000
0xbfd257f0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfd25800:     0x00000000      0x00000040      0xb7f22f2c      0x00000000
0xbfd25810:     0x00000000      0x00000000      0x00000000      0x00000000

0xbfd25800 -> target (initially 0x00000000 0x00000040 ...)
...        -> garbage
0xbfd257e8 -> pointer to buffer
0xbfd257e4 -> 512
0xbfd257e0 -> pointer to target
0xbfd257df -> return address

target gets overwritten with the result of snprintf before snprintf gets to use its words as arguments: It first writes "AAAA" (0x41414141) at 0xbfd25800, then "%x" reads the value at 0xbfd257ec and writes it at 0xbfd25804, ..., then "%x" reads the value at 0xbfd25800 (0x41414141) and writes it at 0xbfd25814, ...

First of all, let's have a look at the stack after calling snprintf():

Reading symbols from /home/blackbear/a.out...done.
(gdb) run
Starting program: /home/blackbear/a.out 
secret = 0xbffff40c
ABCDEF%x %x %x %x %x %x %x

Breakpoint 1, main () at prova.c:13
13      printf("%s",target);
(gdb) x/20x $esp
0xbfffeff0: 0xbffff00c  0x00000200  0xbffff20c  0x00155d7c
0xbffff000: 0x00155d7c  0x000000f0  0x000000f0  0x44434241
0xbffff010: 0x35314645  0x63376435  0x35353120  0x20633764
0xbffff020: 0x66203066  0x34342030  0x32343334  0x33203134
0xbffff030: 0x34313335  0x20353436  0x37333336  0x35333436
(gdb) 

We can actually see, at 0xbffff00c, the string already formatted, so sprintf() wrote right there. We can also see, at 0xbfffeff0, the last argument for snprintf(): target's address, which is actually 0xbffff00c. So I can deduce that strings are saved from the end to the beginning of their allocated space on the stack, as we can also see adding a strcpy():

blackbear@blackbear-laptop:~$ cat prova.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    char secret[]="hack.se is lame";
    char buffer[512];
    char target[512];

    printf("secret = %p\n", &secret);

    strcpy(target, "ABCDEF");   
    fgets(buffer,512,stdin);
    snprintf(target,512,buffer);
    printf("%s",target);
}
blackbear@blackbear-laptop:~$ gcc prova.c -g
prova.c: In function ‘main’:
prova.c:14: warning: format not a string literal and no format arguments
prova.c:14: warning: format not a string literal and no format arguments
blackbear@blackbear-laptop:~$ gdb ./a.out -q
Reading symbols from /home/blackbear/a.out...done.
(gdb) break 13
Breakpoint 1 at 0x8048580: file prova.c, line 13.
(gdb) run
Starting program: /home/blackbear/a.out 
secret = 0xbffff40c

Breakpoint 1, main () at prova.c:13
13      fgets(buffer,512,stdin);
(gdb) x/10x $esp
0xbfffeff0: 0xbffff00c  0x080486bd  0x00000007  0x00155d7c
0xbffff000: 0x00155d7c  0x000000f0  0x000000f0  0x44434241
0xbffff010: 0x00004645  0x00000004
(gdb) 

That's it! In conclusion, we've found the string there because strings are stored on the stack in a reversed way, and the beginning (or the end?) of target is near esp.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM