Pwntools 工具使用

0x00 简介

Pwntools 是一个 CTF 框架和漏洞利用开发,可用于快速编写 exp 脚本。它拥有本地执行、远程连接读写、shellcode生成、ROP链构建、ELF文件解析、符号泄露等众多强大的功能。

  • 官方文档:https://pwntools.readthedocs.io/en/stable/

pwntools 分为两个模块,一个是 pwn,可以用 from pwn import * 导入到 python 中使用,该模块是专门针对 CTF 比赛优化的;另一个模块是 pwnlib,它更适合根据需要导入的子模块,常用于基于 pwntools 的二次开发。

0x01 模块简介

  • context:设置运行时变量
  • elf:操作 ELF 可执行文件和共享库
  • tubes:链接及信息传输模块,与 sockets、process、ssh 等进行连接
  • constants:包含各种体系结构和操作系统中的常量,如- - constants.linux.i386.SYS_stat
  • rop: ROP 利用工具,包括 rop、srop
  • gdb:调试,启用 gdb 调试
  • util:一些使用的小工具
  • log:日志记录管理
  • constants:包含各种体系结构和操作系统中的常量,如constants.linux.i386.SYS_stat
  • asm:汇编和反汇编
  • encoders:对 shellcode 进行编码
  • shellcraft:生成各种功能的汇编代码
  • runner:运行 shellcode,例如 run_assembly()
  • memleak:用于内存泄漏
  • dynelf:利用信息泄露远程解析函数
  • fmtstr:格式化字符串利用工具

0x02 pwntools 安装

apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools

# 可使用国内源提高 pip 下载速度
pip install pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

0x03 context 模块介绍

该模块用于设置运行时变量,如:目标系统、目标体系结构、字节序、日志等

context.clear()	        ## 清除当前运行时变量
context.arch = ‘arm’	## 设置架构:amd64、i386、arm、mips
context.os = ‘linux’	## 设置操作系统:linux
context.bits=32## 设置 32 位或 64 位:32、64
context.endian=‘little’	## 设置字节序:little、big
context.update(os=‘linux’, arch=‘amd64’, bits=64) ## 更新当前运行时变量
context.log_level=‘debug’	                      ## 设置日志级别:debug、info
context.log_file=/tmp/pwnlog.txt’	              ## 设置日志保存文件

0x04 tubes 模块介绍

在漏洞利用中,首先需要与目标文件或者目标服务器进行交互,这就要用到 tubes 模块。

- 常用命令
## 连接
  remote('ip',端口):远程
  process():本地
## 发送
  send(data) : 发送数据
  sendline(data) : 发送一行数据,相当于在数据末尾加\n
  sendafter(xxx,data):接收到 xxx 之后发送 data
## 接收
  recv(numb=4096, timeout=default) : 接收指定字节
  recvline(keepends=True) : 接收一行,keepends为是否保留行尾的\n
  recvuntil(delims, drop=False) : 一直读到 delims 的 pattern 出现为止
  recvrepeat(timeout=default) : 持续接受直到EOF或timeout
## 交互
  interactive()  直接进行交互,相当于回到shell的模式,在取得shell之后使用

模块中的其他函数

interactive()	  ## 交互模式,能够同时读写管道,通常在获得 shell 之后调用
recv(numb=1096, timeout=default)  ## 接受最多 numb 字节的数据
recvn(numb, timeout=default)	  ## 接受 numb 字节的数据
recvall()	                      ## 接受数据直到 EOF
recvline(keepends=True)	          ## 接受一行,可选择是否保留行尾的 ‘\n’
recvrepeat(timeout=default)	      ## 接受数据直到 EOF 或 timeout
recvuntil(delims,timeout=default) ## 接受数据直到 delims 出现
send(data)	      ## 发送数据
sendafter(delim, data, timeout=default)	 ## 相当于 recvuntil(delim, timeout) 和 send(data) 的组合
sendline(data)	  ## 发送一行,默认在行尾加 “\n”
sendlineafter(delim, data, timeout=default)	## 相当于 recvuntil(delim, timeout) 和 sendline(data) 的组合
close()	          ## 关闭管道

0x05 ELF 模块介绍

该模块用于操作 ELF 文件,包括符号查找、虚拟内存、文件偏移,以及修改和保存二进制文件等功能。

## 常用命令
elf = ELF('xx')
elf.address   elf 基地址
elf.bss()     elf bss 段
elf.plt['write']  查看 plt[] 表项对应地址
elf.got['write']  查看 got[] 表项对应地址
elf.symbols['write']  查看对应符号函数/数据所在地址
elf.search['/bin/sh']  返回一个迭代器,用next()获取

模块中的其他函数

asm(address, assembly)	 ## 汇编指令 assemnbly 并将其插入 ELF 的 address 地址处,需要使用 ELF.save() 函数来保存
bss(offset)	             ## 返回 .bss 段加上 offset 后的地址
checksec()	             ## 查看文件开启的安全保护
disable_nx()	         ## 关闭 NX
disasm(address, n_bytes) ## 返回对地址 address 反汇编 n 字节的字符串
offset_to_vaddr(offset)	 ## 将偏移 offset 转换为文件偏移
vaddr_to_offset(address) ## 将虚拟地址 address 转换为文件偏移
read(address, conut)	 ## 从虚拟地址 address 读取 count 个字节的数据
write(address, data)	 ## 在虚拟地址 address 写入data
section(name)	         ## 获取 name 段的数据

