pwn:使用pwntools的rop工具来构建有效负载

1. 安装 pwntools

首先,需要确保已安装 pwntools。可以通过 pip 安装:

pip install pwntools

2. 导入和基本使用

from pwn import *

3. ROP 对象创建

要使用 ROP 工具,你首先需要创建一个 ROP 对象:

context.clear(arch='i386')
context.clear(arch='amd64')
elf = ELF('binary')  # 加载 ELF 文件
rop = ROP(elf)       # 创建 ROP 对象

4. 查找 ROP Gadget

ROP gadget 是一些小段代码,通常以 ret 指令结尾,pwntools 提供了 find_gadget 方法来查找这些 gadget:

>>> rop.eax
Gadget(0x10000004, ['pop eax', 'ret'], ['eax'], 0x8)
>>> hex(rop.eax.address)
'0x10000004'
>>> rop.ecx
Gadget(0x10000006, ['pop ecx', 'pop ebx', 'ret'], ['ecx', 'ebx'], 0xc)

5.修改寄存器的值的poc

调用rop函数并将寄存器值以键值

rop(eax=0x11111111, ecx=0x22222222)

6.创建函数调用栈帧

rop.call('read', [4,5,6])
print(rop.dump())
"""
0x0000:              0x0
0x0004:       0x64636261
0x0008:              0x2
0x000c:       0xdeadbeef read(4, 5, 6)
0x0010:          b'eaaa' <return address>
0x0014:              0x4 arg0
0x0018:              0x5 arg1
0x001c:              0x6 arg2
"""
rop.write(7,8,9)
rop.exit()
print(rop.dump())
"""
0x0000:              0x0
0x0004:       0x64636261
0x0008:              0x2
0x000c:       0xdeadbeef read(4, 5, 6)
0x0010:       0x10000000 <adjust @0x24> add esp, 0x10; ret
0x0014:              0x4 arg0
0x0018:              0x5 arg1
0x001c:              0x6 arg2
0x0020:          b'iaaa' <pad>
0x0024:       0xdecafbad write(7, 8, 9)
0x0028:       0xfeedface exit()
0x002c:              0x7 arg0
0x0030:              0x8 arg1
0x0034:              0x9 arg2
"""

7.手动向栈写入内容

rop.raw(0)
rop.raw(unpack(b'abcd'))
rop.raw(2)
print(rop.dump())
"""
0x0000:              0x0
0x0004:       0x64636261
0x0008:              0x2
"""

8.附加已知基地址

rop = ROP(binary, base=0x7fffe000)
rop.call('execve', [b'/bin/sh', [[b'/bin/sh'], [b'-p'], [b'-c'], [b'ls']], 0])
print(rop.dump())
"""
0x7fffe000:       0xcafebabe execve([b'/bin/sh'], [[b'/bin/sh'], [b'-p'], [b'-c'], [b'ls']], 0)
0x7fffe004:          b'baaa' <return address>
0x7fffe008:       0x7fffe014 arg0 (+0xc)
0x7fffe00c:       0x7fffe01c arg1 (+0x10)
0x7fffe010:              0x0 arg2
0x7fffe014:   b'/bin/sh\x00'
0x7fffe01c:       0x7fffe02c (+0x10)
0x7fffe020:       0x7fffe034 (+0x14)
0x7fffe024:       0x7fffe038 (+0x14)
0x7fffe028:       0x7fffe03c (+0x14)
0x7fffe02c:   b'/bin/sh\x00'
0x7fffe034:       b'-p\x00$'
0x7fffe038:       b'-c\x00$'
0x7fffe03c:       b'ls\x00$'
"""

9.寻找jmp $sp小工具

  • i386
context.clear(arch='i386')
>>> elf = ELF.from_assembly('nop; jmp esp; ret')
>>> rop = ROP(elf)
>>> jmp_gadget = rop.jmp_esp
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
True
  • amd64
context.clear(arch='amd64')
>>> elf = ELF.from_assembly('nop; jmp rsp; ret')
>>> rop = ROP(elf)
>>> jmp_gadget = rop.jmp_rsp
>>> elf.read(jmp_gadget.address, 2) == asm('jmp rsp')
True
  • 过滤badchar,这些字符会在发送时截断数据
context.clear(arch='i386')
>>> elf = ELF.from_assembly('nop; pop eax; jmp esp; int 0x80; jmp esp; ret')
>>> rop = ROP(elf, badchars=b'\x02')
>>> jmp_gadget = rop.jmp_esp    # It returns the second gadget
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
True
>>> rop = ROP(elf, badchars=b'\x02\x06')
>>> rop.jmp_esp == None         # The address of both gadgets has badchar
True

举例说明常见的badchars:

  • \x00(NULL字节): 最常见的badchar,许多字符串处理函数会在遇到\x00时停止读取。

  • \x0a(换行符 \n): 在一些协议中,表示命令或数据的结束。

  • \x0d(回车符 \r): 类似\x0a,在网络通信中常与\x0a一起使用。

10.创建ret2csu poc

  • 参数

    • edi – 要填充的三个主寄存器

    • rsi – 要填充的三个主寄存器

    • rdx – 要填充的三个主寄存器

    • rbx – 要填充的可选寄存器

    • rbp – 要填充的可选寄存器

    • r12 – 要填充的可选寄存器

    • r13 – 要填充的可选寄存器

    • r14 – 要填充的可选寄存器

    • r15 – 要填充的可选寄存器

    • call – 对于 PIE 二进制文件必填

>>> context.clear(binary=pwnlib.data.elf.ret2dlresolve.get("amd64"))
>>> r = ROP(context.binary)
>>> r.ret2csu(1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> r.call(0xdeadbeef)
>>> print(r.dump())
0x0000:         0x40058a
0x0008:              0x0
0x0010:              0x1
0x0018:         0x600e48
0x0020:              0x1
0x0028:              0x2
0x0030:              0x3
0x0038:         0x400570
0x0040:      b'qaaaraaa' <add rsp, 8>
0x0048:              0x4
0x0050:              0x5
0x0058:              0x6
0x0060:              0x7
0x0068:              0x8
0x0070:              0x9
0x0078:       0xdeadbeef 0xdeadbeef()
>>> open('core','w').close(); os.unlink('core')  # remove any old core file for the tests
>>> p = process()
>>> p.send(fit({64+context.bytes: r}))
>>> p.wait(0.5)
>>> core = p.corefile
>>> hex(core.pc)
'0xdeadbeef'
>>> core.rdi, core.rsi, core.rdx, core.rbx, core.rbp, core.r12, core.r13, core.r14, core.r15
(1, 2, 3, 4, 5, 6, 7, 8, 9)

11.获取poc并清除缓存

raw_rop = rop.chain()
>>> print(enhex(raw_rop))
120000102f000010010000002600001008000000
>>> rop.clear_cache()

翻译并整理

pwnlib.rop.rop — 面向返回的编程 — pwntools 4.13.1 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值