PwnTools常见用法

pwntools是一个ctf框架和漏洞利用开发库,用Python开发,由rapid设计,旨在让使用者简单快速的编写exploit。

安装:

pwntools对Ubuntu 12.04和14.04的支持最好,但是绝大多数的功能也支持Debian, Arch, FreeBSD, OSX, 等等,确保安装以下系统库。

Binutils

Ubuntu

Mac OS X

Alternate OSes

Capstone

Ubuntu

Mac OS X

Python Development Headers

Ubuntu

Mac OS X

获得发行版本

$ apt-get install python2.7 python2.7-dev python-pip

$ pip install pwntools

获得最新版本

$ git clone https://github.com/Gallopsled/pwntools

$ cd pwntools

$ pip install -e .


1 context 设置运行时变量

context.log_level = 'debug'

2 remote,listen,ssh,process

支持常见操作recvline, recvuntil, clean 可以通过.interactive()直接与程序交互

3 p32 and u32

前者将数字转化为字符串,后者反之

4 log

输出消息

log.info('Hello, world!')


p = log.progress('Working')

p.status('Reticulating splines')

time.sleep(1)

p.success('Got a shell!')

5 cyclic and cyclic_find 对于直接的缓冲区溢出,可以很方便的确认再偏移多少可以控制eip

cyclic(20)

cyclic_find('aafb')

6 asm and disasm 快速的汇编和反汇编代码

asm('mov eax, 0')

asm(shellcraft.sh())

disasm('\xb8\x0b\x00\x00\x00')

7 shellcraft 提供了很多现成shellcode

8 ELF 用来操作ELF文件的工具

elf = ELF('pwn')

hex(elf.address)

hex(elf.symbols['write'])

hex(elf.got['write'])

hex(elf.plt['write'])

9 DynELF 通过信息泄露获得远程函数地址

 可以没有程序

p = process('./pwnme')

def leak(address):

data = p.read(address, 4)

return data

main   = 0xfeedf4ce

d = DynELF(leak, main)

d.lookup('system', 'libc')

如果有程序,速度会更快

d = DynELF(leak, main, elf=ELF('./pwnme'))

10 ROP 简化产生ROP链的操作

11 gdb.debug 和 gdb.attach

1 用gdb启动程序,并弹出新窗口与其交互

2 附加到一个程序上,pid/pwnlibs.tubes/socket都可以

12 args 快速访问所有的命令行参数

python foo.py REMOTE=1

args['REMOTE'] == '1'

13 一些实用工具

b64d('dGVzdA==')

b64e("test")

bits(511, zero = "+", one = "-") 把参数转换为位

bits_str(511) 得到'0000000111111111'

enhex("test") 得到'74657374'

isprint(c) 判断一个字符是否可打印

randoms(10) 返回'evafjilupm'

rol('abcdefg', 2) 得到'cdefgab'

unhex("74657374") 得到'test'

urldecode("test%20%41")

urlencode

14 net 查询网络接口

15 proc 查询进程

16 pause

17 safeeval 执行python代码,但不会产生副作用

18 其他

hexdump

read and write

enhex and unhex

more

group

align and align_down

urlencode and urldecode

which

wget

————————————–

与pwnlib.tubes的常见交互方式

recv()

recvuntil()

recvline()读取到'\n'

recvlines(n)

recvall() 读取到EOF


send()

sendline()会自动加换行符

——————————-

>>> 'b800000000'.decode('hex')

'\xb8\x00\x00\x00\x00'

>>> '\xb8\x00\x00\x00\x00'.encode('hex')

'b800000000'

转自:http://www.91ri.org/14382.html

------------持续更新ing------------

ROP链生成器

现在的exploit是越来越难,一般起手题都得是NX开启的,ROP这种以前都能出400分题的技术现在也就出50-100分题了非常惨,也许跟这个工具简化了ROP过程有关系?「误」

先简单回顾一下ROP的原理,由于NX开启不能在栈上执行shellcode,我们可以在栈上布置一系列的返回地址与参数,这样可以进行多次的函数调用,通过函数尾部的ret语句控制程序的流程,而用程序中的一些pop/ret的代码块(称之为gadget)来平衡堆栈。其完成的事情无非就是放上/bin/sh,覆盖程序中某个函数的GOT为system的,然后ret到那个函数的plt就可以触发system('/bin/sh')。由于是利用ret指令的exploit,所以叫Return-Oriented Programming。(如果没有开启ASLR,可以直接使用ret2libc技术)

好,这样来看,这种技术的难点自然就是如何在栈上布置返回地址以及函数参数了。而ROP模块的作用,就是自动地寻找程序里的gadget,自动在栈上部署对应的参数。

elf = ELF('ropasaurusrex')

rop = ROP(elf)

rop.read(0, elf.bss(0x80))

rop.dump()

# ['0x0000:        0x80482fc (read)',

#  '0x0004:      0xdeadbeef',

#  '0x0008:              0x0',

#  '0x000c:        0x80496a8']

str(rop)

# '\xfc\x82\x04\x08\xef\xbe\xad\xde\x00\x00\x00\x00\xa8\x96\x04\x08'

使用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) : 给出一个地址,反解析出符号

你可能感兴趣的:(PwnTools常见用法)