-
Notifications
You must be signed in to change notification settings - Fork 42
Detecting a classic buffer overflow
Wei Ming Khoo edited this page Oct 25, 2018
·
9 revisions
A classical example would be (see also misprint.c):
/* misprint.c */
#include <stdio.h>
#include <stdlib.h>
#include "taintgrind.h"
void hello_function()
{
printf("INFO: Hello World!\n");
}
/*
* $ VAL=`readelf -s misprint | grep secret_function | awk '{print $2}'` && printf "%d\n" 0x$VAL
*/
void secret_function()
{
printf("INFO: Oh no! The application is compromised!\n");
}
int main(int argc, char** argv)
{
int i;
int val;
int iter;
int buffer[10];
int canary;
void (*func)(void);
if (argc != 3) { return(1); }
iter = atoi(argv[1]);
val = atoi(argv[2]);
TNT_TAINT(&val, sizeof(val));
/* It should print Hello World! */
func = &hello_function;
//canary = UNINTIALIZED;
/* If iter > 10 then a buffer overflow will occur */
for (i = 0; i < iter; i++)
buffer[i] = val;
/*
* ... if the buffer overflow is "severe enough",
* it may overwrite the function pointer with user data,
* e.g. a pointer to the secret function
*/
func();
return(0);
}
Compile the application:
$ cc -g -O0 -Ipath/to/taintgrind -fno-inline -fno-omit-frame-pointer -fno-stack-protector -m32 misprint.c -o misprint
or run
make check
To compile taintgrind/tests/misprint.c
Run it with "safe" parameters, it simply prints Hello World.
$ ./misprint 1 1
INFO: Hello World!
Run it with parameters that lead to a buffer overrun attack (you may have to find the pointer to the secret function):
$ VAL=`readelf -s misprint | grep secret_function | awk '{print $2}'` && printf "%d\n" 0x$VAL
134513809
$ ./misprint 12 134513809
INFO: Oh no! The application is compromised!
Running this test case with
valgrind --tool=taintgrind -- taintgrind/tests/misprint 12 134513924
gives this output
0x8048615: main (misprint.c:45) | STle(t59) = t55 | Store | 0x8048504 | canary <- t55_448
...
0x8048623: main (misprint.c:44) | t14 = LDle:I32(t12) | Load | 0x8048504 | t14_7979 <- val
...
0x8048615: main (misprint.c:45) | STle(t18) = t14 | Store | 0x8048504 | func <- t14_7979
...
0x8048625: main (misprint.c:52) | t5 = LDle:I32(t3) | Load | 0x8048504 | t5_11954 <- func
0x8048628: main (misprint.c:52) | JMP t5_11953 | Jmp | 0x8048504 | t5_11954
The jump target at line 52 is tainted. Taint flows from value to func to the jump.
Generate the taint graph by running:
valgrind --tool=taintgrind -- taintgrind/tests/misprint 12 134513924 2>&1 | python taintgrind/log2dot.py | tee misprint.dot
dot -Tpng misprint.dot -o misprint.png
The tainted jump is highlighted in red.
Credit to Giuseppe Di Guglielmo for the test case