C函数栈布局 [英] C function stack layout

查看:27
本文介绍了C函数栈布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个看起来像这样的函数:

I have a function that looks like so:

int bof(char *str)
{
    char buffer[12];

    strcpy(buffer, str);

    return 1;
}

我正在尝试覆盖其返回地址.我发现我可以通过使用例如 memcpy(buffer+24, "\x15\xf1\xff\xbf", 4) 来做到这一点.我不明白的是为什么我需要访问 buffer + 24.我对C内存模型的理解告诉我,这个函数执行时的堆栈应该是这样的

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

这表明我应该将 ret 地址从 buffer+16 开始.额外的 8 个字节从何而来?

This would suggest that I should the ret address should begin at buffer+16. Where are the extra 8 bytes coming in?

顺便说一下,我在 32 位系统上运行它.

By the way, I am running this on a 32-bit system.

推荐答案

检查 ISO C 99 和更早的标准,您会发现没有 C 内存模型这样的东西.每个编译器都可以自由使用它喜欢的任何模型来满足功能规范.一个简单的例子是编译器可以使用或省略帧指针.它还可以为返回值分配空间或使用寄存器.

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

leal 指令正在计算 bp-20 处的缓冲区起始位置.在序言之后,堆栈帧看起来像:

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 ] ...

所以看起来你必须写 28 个字节来改变这里的返回地址.我的猜测是编译器正试图在段落边界上对齐堆栈帧.这里包括 strcpy arg 设置在内的完整帧为 48 字节,即 3 个段落.段落对齐有助于提高总线和缓存性能.

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.

这篇关于C函数栈布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