I have a function that looks like so:
int bof(char *str)
{
char buffer[12];
strcpy(buffer, str);
return 1;
}
I am attempting to overwrite its return address. I have found that I can do so by using, for instance, memcpy(buffer+24, "\x15\xf1\xff\xbf", 4). What I do not understand is why I need to access buffer + 24. My understanding of the C memory model tells me that the stack when this function is executed should look like
bottom of top of
memory memory
buffer(12) sfp(4) ret(4) str(4)
<------ [ ][ ][ ][ ] --->
top of bottom of
stack stack
This would suggest that I should the ret address should begin at buffer+16. Where are the extra 8 bytes coming in?
By the way, I am running this on a 32-bit system.
Check the ISO C 99 and earlier standards, and you'll see there is no such thing as a C memory model. Every compiler is free to use whatever model it likes to meet the functional spec. One easy example is that the compiler may use or omit a frame pointer. It can also allocate space for a return value or use a register.
When I compile this code on my machine, I get
_bof:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl 8(%ebp), %eax
movl %eax, 4(%esp)
leal -20(%ebp), %eax
movl %eax, (%esp)
call _strcpy
movl $1, %eax
leave
ret
The leal instruction is computing the buffer start location at bp-20. After the prologue, the stack frame looks like:
[ bp+8: str ] [bp+4: rtn address ] [bp: saved bp] [ bp-20: buf ] ...
So it looks like you would have to write 28 bytes to change the return address here. My guess is that the compiler is trying to align stack frames on paragraph boundaries. The full frame here including the strcpy arg setup is 48 bytes, which is 3 paragraphs. Paragraph alignment helps bus and cache performance.
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