pwntools 笔记
Pwntools 简述
Pwntools 是一个 CTF 框架和漏洞利用开发库。
它是用 Python 编写的,专为快速原型设计和开发而设计,旨在使漏洞利用编写尽可能简单。
我们可以使用 pip 包管理工具安装 pwntools
:
1 | pip3 install pwntools |
pwntools 需要及时使用最新版,我们可以使用以下命令对 pwntools 更新:
1 | python3 -m pip install --upgrade pwntools |
Pwntools 详解
pwntools
模块索引
模块名称 | 模块功能 |
---|---|
pwnlib.adb |
adb 调试桥的封装 |
pwnlib.args |
包含命令行参数的一些配置 (包含这个包后会自动从命令行中获取参数) |
pwnlib.asm |
通过 capstone 进行汇编的编译和反编译等功能的封装 |
pwnlib.atexception |
包含未处理异常的回调函数 |
pwnlib.atexit |
atexit 的替代品 |
pwnlib.constants |
头文件宏定义的封装,可以通过这个模块直接获取系统宏定义常数 |
pwnlib.config |
Pwntools 配置变量 |
pwnlib.context |
包含运行时变量,上下文管理器 |
pwnlib.dynelf |
通过内存 leak 数据自动化定位程序中函数位置 |
pwnlib.encoders |
Shellcode 编码工具封装 |
pwnlib.elf.config |
elf 核心配置 |
pwnlib.elf.corefile |
elf 核心文件转储功能 |
pwnlib.elf.elf |
elf 文件操作封装 |
pwnlib.exception |
Pwnlib 异常 |
pwnlib.filepointer |
FILE* 结构体封装 |
pwnlib.filesystem |
通过 SSH 为本地文件系统和远程文件系统上的路径提供 Python2 的兼容接口 |
pwnlib.flag |
CTF Flag 管理 |
pwnlib.fmtstr |
格式化字符串漏洞利用封装 |
pwnlib.gdb |
GDB 调试封装 |
pwnlib.libcdb |
Libc 数据库,可以通过一些信息查找对应的地址 |
pwnlib.log |
日志库,跟 Pwntools 的操作 |
pwnlib.memleak |
内存泄漏管理工具 |
pwnlib.qemu |
QEMU 适用工具封装 |
pwnlib.replacements |
一些标准函数的替代品 |
pwnlib.rop.ret2dlresolve |
提供缓冲区溢出利用的负载自动化生成工具 |
pwnlib.rop.rop |
ROP 生成工具,可以直接生成 32 位 ROP |
pwnlib.rop.srop |
Sigreturn 相关的利用封装 |
pwnlib.runner |
Shellcode 运行封装 |
pwnlib.shellcraft |
Shellcode 生成工具 |
pwnlib.shellcraft.aarch64 |
Shellcode for AArch64 |
pwnlib.shellcraft.amd64 |
Shellcode for AMD64 |
pwnlib.shellcraft.arm |
Shellcode for ARM |
pwnlib.shellcraft.common |
Shellcode 所有架构的基本利用 |
pwnlib.shellcraft.i386 |
Shellcode for Intel 80386 |
pwnlib.shellcraft.mips |
Shellcode for MIPS |
pwnlib.shellcraft.thumb |
Shellcode for Thumb Mode |
pwnlib.term |
终端处理封装 |
pwnlib.timeout |
超时处理封装 |
pwnlib.tubes |
套接字、SSH 等 IO 封装 |
pwnlib.tubes.buffer |
IO 缓冲封装 |
pwnlib.tubes.process |
IO 进程封装 |
pwnlib.tubes.serialtube |
IO 串行端口封装 |
pwnlib.tubes.sock |
套接字封装 |
pwnlib.tubes.ssh |
SSH 封装 |
pwnlib.ui |
UI 封装 |
pwnlib.update |
更新 Pwntools |
pwnlib.useragents |
useragent 生成封装 |
pwnlib.util.crc |
计算一系列 CRC 的封装 |
pwnlib.util.cyclic |
一些序列生成器的封装 |
pwnlib.util.fiddling |
编码封装 |
pwnlib.util.getdents |
Linux 二进制目录处理 |
pwnlib.util.hashes |
哈希散列函数封装 |
pwnlib.util.iters |
itertools 的扩展 |
pwnlib.util.lists |
对 list 的操作封装 |
pwnlib.util.misc |
一些没办法分类的杂项函数封装 |
pwnlib.util.net |
网络交互封装 |
pwnlib.util.packing |
压缩操作封装 |
pwnlib.util.proc |
与 /proc/ 相关的进程操作封装 |
pwnlib.util.safeeval |
安全的 eval() |
pwnlib.util.sh_string |
Shell 字符串 eval() |
pwnlib.util.web |
web 网络交互工具 |
推荐使用
from pwn import *
将以上各功能模块直接导入
Pwntools 与服务器
使用 Pwntools 与服务器进行交互,需要利用 pwnlib.tubes
库,方便起见可以直接 from pwn import *
导入所有模块。
建立连接
建立连接我们需要使用 remote
类,它的构造函数需要接收域名
(host) 和 端口 (port) 来跟服务器建立 TCP 或 UDP 连接,相当于 Linux 中的
nc
指令。
其他参数请参考官方文档 http://docs.pwntools.com/en/latest/tubes.html
使用示例:
1 | io = pwn.remote("127.0.0.1", 8888) |
接收数据
recv(numb, timeout)
numb
→ 接收的字节数;有默认值timeout
→ 接收时限,单位秒,超时则中断接收;有默认值@returns
→ 返回一个保存所接收数据的bytes
数组如果不给参数,默认返回缓冲区数据
使用示例:
1
2
3
4
5
6
7
8# 接收所有数据 (但只是缓冲区内容)
data = io.recv()
# 接收 1024 字节数据
data = io.recv(1024)
# 接收 1 秒数据
data = io.recv(timeout=1)
# 接收 1024 字节数据,如果超时则直接返回
data = io.recv(1024, timeout=1)recvall(timeout)
timeout
→ 接收时限,单位秒,超时则中断接收;默认 forever@returns
→ 返回一个保存所接收数据的bytes
数组使用示例:
1
2
3
4# 接收所有数据,直到 socket 关闭
data = io.recvall()
# 接收 1 秒数据
data = io.recvall(timeout=1)recvline(keepends, timeout)
keepends
→ 接收数据是否保留回车;默认保留timeout
→ 接收时限,单位秒,超时则中断接收;有默认值@returns
→ 返回一个保存所接收数据的bytes
数组使用示例:
1
2
3
4# 接收一行数据 (但含有'\n')
data = io.recvline()
# 接收一行数据 (不含有'\n')
data = io.recvline(False)recvuntil(delims, drop, timeout)
delims
→ 接收中止标志drop
→ 是否丢弃中止标志;默认不丢弃timeout
→ 接收时限,单位秒,超时则中断接收;有默认值@returns
→ 返回一个保存所接收数据的bytes
数组使用示例:
1
2
3
4
5
6
7
8
9
10
11
12"""
接收数据直到接收到 'start' 后结束,字符串中包含 'start'
比如缓冲区中存在数据 'the game is started!'
那么函数会返回 b'the game is start',缓冲区为 'ed!'
"""
data = io.recvuntil('start')
"""
接收数据直到接收到 'start' 后结束,字符串中不包含 'start'
比如缓冲区中存在数据 'the game is started!'
那么函数会返回 b'the game is ',而缓冲区为 'ed!'
"""
data = io.recvuntil('start', True)
发送数据
send(data)
data
→ 发送的 bytes 数组使用示例:
1
2# 发送数据,但不包含'\n'
io.send('hey!')sendline(data)
data
→ 发送的 bytes 数组,默认值为换行符使用示例:
1
2# 发送数据,且包含换行符
io.sendline('hey!')sendthen(delim, data, timeout)
delims
→ 接收中止标志data
→ 发送的 bytes 数组timeout
→ 接收时限,单位秒,超时则中断接收;有默认值@returns
→ 返回一个保存所接收数据的bytes
数组sendlinethen
同理使用示例:
1
2
3
4# 发送数据'hey!',然后 io.recvuntil('how are u?')
data = io.sendthen('how are u?', 'hey!')
# 发送数据'hey!',然后 io.recvuntil('how are u?', 1)
data = io.sendthen('how are u?', 'hey!', 1)sendafter(delim, data, timeout)
delims
→ 接收中止标志data
→ 发送的 bytes 数组timeout
→ 接收时限,单位秒,超时则中断接收;有默认值@returns
→ 返回一个保存所接收数据的bytes
数组sendlinethen
同理使用示例:
1
2
3
4# io.recvuntil('how are u?'),然后接收数据'I am fine.'
data = io.sendafter('how are u?', 'I am fine.')
# io.recvuntil('how are u?', 1),然后接收数据'I am fine.'
data = io.sendafter('how are u?', 'hey!', 1)
交互模式
remote.interactive()
可以直接进入终端交互模式,自动接收数据并输出,且会等待输入。
使用示例:
1 | io.interactive() |
完整示例
1 | from pwn import * |