Dr *_*Deo 5 c c++ x86 winapi stack
我一直在阅读一个可以覆盖其返回地址的函数.
void foo(const char* input)
{
char buf[10];
//What? No extra arguments supplied to printf?
//It's a cheap trick to view the stack 8-)
//We'll see this trick again when we look at format strings.
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n"); //%p ie expect pointers
//Pass the user input straight to secure code public enemy #1.
strcpy(buf, input);
printf("%s\n", buf);
printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}
Run Code Online (Sandbox Code Playgroud)
有人建议这就是堆栈的样子
地址foo = 00401000
我的堆栈看起来像:
00000000
00000000
7FFDF000
0012FF80
0040108A < - 我们要覆盖foo的返回地址.
00410EDE
问题:
- .为什么作者任意选择倒数第二个值作为foo()的返回地址?
- .值是从底部还是从顶部添加到堆栈中?
谢谢.
上面的是前一个 EBP ( 0012FF80)。prev-EBP 上方的值始终是返回地址。
(这显然假设非 FPO 二进制文件和 32 位 Windows)1。
如果你还记得的话,序言是这样的:
push ebp ; back up the previous ebp on the stack
mov ebp, esp ; set up the new frame pointer
Run Code Online (Sandbox Code Playgroud)
当调用函数时,例如
call 0x00401000
Run Code Online (Sandbox Code Playgroud)
当前的EIP被压入堆栈(用作返回地址),因此序言之后的堆栈如下所示:
[ebp+0xc] ; contains parameter 1, etc
[ebp+0x8] ; contains parameter 0
[ebp+0x4] ; contains return address
[ebp] ; contains prev-EBP
Run Code Online (Sandbox Code Playgroud)
因此,对于每个, printf 使用从(第一个参数)%p开始的接下来的 4 个字节。最终,您命中存储在堆栈中的上一个 EBP 值,即 ( ),然后下一个值是返回地址。[ebp+0xc]%p0012FF80
请注意,这些地址必须“有意义”,它们在这里显然做到了这一点(尽管可能并非所有人都“清楚”)。
关于 Q2)堆栈向下增长。因此push eax,当您从 中减去 4 时esp,eax 的值将移动到 [esp],相当于代码中的:
push eax
; <=>
sub esp, 4
mov [esp], eax
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5336 次 |
| 最近记录: |