I've been working on Buffer-Overflow Vulnerability Lab from SEED (Lab Description and Tasks). The environment is Ubuntu 12.04 32 bit. Please consider the following code:
/* stack.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[24];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
I found that in order to overwrite the return address we would have to overwrite the array starting from 36th place because we would have to jump 24 bytes (the size of the array) plus 4 bytes (for the previous frame pointer) plus 8 bytes for the some compiler data (not specified for what purpose). I calculated this with the difference of the EBP and the address of the buffer (using the debugger).
I realized that in order to jump to the malicious code we can jump to any address on the NOP sled. For a sufficiently large value the attack succeeded. I tried to calculate the minimum possible address. The logic (and the lecturer) said it was EBP + 8 because we wanted to pass both the return address and the previous frame pointer (4 bytes each). Unfortunately the attack did not succeed when I tried to run it with that value. I found through an exhaustive search that the minimum possible address is 0xBFFFF168
, which is EBP + 48, and I do not understand why.
I even tried to run the attack without the NOP sled and encountered problems.
Can someone please explain? Below there is a description of the stack before and after the overrun and some additional values.
Thank you very much in advance.
14 strcpy(buffer, str);
(gdb) x/20x $sp
0xbffff100: 0x0804b008 0xbffff157 0x00000205 0xb7e34374
0xbffff110: 0xb7fc4ff4 0xb7fc4ff4 0x00000000 0xb7e1f900
0xbffff120: 0xbffff368 0xb7ff26b0 0x0804b008 0xb7fc4ff4
0xbffff130: 0x00000000 0x00000000 0xbffff368 0x080484ff
0xbffff140: 0xbffff157 0x00000001 0x00000205 0x0804b008
(gdb) next
16 return 1;
(gdb) x/20x $sp
0xbffff100: 0xbffff118 0xbffff157 0x00000205 0xb7e34374
0xbffff110: 0xb7fc4ff4 0xb7fc4ff4 0x90909090 0x90909090
0xbffff120: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff130: 0x90909090 0x90909090 0x90909090 0xbffff168
0xbffff140: 0x90909090 0x90909090 0x90909090 0x90909090
(gdb) p &buffer
$1 = (char (*)[24]) 0xbffff118
(gdb) p $ebp
$2 = (void *) 0xbffff138
(gdb) p $sp
$3 = (void *) 0xbffff100