pwntools是一个CTF框架和漏洞利用开发库,用Python开发,由rapid设计,旨在让使用者简单快速的编写exploit。包含了本地执行、远程连接读写、shellcode生成、ROP链的构建、ELF解析、符号泄露等众多强大功能。
模块
使用from pwn import *将所有的模块导入到当前namespace,这条语句还会帮你把os,sys等常用的系统库导入。
常用模块如下:
- asm : 汇编与反汇编,支持x86/x64/arm/mips/powerpc等基本上所有的主流平台
 - dynelf : 用于远程符号泄漏,需要提供leak方法
 - elf : 对elf文件进行操作
 - gdb : 配合gdb进行调试
 - memleak : 用于内存泄漏
 - shellcraft : shellcode的生成器
 - tubes : 包括tubes.sock, tubes.process, tubes.ssh, tubes.serialtube,分别适用于不同场景的PIPE
 - utils : 一些实用的小功能,例如CRC计算,cyclic pattern等
 
连接
1  | 本地:sh = porcess("./level0")  | 
IO模块
1  | sh.send(data) #发送数据  | 
汇编和反汇编
汇编:
1  | asm('nop')  | 
可以使用context来指定cpu类型以及操作系统
1  | context.arch = 'i386'  | 
使用disasm进行反汇编
1  | print disasm('6a0258cd80ebf9'.decode('hex'))  | 
注意,asm需要binutils中的as工具辅助,如果是不同于本机平台的其他平台的汇编,例如在我的x86机器上进行mips的汇编就会出现as工具未找到的情况,这时候需要安装其他平台的cross-binutils。
Shellcode生成器
1  | print shellcraft.i386.nop().strip('\n')  | 
结合asm可以可以得到最终的pyaload。
1  | from pwn import *  | 
除了直接执行sh之外,还可以进行其它的一些常用操作例如提权、反向连接等等。
ELF文件操作
1  | e = ELF('/bin/cat')  | 
同样,也可以打开一个libc.so来解析其中system的位置:
甚至可以修改一个ELF的代码
1  | e = ELF('/bin/cat')  | 
下面是一些可用的函数:
- asm(address, assembly) : 在指定地址进行汇编
 - bss(offset) : 返回bss段的位置,offset是偏移值
 - checksec() : 对elf进行一些安全保护检查,例如NX, PIE等。
 - disasm(address, n_bytes) : 在指定位置进行n_bytes个字节的反汇编
 - offset_to_vaddr(offset) : 将文件中的偏移offset转换成虚拟地址VMA
 - vaddr_to_offset(address) : 与上面的函数作用相反
 - read(address, count) : 在address(VMA)位置读取count个字节
 - write(address, data) : 在address(VMA)位置写入data
 - section(name) : dump出指定section的数据
 
整数pack与数据unpack
pack:p32,p64
unpack:u32,u64
(分别对应着32位和64位的整数)
1  | from pwn import *  | 
ROP链生成器
1  | elf = ELF('ropasaurusrex')  | 
使用ROP(elf)来产生一个rop的对象,这时rop链还是空的,需要在其中添加函数。
因为ROP对象实现了getattr的功能,可以直接通过func call的形式来添加函数,rop.read(0, elf.bss(0x80))实际相当于rop.call(‘read’, (0, elf.bss(0x80)))。
 通过多次添加函数调用,最后使用str将整个rop chain dump出来就可以了。
- call(resolvable, arguments=()) : 添加一个调用,resolvable可以是一个符号,也可以是一个int型地址,注意后面的参数必须是元组否则会报错,即使只有一个参数也要写成元组的形式(在后面加上一个逗号)
 - chain() : 返回当前的字节序列,即payload
 - dump() : 直观地展示出当前的rop chain
 - raw() : 在rop chain中加上一个整数或字符串
 - search(move=0, regs=None, order=’size’) : 按特定条件搜索gadget
 - unresolve(value) : 给出一个地址,反解析出符号
 




