CTF PWN工具篇1-pwntools
0x00 引子
今年5月份参加红帽杯比赛,线下攻防赛,因为不懂PWN类题目,被吊打。很不爽,于是从6月初开始重新学习汇编,操作系统到7月底,算告一段落。参考书上教程,从零完成一个简陋的操作系统,只有一个进程。这个过程中最大的收获是对汇编的深入理解,以及程序加载执行的过程的熟悉。这对PWN来说是非常好的基础。现在开始学习PWN类题目。先来梳理下常用的工具。网上有人介绍过,我自己从初学者的角度来看待,尽可能详尽些。
后续会逐个详细介绍在做PWN题中使用到的功能点。
0x01 工具
古书云:人欲善其事,必先利其器。PWN类题目主要的工具有:
- pwntools:
这是基于Python开发的工具库。可以很方便的进行本地调试,远程利用。在github上可以找到。 - gdb:调试神器
- peda: 基于Python开发的gdb的插件,可以方便地显示当前栈,堆等信息。
- IDA:反汇编逆向的神器,F5一键查看伪代码。
目前用到的就这么多,后面有的话,再添加。0x02 pwntools
https://github.com/Gallopsled/pwntools,附上项目的github地址。这种正规的项目,都有完备的使用和开发说明文档,但这些文档太全面,从实用的角度来说,只挑现在用到的功能。2.1 安装
可以方便的使用pip进行安装:这是在Ubuntu系统下。如果安装过程中遇到问题了可以参考下官方文档https://docs.pwntools.com/en/stable/1
pip install pwntools
2.2 pwntools使用的一般流程
- 使用process/remote建立交互
- 通过调试,泄露堆栈信息找到利用点。
- 构造Payload利用
- 开启交互式shell,完成利用。
下面的介绍也是按照这样一个顺序进行。2.3 process/remote模块
PWN题一开始就要建立与可执行程序的交互。这就是通过这两个模块实现的。如果是本地调试的话,就使用process模块,本地调试好了就是远程利用拿FLAG了,用的是remote模块。
一般使用pwntools的脚本和可执行文件放在同一目录,方便管理。使用process的过程为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 引入模块
from pwn import process
# 生成实例
p = process('./pwn')
# 向进程发信息, 模拟用户的输入,在输入后添加回车,传递给进程。
p.sendline('some thing')
# 接收进程输出信息
# 交互时,要确定进程的状态,通过recvuntil,确保程序是运行在期望的状态下,
# 可以保证Payload是在合适的时机发送的。
p.recvuntil('some thing')
# 开启交互shell
# 这个时候要确认进程已已经成功get shell了,这个函数能开启一个shell。如果
# Payload 有异常这时脚本会异常中止。
p.interactive()2.4 ELF模块
大多数CTF比赛中的PWN题是基于Linux下可执行文件的。而Linux下可执行文件的格式为ELF。有时候我们需要从可执行文件中提取出一些有用信息,如函数的相对偏移地址,函数在GOT,PLT表的位置等,包括libc中一个信息。
这里再说一下自己对程序和进程的差别的理解。
也就是说进程不是简单地把程序拷贝到内存就可以执行了。这当中有许多历史和技术原因。程序是编译好的可执行文件,存在于磁盘上的。它的内容是按段组织的。可以使用objdump -x pwn2来查看。可以看到文件分成好多段,粘过来的格式乱掉了。
一般基本的有:
- .text: 代码段
- .data: 数据段
当然用C语言编写得到的可执行程序的段不会只有这2个。如果是汇编的话,就能做到只有这两个段。这里的.text段放的就是程序要执行的代码,是编译好的机器语言。.data段放的是变量,全局变量。因为局部变量是在栈上分配的。除了这两个,还一个header段,是用来说明这个程序的文件格式。
需要动态链接的程序还会有以下段: - .plt: procedure link table, 过程链接表
- .got: global offset table,全局偏移表。
当然这两个段跟PWN题强相关的。这两个段用于在加载时,重定位库函数的偏移地址的。可参考这篇文章聊聊Linux动态链接中的PLT和GOT(1)——何谓PLT与GOT
通过ELF加载了可执行文件,就可以方便地读取一些信息了。
1 | elf = ELF('./pwn') |
2.5 一些通用的模块
这些模块用来处理一些细节
如大小端字节的处理。这两个模块在由泄露信息生成payload时很好用,不需要再手动将32位数值转化为小端4字节二进制数,同时也方便将人可读的信息转化为机器可识别信息。
1 | # 将32位数值转化为小当前计算机上的表示,x86就是小端得到的是/x78/x56/x34/x12 |