PWN从入门到放弃(2)——Pwntools使用入门
上篇介绍了做CTF PWN题目的环境搭建,这篇我们将介绍如何利用Pwntools帮助我们更加快速的解题。
0x00 Pwntools介绍
Pwntools是一个CTF框架和漏洞利用开发库,用Python开发,旨在让使用者简单快速的编写exploit。几乎涵盖了做pwn题目脚本所需要用到的各种工具。
0x01 导入pwntools库
from pwn import *
0x02 建立连接
建立连接对于解pwn题尤为重要,比赛时,一般会给你一个pwn题目文件(一般是linux elf文件),还会给你一个nc地址。
- elf文件用于本地调试,发现漏洞
- nc地址用于攻击,获取flag
因此,我们需要与nc服务器和elf文件建立连接。
与程序文件建立连接
我们可以利用pwnlib.elf模块来连接程序文件。
elf = ELF('./process') #process为题目给出的程序文件
当我们连接到程序文件后,可使用内置方法快速查找函数地址等一系列功能。
与服务器建立连接
我们通过pwnlib.tubes模块来连接服务器
r = remote('ip',port) #在对应位置填入题目给出的ip和端口
在链接到服务器之后,可利用内置方法与服务器进行数据发送、接受等一系列交互操作。
0x03 设置目标架构和操作系统
我们可以通过设置目标架构和操作系统,来告诉pwntools我们程序的运行环境,pwntools会自动帮我们调整对应的编译格式和字节序。
context.arch = 'i386' #32位程序设置为i386;64位程序设置为amd64
context.binary = './process' #可以用这种方法自动设置成适当的值
context.os = 'linux'
context.log_level = 'debug' #可在屏幕上打印debug信息
context.terminal = ['tmux', 'splitw', '-h'] #告诉pwntools你的终端信息,方便后期动态调试
context.endian = 'big' #设置字节序为大端序,小端序设置为little
0x04 交互
在了解了上述的一些准备工作之后,我们可以尝试开始和程序进行交互了。
接收数据
r.recv() #接收数据
r.recvline() #接收一行数据
r.recvall() #接收数据,直到达到EOF
发送数据
r.send() #发送数据
r.sendline() #发送一行数据
r.sendlineafter('str',payload) #当接收到指定数据时,发送数据
shell交互
r.interactive()
0x05 获取函数地址
当我们成功连接到程序文件时,我们可以利用pwntools快速获取函数地址。
例如获取puts函数地址:
puts_got_addr = elf.got['puts'] #获取puts函数got表地址
puts_plt_addr = elf.plt['puts'] #获取puts函数plt表地址
puts_sym_addr = elf.symbols['puts'] #获取puts函数符号表地址
0x06 shellcraft
我们做题时,会经常用到shellcode,但是每次都从网上找对应的shellcode会大大降低我们的做题效率。shellcraft模块可以帮我们自动生成shellcode。
shellcraft.sh()
0x07 打包解包&汇编
在我们发送和接收数据时,会经常使用打包解包操作。
p32() #将数据打包成32位二进制格式,字节序由context.endian设置
p64() #将数据打包成64位二进制格式,字节序由context.endian设置
u32() #将32位二进制格式数据解包
u64() #将64位二进制格式数据解包
有时我们也会用到汇编操作,例如我们要发送shellcode:
shellcode = asm(shellcraft.sh())
r.sendline(shellcode)