pwntools 英文文档
pwntools 中文文档
安装
环境准备
python pip libssl-dev libffi-dev
|
sudo apt install libssl-dev sudo apt install libffi-dev sudo pip install pwntools
|
利用
以下只是常用命令
导入
导入pwntools模块
context
Log等级
context.log_level = "debug" context.log_level = "error"
|
或者在调用时使用 DEBUG 参数
指定cpu类型, 操作系统类型, 端序, 位数
context.arch = 'i386' context.os = 'linux' context.endian = 'little' context.word_size = 32
|
在tmux中以分屏的形式启动gdb
context.terminal = ['tmux', 'splitw', '-h'] context.terminal = ['tmux', 'splitw', '-v']
|
启动程序
p = process("./pwn") p = remote(ip, port)
|
绑定libc
p = process(['./bin'], env={'LOAD_PRELOAD': './libc-2.23.so'})
|
gdb调试
IO模块
发送信息
p.send(data) p.sendline(data) p.sendafter(delim, data, timeout = default) p.sendlineafter(delim, data, timeout = default)
|
接受信息
p.recv(number) p.recvline() p.recvuntil(msg)
|
启动交互
打印信息
log.success("msg") log.info("msg")
|
Shellcode 生成器
shellcraft.i386.linux.sh()
|
打印出来:
>>> print(shellcraft.i386.linux.sh()) /* execve(path='/bin///sh', argv=['sh'], envp=0) */ /* push b'/bin///sh\x00' */ push 0x68 push 0x732f2f2f push 0x6e69622f mov ebx, esp /* push argument array ['sh\x00'] */ /* push 'sh\x00\x00' */ push 0x1010101 xor dword ptr [esp], 0x1016972 xor ecx, ecx push ecx /* null terminate */ push 4 pop ecx add ecx, esp push ecx /* 'sh\x00' */ mov ecx, esp xor edx, edx /* call execve() */ push SYS_execve /* 0xb */ pop eax int 0x80
|
结合 asm 可以得到最终的 payload
from pwn import * context(os='linux',arch='amd64') shellcode = asm(shellcraft.sh())
|
或者
from pwn import * shellcode = asm(shellcraft.amd64.linux.sh())
|
除了直接执行sh之外,还可以进行其它的一些常用操作例如提权、反向连接等等。
pack and unpack
pack: p8, p16, p32, p64
unpack: u8, u16, u32, u64
示例
payload = 'a' * 0x80 + p64(sys_addr)
__malloc_hook_addr = u64(p.recv(6).ljust(8, "\x00"))
|
ROP链生成器
elf = ELF('ropasaurusrex') rop = ROP(elf) rop.read(0, elf.bss(0x80)) rop.dump()
str(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) : 给出一个地址,反解析出符号
常用模板
from pwn import *
elf_name = "./filename"
p = process([elf_name], env = {"LD_PRELOAD": "./libc.so.6"})
elf = ELF(elf_name) libc = ELF("./libc.so.6")
context.log_level = "debug" context.terminal = ['tmux', 'splitw', '-v']
rv = p.recv ru = p.recvuntil sd = p.send sa = p.sendafter sl = p.sendline sla = p.sendlineafter ia = p.interactive
def dbg(breakpoint): gdb.attach(p, "b " + breakpoint)
p.interactive()
|
参考
pwntools使用