你可以使用 Ropper 显示不同文件格式的二进制文件信息, 并搜索用于构建不同架构(x86/X86_64、ARM/ARM64、MIPS/MIPS64、PowerPC/PowerPC64、SPARC64)的 ROP 链的 gadgets。 反汇编方面,Ropper 使用了强大的 Capstone 框架。
通过 PyPi 安装 Capstone:
$ sudo pip install capstone
通过 PyPi 安装 filebytes:
$ sudo pip install filebytes
可选(运行 Ropper 不需要,仅用于搜索 gadgets):
安装 Keystone:
$ sudo pip install keystone-engine
安装并运行 Ropper
$ python setup.py install
$ ropper
你也可以通过 pip 安装 Ropper
$ pip install ropper
如果你愿意,也可以不安装直接使用 Ropper
$ ./Ropper.py
如果你不想安装 filebytes,filebytes 是 Ropper 仓库的一个子模块。这意味着你无需单独安装 filebytes 和 Ropper。
$ git clone https://github.com/sashs/ropper.git
$ cd ropper
$ git submodule init
$ git submodule update
$ ./Ropper.py
该功能仍在开发中! Ropper 提供了一个语义搜索命令,允许搜索 gadgets。
$ ropper --file <afile> --semantic "<任何约束>"
使用语义搜索需要以下可选依赖:
安装 pyvex
$ sudo pip install pyvex
安装 z3py
$ python scripts/mk_make.py
$ cd build
$ make
$ sudo make install
reg == reg - 将一个寄存器赋值给另一个
reg == number - 将数值赋给寄存器
reg == [reg] - 将内存内容赋给寄存器
reg += number/reg/[reg]
reg -= number/reg/[reg]
reg *= number/reg/[reg]
reg /= number/reg/[reg]
eax==1 !ebx - 将 eax 设为 1,并查找不破坏 ebx 的 gadgets

