3

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.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
Kvothe
  • 467
  • 4
  • 13
  • 2
    This question might be a good reference: [Buffer Overflow Attack](http://stackoverflow.com/questions/7344226/buffer-overflow-attack) – Mysticial Nov 06 '12 at 04:46
  • 1
    Just use the debugger, and answer your own question. Which might almost certainly depend (at least in part) on your OS, compiler and compiler version :) – paulsm4 Nov 06 '12 at 04:52
  • 3
    Compilers are free to add any paddings – SwiftMango Nov 06 '12 at 04:53
  • 5
    *"My understanding of the C memory model tells me that the stack when this function is executed should look like.."* - The C standard says nothing of a stack layout, so I'm not sure what you're referring to. These are implementation defined (there is no requirement that a stack is used in the first place) and dependent upon the calling convention. – Ed S. Nov 06 '12 at 05:05
  • 1
    Why? Why? Why? Let the OS/Compiler do its job - do you ask why the person in Starbucks sprinkles coco using the left hand or the right. Who gives a .... – Ed Heal Nov 06 '12 at 07:08
  • @Kvothe - What are you trying to achieve? – Ed Heal Nov 06 '12 at 07:24

2 Answers2

3

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.

Gene
  • 46,253
  • 4
  • 58
  • 96
2

This is not C memory model or C function call stack layout. It is just an implementation you know for a specific compiler and hardware architecture. In ARM 32-bit CPU, the function call arguments 1~4 does not push to the stack, it uses r0~r3 to pass arguments, and then push other arguments to the stack if you have arguments more than 4. The function return address might not also necessary push to the stack because there is a special register LR to keep the return address.

jclin
  • 2,449
  • 1
  • 21
  • 27