pwn stack migration
先看题目示例:
1 2 3 4 5 6 7 8 9 10 11
| int __cdecl main(int argc, const char **argv, const char **envp) { _BYTE buf[40];
if ( count != 1337 ) exit(1); count = 1338; setvbuf(stdout, 0, 2, 0); puts("Try your best :"); return read(0, buf, 0x40u); }
|
可以看出,与其他题目不同的是,return 的位置是一个函数,在汇编中如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| loc_80484C4: mov eax, count add eax, 1 mov count, eax mov eax, ds:stdout@@GLIBC_2_0 push 0 ; n push 2 ; modes push 0 ; buf push eax ; stream call setvbuf add esp, 10h push offset s ; "Try your best :" call puts add esp, 4 push 40h ; '@' ; nbytes lea eax, [ebp+buf] push eax ; buf push 0 ; fd call read add esp, 0Ch nop nop leave retn ; } // starts at 80484AB main endp
|
我们知道在执行 call func 的时候,实际上是:
1
| push eip+4; push ebp; mov ebp esp;
|
在执行 leave; ret; 的时候实际上是:
1 2
| mov esp ebp; pop ebp; // leave pop eip; // ret
|
所以在栈溢出之后的第一个值会被pop到ebp中,我们就将栈迁移到了一个我们想要的空间中去。
由此,可以开辟一块新的栈空间来存放我们想要的另一条gadget