0%

【pdkx培训】pwn stack migration

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]; // [esp+0h] [ebp-28h] BYREF

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