usage: Ropper.py [-h] [--help-examples] [-v] [--console]
[-f <file> [<file> ...]] [-r] [-a <arch>]
[--section <section>] [--string [<string>]] [--hex]
[--asm [<asm> [H|S|R] ...]] [--disasm <opcode>]
[--disassemble-address <address:length>] [-i] [-e]
[--imagebase] [-c] [-s] [-S] [--imports] [--symbols]
[--set <option>] [--unset <option>] [-I <imagebase>] [-p]
[-j <reg>] [--stack-pivot] [--inst-count <n bytes>]
[--search <regex>] [--quality <quality>] [--opcode <opcode>]
[--instructions <instructions>] [--type <type>] [--detailed]
[--all] [--cfg-only] [--chain <generator>] [-b <badbytes>]
[--nocolor] [--clear-cache] [--no-load] [--analyse <quality>]
[--semantic constraint]
[--count-of-findings <count of gadgets>] [--single]
你可以使用 ropper 显示不同文件格式的二进制文件信息,
并搜索用于构建不同架构的 ROP 链的 gadgets
支持的文件类型:
ELF
PE
Mach-O
Raw
支持的架构:
x86 [x86]
x86_64 [x86_64]
MIPS [MIPS, MIPS64]
ARM/Thumb [ARM, ARMTHUMB]
ARM64 [ARM64]
PowerPC [PPC, PPC64]
SPARC [SPARC64]
可用的 ROP 链生成器:
execve (execve[=<cmd>], 默认 /bin/sh) [Linux x86, x86_64]
mprotect (mprotect=<address>:<size>) [Linux x86, x86_64]
virtualprotect (virtualprotect=<address iat vp>:<size>) [Windows x86]
选项:
-h, --help 显示此帮助信息并退出
--help-examples 打印示例
-v, --version 打印版本
--console 启动交互式命令行
-f <file> [<file> ...], --file <file> [<file> ...]
要加载的文件
-r, --raw 以裸文件形式加载文件
-a <arch>, --arch <arch>
加载文件的架构
--section <section> 打印此节的数据
--string [<string>] 在所有数据节中查找字符串 <string>
--hex 以十六进制格式打印所选节
--asm [<asm> [H|S|R] ...]
要汇编的字符串及输出格式(H=HEX, S=STRING, R=RAW, 默认:H)
--disasm <opcode> 要反汇编的操作码(例如 ffe4, 89c8c3, ...)
--disassemble-address <address:length>
反汇编地址 <address>(0x12345678:L3)处的指令。可以指定要反汇编的指令数量(0x....:L...)
-i, --info 显示文件头部 [ELF/PE/Mach-O]
-e 显示入口点
--imagebase 显示映像基址 [ELF/PE/Mach-O]
-c, --dllcharacteristics
显示 DLL 特性 [PE]
-s, --sections 显示文件节区 [ELF/PE/Mach-O]
-S, --segments 显示文件段 [ELF/Mach-O]
--imports 显示导入 [ELF/PE]
--symbols 显示符号 [ELF]
--set <option> 设置选项。可用选项:aslr nx
--unset <option> 取消设置选项。可用选项:aslr nx
-I <imagebase> 使用此映像基址查找 gadgets
-p, --ppr 搜索 'pop reg; pop reg; ret' 指令 [仅 x86/x86_64]
-j <reg>, --jmp <reg>
搜索 'jmp reg' 指令(-j reg[,reg...])[仅 x86/x86_64]
--stack-pivot 打印所有栈迁移 gadgets
--inst-count <n bytes>
指定 gadget 中最大指令数(默认:6)
--search <regex> 搜索 gadgets
--quality <quality> 搜索找到的 gadgets 的质量(1 = 最佳)
--opcode <opcode> 搜索操作码(例如 ffe4 或 ffe? 或 ff??)
--instructions <instructions>
搜索指令(例如 "jmp esp", "pop eax; ret")
--type <type> 设置 gadgets 类型 [rop, jop, sys, all](默认:all)
--detailed 更详细地打印 gadgets
--all 不删除重复的 gadgets
--cfg-only 过滤掉未通过 Microsoft CFG 检查的 gadgets。仅适用于启用了 CFG 检查编译的 PE 文件(检查 DllCharacteristics)[PE]
--chain <generator> 生成 ROP 链 [generator parameter=value[ parameter=value]]
-b <badbytes>, --badbytes <badbytes>
设置 gadgets 中不应包含的字节
--nocolor 禁用彩色输出
--clear-cache 清除缓存
--no-load 启动控制台时不自动加载 gadgets(--console)
--analyse <quality> 仅用于语义搜索的实现
--semantic constraint 语义搜索 gadgets
--count-of-findings <count of gadgets>
语义搜索时打印的最大 gadgets 数量(0 = 未定义,默认:5)
--single 不使用多进程进行 gadget 扫描
使用示例:
[通用]
./Ropper.py
./Ropper.py --file /bin/ls --console
[信息]
./Ropper.py --file /bin/ls --info
./Ropper.py --file /bin/ls --imports
./Ropper.py --file /bin/ls --sections
./Ropper.py --file /bin/ls --segments
./Ropper.py --file /bin/ls --set nx
./Ropper.py --file /bin/ls --unset nx
./Ropper.py --file /bin/ls --inst-count 5
./Ropper.py --file /bin/ls --search "sub eax" --badbytes 000a0d
./Ropper.py --file /bin/ls --search "sub eax" --detail
./Ropper.py --file /bin/ls --filter "sub eax"
./Ropper.py --file /bin/ls --inst-count 5 --filter "sub eax"
./Ropper.py --file /bin/ls --opcode ffe4
./Ropper.py --file /bin/ls --opcode ffe?
./Ropper.py --file /bin/ls --opcode ??e4
./Ropper.py --file /bin/ls --detailed
./Ropper.py --file /bin/ls --ppr --nocolor
./Ropper.py --file /bin/ls --jmp esp,eax
./Ropper.py --file /bin/ls --type jop
./Ropper.py --file /bin/ls --chain execve
./Ropper.py --file /bin/ls --chain "execve cmd=/bin/sh" --badbytes 000a0d
./Ropper.py --file /bin/ls --chain "mprotect address=0xbfdff000 size=0x21000"
./Ropper.py --file /bin/ls /lib/libc.so.6 --console
[汇编/反汇编]
./Ropper.py --asm "jmp esp"
./Ropper.py --asm "mov eax, ecx; ret"
./Ropper.py --disasm ffe4
[搜索]
./Ropper.py --file /bin/ls --search <搜索字符串>
? 任意字符
% 任意字符串
示例:
./Ropper.py --file /bin/ls --search "mov e?x"
0x000067f1: mov edx, dword ptr [ebp + 0x14]; mov dword ptr [esp], edx; call eax
0x00006d03: mov eax, esi; pop ebx; pop esi; pop edi; pop ebp; ret ;
0x00006d6f: mov ebx, esi; mov esi, dword ptr [esp + 0x18]; add esp, 0x1c; ret ;
0x000076f8: mov eax, dword ptr [eax]; mov byte ptr [eax + edx], 0; add esp, 0x18; pop ebx; ret ;
./Ropper.py --file /bin/ls --search "mov [%], edx"
0x000067ed: mov dword ptr [esp + 4], edx; mov edx, dword ptr [ebp + 0x14]; mov dword ptr [esp], edx; call eax;
0x00006f4e: mov dword ptr [ecx + 0x14], edx; add esp, 0x2c; pop ebx; pop esi; pop edi; pop ebp; ret ;
0x000084b8: mov dword ptr [eax], edx; ret ;
0x00008d9b: mov dword ptr [eax], edx; add esp, 0x18; pop ebx; ret ;
./Ropper.py --file /bin/ls --search "mov [%], edx" --quality 1
0x000084b8: mov dword ptr [eax], edx; ret ;; ret ;
#!/usr/bin/env python
from ropper import RopperService
# 并非所有选项都需要提供
options = {'color' : False, # 打印 gadgets 时是否使用彩色输出:默认:False
'badbytes': '00', # 地址或 ROP 链中不应包含的坏字节;默认:''
'all' : False, # 显示所有 gadgets,即不删除重复 gadgets;默认:False
'inst_count' : 6, # gadget 中的指令数量;默认:6
'type' : 'all', # rop, jop, sys, all;默认:all
'detailed' : False} # 打印 gadgets 时是否使用详细输出;默认:False
rs = RopperService(options)
##### 更改选项 ######
rs.options.color = True
rs.options.badbytes = '00'
rs.options.badbytes = ''
rs.options.all = True
##### 打开二进制文件 ######
# 可以同时打开多个文件
rs.addFile('test-binaries/ls-x86')
rs.addFile('ls', bytes=open('test-binaries/ls-x86','rb').read()) # 另一种方式
rs.addFile('ls_raw', bytes=open('test-binaries/ls-x86','rb').read(), raw=True, arch='x86')
##### 关闭二进制文件 ######
rs.removeFile('ls')
rs.removeFile('ls_raw')
# 设置二进制文件的架构,以便为不同架构查找 gadgets
# 对于 ARM,如果要查找 ARM gadgets 或 Thumb gadgets,这很有用
# 或者在打开裸文件时使用
ls = 'test-binaries/ls-x86'
rs.setArchitectureFor(name=ls, arch='x86')
rs.setArchitectureFor(name=ls, arch='x86_64')
rs.setArchitectureFor(name=ls, arch='ARM')
rs.setArchitectureFor(name=ls, arch='ARMTHUMB')
rs.setArchitectureFor(name=ls, arch='ARM64')
rs.setArchitectureFor(name=ls, arch='MIPS')
rs.setArchitectureFor(name=ls, arch='MIPS64')
rs.setArchitectureFor(name=ls, arch='PPC')
rs.setArchitectureFor(name=ls, arch='PPC64')
rs.setArchitectureFor(name=ls, arch='SPARC64')
rs.setArchitectureFor(name=ls, arch='x86')
##### 加载 gadgets ######
# 为所有已打开的文件加载 gadgets
rs.loadGadgetsFor()
# 仅为某个已打开的文件加载 gadgets
ls = 'test-binaries/ls-x86'
rs.loadGadgetsFor(name=ls)
# 更改 gadget 类型
rs.options.type = 'jop'
rs.loadGadgetsFor()
rs.options.type = 'rop'
rs.loadGadgetsFor()
# 更改指令计数
rs.options.inst_count = 10
rs.loadGadgetsFor()
##### 打印 gadgets #######
rs.printGadgetsFor() # 打印所有 gadgets
rs.printGadgetsFor(name=ls)
##### 获取 gadgets ######
gadgets = rs.getFileFor(name=ls).gadgets
##### 搜索 pop pop ret ######
pprs = rs.searchPopPopRet(name=ls) # 仅在 'test-binaries/ls-x86' 中查找 ppr
pprs = rs.searchPopPopRet() # 在所有已打开的文件中查找 ppr
for file, ppr in pprs.items():
for p in ppr:
print p
##### 加载 jmp reg ######
jmp_regs = rs.searchJmpReg(name=ls, regs=['esp', 'eax']) # 仅在 'test-binaries/ls-x86' 中查找 jmp reg
jmp_regs = rs.searchJmpReg(regs=['esp', 'eax'])
jmp_regs = rs.searchJmpReg() # 在所有已打开的文件中查找 jmp esp
for file, jmp_reg in jmp_regs.items():
for j in jmp_reg:
print j
##### 搜索操作码 ######
ls = 'test-binaries/ls-x86'
gadgets_dict = rs.searchOpcode(opcode='ffe4', name=ls)
gadgets_dict = rs.searchOpcode(opcode='ffe?')
gadgets_dict = rs.searchOpcode(opcode='??e4')
for file, gadgets in gadgets_dict.items():
for g in gadgets:
print g
##### 搜索指令 ######
ls = 'test-binaries/ls-x86'
for file, gadget in rs.search(search='mov e?x', name=ls):
print file, gadget
for file, gadget in rs.search(search='mov [e?x%]'):
print file, gadget
result_dict = rs.searchdict(search='mov eax')
for file, gadgets in result_dict.items():
print file
for gadget in gadgets:
print gadget
##### 汇编指令 ######
hex_string = rs.asm('jmp esp')
print '"jmp esp" 汇编为十六进制字符串 =', hex_string
raw_bytes = rs.asm('jmp esp', format='raw')
print '"jmp esp" 汇编为原始字节 =', raw_bytes
string = rs.asm('jmp esp', format='string')
print '"jmp esp" 汇编为字符串 =',string
arm_bytes = rs.asm('bx sp', arch='ARM')
print '"bx sp" 汇编为十六进制字符串 =', arm_bytes
##### 反汇编字节 #######
arm_instructions = rs.disasm(arm_bytes, arch='ARM')
print arm_bytes, '反汇编为 "%s"' % arm_instructions
# 更改映像基址,这也会更改该二进制文件所有已加载 gadgets 的映像基址
rs.setImageBaseFor(name=ls, imagebase=0x0)
# 重置映像基址
rs.setImageBaseFor(name=ls, imagebase=None)
gadgets = rs.getFileFor(name=ls).gadgets
# gadget 地址
print hex(gadgets[0].address)
# 获取 gadget 的指令字节
print bytes(gadgets[0].bytes).encode('hex')
# 移除所有地址中包含坏字节的 gadgets
rs.options.badbytes = '000a0d' # gadgets 会自动过滤






