pwntools是一个CTF框架和漏洞利用开发库,用Python开发,旨在让使用者简单快速的编写exploit。
这里简单的介绍一下pwntools的使用。
首先就是导入包
from pwn import *
你将在全局空间里引用pwntools的所有函数。现在可以用一些简单函数进行汇编,反汇编,pack,unpack等等操作。
将包导入后,我一般都会设置日志记录级别,方便出现问题的时候排查错误
context.log_level = 'debug'
这样设置后,通过管道发送和接收的数据都会被打印在屏幕上。
然后就是连接了,一般题目都会给你一个ip和一个端口,让你用nc连接访问,也有的题是让你通过ssh连接,这两种方式都可以通过pwntools实现。
# 第一种连接方式,通过ip和port去连接
conn = remote('127.0.0.1', 8888)
# 第二种连接方式,通过ssh连接
shell = ssh(host='192.168.14.144', user='root', port=2222, password='123456')
在编写exp时,最常见的工作就是在整数之间转换,而且转换后,它们的表现形式就是一个字节序列,pwntools提供了打包函数。
p32/p64: 打包一个整数,分别打包为32位或64位
u32/u64:解包一个字符串,得到整数
具体用法
# 比如将0xdeadbeef进行32位的打包,将会得到'\xef\xbe\xad\xde'(小端序)
payload = p32(0xdeadbeef) #pack 32 bits number
payload = p64(0xdeadbeef) #pack 64 bits number
打包的时候要指定程序是32位还是64位的,他们之间打包后的长度是不同的。
建立连接后就可以发送和接收数据了。
conn.send(data) #发送数据
conn.sendline(data) #发送一行数据,相当于在数据后面加\n
#接收数据,numb制定接收的字节,timeout指定超时
conn.recv(numb = 2048, timeout = default)
#接受一行数据,keepends为是否保留行尾的\n
conn.recvline(keepends=True)
#接受数据直到我们设置的标志出现
conn.recvuntil("Hello,World\n",drop=fasle)
conn.recvall() #一直接收直到 EOF
conn.recvrepeat(timeout = default) #持续接受直到EOF或timeout
#直接进行交互,相当于回到shell的模式,在取得shell之后使用
conn.interactive()
做过pwn题的人应该知道,如果是通过nc连接的话,一进去就相当于开启了一个进程,你只需要发送数据和程序交互就行了。
如果是通过ssh连接进去的,你需要手动创建一个进程,就跟正常通过ssh连接一样,你需要打开一个程序。
比如
>>> sh = process('/bin/sh') # 创建进程,这里开了一个shell
>>> sh.sendline('sleep 3; echo hello world;') # 发送命令
>>> sh.recvline(timeout=1) # 接收数据
''
>>> sh.recvline(timeout=5)
'hello world\n'
>>> sh.close() # 关闭进程
ELF模块用于获取ELF文件的信息,首先使用ELF()获取这个文件的句柄,然后使用这个句柄调用函数,和IO模块很相似。
下面演示了:获取基地址、获取函数地址(基于符号)、获取函数got地址、获取函数plt地址
>>> e = ELF('/bin/cat')
>>> print hex(e.address) # 文件装载的基地址
0x400000
>>> print hex(e.symbols['write']) # 函数地址
0x401680
>>> print hex(e.got['write']) # GOT表的地址
0x60b070
>>> print hex(e.plt['write']) # PLT的地址
0x401680
汇编与反汇编
>>> asm('mov eax, 0') #汇编
'\xb8\x00\x00\x00\x00'
>>> disasm('\xb8\x0b\x00\x00\x00') #反汇编
' 0: b8 0b 00 00 00 mov eax,0xb'
pwnlib.shellcraft模块包含生成shell代码的函数。
其中的子模块声明结构,比如
可以通过context设置架构,然后生成shellcode
context(arch='i386', os='linux')
shellcode = asm(shellcraft.sh())
调用gdb调试
在python文件中直接设置断点,当运行到该位置之后就会断下
from pwn import *
p = process('./c')
gdb.attach(p)
好了,关于pwntools的基本使用就介绍到这里,想要了解更多,可以去pwntools的官方文档去查询和探索。pwnable.kr里面有一些pwn的入门题,我记录了我的一些解题过程,可以去我的博客查看,365990646这个是极客方舟新手逆向群,可以加进来一起探讨问题。