0x06 GDB 模块介绍

在编写漏洞利用的时候,常常需要使用 GDB 动态调试,该模块就提供了这方面的支持。两个常用函数如下:

gdb.attach(target, gdbscript = None):在一个新终端打开 GDB 并 attach 到指定 PID 的进程,或者一个 pwnlib.tubes 对象
gdb.debug(args, gdbscript = None):在新终端中使用 GDB 加载一个二进制文件
gdb.attach(1234)

bash = process(./bash’)
gdb.attach(bash, ’’’command’’’)

0x07 util.packing

可以设置小端和大端
p32    数字 -> bytes
p64
u32    bytes -> 数字
u64

0x08 fmt 模块

Pwntools pwnlib.fmtstr 模块提供了一些字符串漏洞利用工具。该模块中定义了一个 类 FmtStr 和一个函数 fmtstr_payload。其中 FmtStr 提供了自动话的字符串漏洞利用。fmtstr_payload 则用于自动生成格式化字符串 payload

class pwnlib.fmtstr.Fmtstr(execute_fmt, offset=None,padlen=0,numbwriteen=0)
## 参数说明
- execute_fmt(function)## 与漏洞进程进行交互的函数
- offset(int)## 你控制的第一个格式化程序的偏移量
- padlen(int)## 在 paload 之前添加的 pad 大小
- numbwriteen(int)## 已经写入的字节数

class pwnlib.fmtstr.fmtstr_payload(offset,writes, numbwriteen=0, write_size=bytes)
## 参数说明
- offset(int)## 你控制的第一个格式化程序的偏移量
- writes(dict)## 格式为{addr1:value,addr2:value2},用于往 addr 里写入 value 值(常用:printf_got)
- numbwriteen(int)## 已经由 printf 写入的字节数
- write_size(str)## 必须是 bytes、short 或 int。

0x09 shellcode 相关模块介绍

导入 pwntools 库,并使用对用函数生成 getshell 的汇编代码
在这里插入图片描述
在这里插入图片描述
使用 pwntools 中的 asm 对 sh 进行汇编。生成二进制代码:
在这里插入图片描述

0x0A Dynelf 相关模块介绍

Dynelf 是 pwntools 工具库中的一个类,使用 DynELF 时,我们需要使用一个 leak 函数作为必选参数。并且至少要提供一个指向目标 ELF 文件的指针或者目标ELF 文件通过 ELF 类实例化的对象(二者选其一),作为可选参数,以此来初始化一个 DynELF 类。
leak 函数需要使用目标程序本身的漏洞,泄露出 int 型参数 addr 对应的内存地址中的数据。由于 DynELF 会多次调用leak函数,这个 leak 函数必须能任意次使用,即不能泄露几个地址之后就导致程序崩溃。

## leak 函数模板
def leak(addr):                     ## addr 类型 int
  payload = xxx
  p.send (payload)    
  leak_data = p.recv(4)         ## 32位   
  ## leak_data = p.recv(8)    ## 64位
  print("%#x -> %s" %(addr, (leak_data or ''))))    
  return leak_data                  ## leak_data 必须返回 Bytes 类型的值

Dynelf:用法

dynelf_obj = DynELF(leak, elf=elf)
system_addr = dynelf_obj .lookup('system', 'libc')
success("system: %#x" %system_addr)
read_addr = dynelf_obj .lookup('read', 'libc')
success("read: %#x" %read_addr)

0x0B ROP 模块介绍

该模块可以帮助我们简单快速的生成 ROP chain

##  相关函数:
R = ROP(elfs(list), base(int), badchars(str))  类初始化
R.raw()                       ## 直接添加原始数据
R.call(funcname, args(list))  ## 调用某函数
R.funcname(arg1,rag2)         ## 调用某函数

R.dump()                      ## 显示 ROP chain 的内容
hexdump(r.chain())            ## 输出 ROP chain 信息

R.gadgets                     ## 显示所有 gadgets               
R.rax                         ## 显示与 rax 相关的 gadget 返回 Gadget 类
R.syscall                     ## 显示 syscall gadget
R.search()                    ## 按某条件搜索 gadget

R.chain()                     ## 生成 ROP chain 原理是通过 flat 进行封装

除了上述基础函数外, ROP 模块还可以自动生成某些攻击类型的 ROP chain,例如 ret2csu 的攻击链、栈迁移的攻击链、ret2dlresolver 的攻击链、SROP 的 SigreturnFrame。

  • ret2dlresolver 的使用方法

    dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"], data_addr = None)
    
    ## 生成对应的 ROP Chain
    rop.ret2dlresolve(dlresolve)
    ## 生成的 fake_data
    dlresolve.payload
    ## 保存 fake_data 的地址,默认会自动生成一个地址,所以我们在调用 read 时可以使用其默认的地址,
    ## 但是我们也可以在初始化时传入一个地址
    dlresolve.data_addr:
    
  • 13
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值