PWN从入门到放弃(2)——Pwntools使用入门

2024-01-30 14:15:47 浏览数 (1)

上篇介绍了做CTF PWN题目的环境搭建,这篇我们将介绍如何利用Pwntools帮助我们更加快速的解题。

0x00 Pwntools介绍

Pwntools是一个CTF框架和漏洞利用开发库,用Python开发,旨在让使用者简单快速的编写exploit。几乎涵盖了做pwn题目脚本所需要用到的各种工具。

0x01 导入pwntools库

代码语言:javascript复制
from pwn import *

0x02 建立连接

建立连接对于解pwn题尤为重要,比赛时,一般会给你一个pwn题目文件(一般是linux elf文件),还会给你一个nc地址。

  • elf文件用于本地调试,发现漏洞
  • nc地址用于攻击,获取flag

因此,我们需要与nc服务器和elf文件建立连接。

与程序文件建立连接

我们可以利用pwnlib.elf模块来连接程序文件。

代码语言:javascript复制
elf = ELF('./process') #process为题目给出的程序文件

当我们连接到程序文件后,可使用内置方法快速查找函数地址等一系列功能。

与服务器建立连接

我们通过pwnlib.tubes模块来连接服务器

代码语言:javascript复制
r = remote('ip',port) #在对应位置填入题目给出的ip和端口

在链接到服务器之后,可利用内置方法与服务器进行数据发送、接受等一系列交互操作。

0x03 设置目标架构和操作系统

我们可以通过设置目标架构和操作系统,来告诉pwntools我们程序的运行环境,pwntools会自动帮我们调整对应的编译格式和字节序。

代码语言:javascript复制
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 交互

在了解了上述的一些准备工作之后,我们可以尝试开始和程序进行交互了。

接收数据
代码语言:javascript复制
r.recv() #接收数据
r.recvline() #接收一行数据
r.recvall() #接收数据,直到达到EOF
发送数据
代码语言:javascript复制
r.send() #发送数据
r.sendline() #发送一行数据
r.sendlineafter('str',payload) #当接收到指定数据时,发送数据
shell交互
代码语言:javascript复制
r.interactive()

0x05 获取函数地址

当我们成功连接到程序文件时,我们可以利用pwntools快速获取函数地址。

例如获取puts函数地址:

代码语言:javascript复制
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。

代码语言:javascript复制
shellcraft.sh()

0x07 打包解包&汇编

在我们发送和接收数据时,会经常使用打包解包操作。

代码语言:javascript复制
p32() #将数据打包成32位二进制格式,字节序由context.endian设置
p64() #将数据打包成64位二进制格式,字节序由context.endian设置
u32() #将32位二进制格式数据解包
u64() #将64位二进制格式数据解包

有时我们也会用到汇编操作,例如我们要发送shellcode:

代码语言:javascript复制
shellcode = asm(shellcraft.sh())
r.sendline(shellcode)

0 人点赞