我有一个看起来像这样的函数:
int bof(char *str)
{
char buffer[12];
strcpy(buffer, str);
return 1;
}
我正在尝试覆盖其返回地址。我发现我可以通过使用来做到这一点,例如,memcpy(buffer+24, "\x15\xf1\xff\xbf", 4)
。我不明白的是为什么我需要访问buffer + 24
。我对C内存模型的理解告诉我,执行这个函数时的堆栈应该是这样的
bottom of top of
memory memory
buffer(12) sfp(4) ret(4) str(4)
<------ [ ][ ][ ][ ] --->
top of bottom of
stack stack
这表明我应该 ret 地址应该从 buffer+16 开始。额外的 8 个字节从哪里来?
顺便说一句,我在 32 位系统上运行它。
检查 ISO C 99 和更早的标准,您会发现不存在 C 内存模型这样的东西。每个编译器都可以自由使用它喜欢的任何模型来满足功能规范。一个简单的例子是编译器可以使用或省略帧指针。它还可以为返回值分配空间或使用寄存器。
当我在我的机器上编译这段代码时,我得到
_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
指令正在计算缓冲区的起始位置bp-20
。序言之后,堆栈帧如下所示:
[ bp+8: str ] [bp+4: rtn address ] [bp: saved bp] [ bp-20: buf ] ...
所以看起来你必须在这里写入 28 个字节来更改返回地址。我的猜测是编译器正在尝试在段落边界上对齐堆栈帧。这里的完整框架包括 strcpy arg 设置为 48 字节,即 3 段。段落对齐有助于总线和缓存性能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)