攻防世界-PWN进阶区-EasyPwn(XCTF 4th-WHCTF-2017)

这题其实不算难,不过漏洞比较隐蔽,需要细心才能发现

题目分析

checksec:
在这里插入图片描述
RELRO只是部分开启,考虑覆写GOT表

main:
在这里插入图片描述

echo:
在这里插入图片描述
在该函数中存在一个溢出:
v2的大小为1000(0x3E8),而我们的输入最大为0x438(输入缓冲区大小为0x400),如果我们的输入大于0x3E8,就会覆盖了v3的内容(%s),而%s是snprintf在向v2写入数据时格式化写入的数据的,如果被覆盖,之后我们再加上%x$p,格式化字符串就变成了"bb%x$p",snprintf就会把位置在x的数据写入v2中。
但是按理来说,在调用snprintf时%s就已经被传入,即使v3被修改应该影响不了snprintf,下面是某dalao对此的解释:

snprintf 把格式化字符串的地址记下来,然后,每次要处理一个字符时,先从地址处取格式化字符串,然后再根据格式化字符串来处理字符。由于地址是没变的,变的是地址里面的内容。

漏洞利用

根据上文的分析,可以发现echo函数中的格式化字符串漏洞,我们可以使用该漏洞修改free函数的got表项来得到shell,过程如下:

  1. 执行执行一次2,调用free,从而把free的地址加载进got表
  2. 用格式化字符串泄露 __libc_start_main+0xF0的地址,从而计算libc的基地址,payload: ‘a’ * 0x3E8 + ‘bb%397$p’,这里简单说一下为什么是397

我们现在snprintf的位置下断点,输入%p:%p:%p:%p:%p:%p.运行至此处,此时main的返回地址位于0x7fff0d97f298,而此时rsp为0x7fff0d97e650,(0x7fff0d97f298-0x7fff0d97e650)/8=393,而第三个为0x7fff0d97e650内存储的值,它是%4$p,因此0x7ffd7b5c0348应该是%(4+393)$p
在这里插入图片描述
在这里插入图片描述

  1. 利用格式化字符串泄露elf的基地址,payload:payload: ‘a’ * 0x3E8 + ‘bb%396$p’

在上面的调试中可以发现,在main函数返回地址的上面正好是init函数的地址(下图因为重新启动了进程所以地址变了)
在这里插入图片描述
因此我们把该地址减去0xDA0就是elf的基地址
在这里插入图片描述

  1. 把free的got表最低4个字节改成system的最低4个字节(他们两个只有最低4个字节不同),这样执行free操作就会调用system
    在这里插入图片描述

这里说一下如何构造%n覆写got
在snprintf中,被写入目标地址的字符数就是%n写入的值,而本题中这个值至少为1000,所以我们按如下方法构造payload

num = (system & 0xFFFF) - padding_num
print hex(num + padding_num)
payload = 'a' * padding_num + ('bb%' + str(num) + 'c%133$hn').ljust(16, 'a') + p64(free_got)
echo(payload)
num = (
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值