Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to understand a format string exploitation code

Tags:

c

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, i.e, 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.

like image 855
Terminal Avatar asked Aug 03 '11 17:08

Terminal


People also ask

What do you understand by format string vulnerabilities?

A format string vulnerability is a bug where user input is passed as the format argument to printf , scanf , or another function in that family. The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf .

What can be the impact of a format string vulnerability?

This could lead to overwriting sensitive variables such as passwords and username of the program and lead to a complete compromise. Attackers can also make use of this vulnerability to perform arbitrary writes in the dtors table of the program and make the program execute malicious code.

Why does a format string attack occur?

The attack could be executed when the application doesn't properly validate the submitted input. In this case, if a Format String parameter, like %x, is inserted into the posted data, the string is parsed by the Format Function, and the conversion specified in the parameters is executed.

What is format string error?

A Format String error occurs when the submitted data of an input string is evaluated as a command by the application.


2 Answers

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, ...

like image 87
ninjalj Avatar answered Sep 19 '22 08:09

ninjalj


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.

like image 26
BlackBear Avatar answered Sep 19 '22 08:09

BlackBear