2021-鹏城实验室网络安全技能大赛-pwn-babyheap 题解

本文详细分析了2021年鹏城实验室网络安全技能大赛的pwn题目-babyheap,重点讨论了off-by-null漏洞的利用方法,包括利用流程、libc泄漏和setcontext的使用。通过大型、小型bin及快速bin的特性构造fake chunk,最终实现漏洞利用。
摘要由CSDN通过智能技术生成

文件信息

  本题来自于2021年的鹏城实验室比赛的pwn题,题目链接如下:2021-鹏城实验室-pwn-babyheap
  该题目主要考查了libc-2.29.so及以上版本的off-by-null利用方式,本题目使用的是libc-2.31.so,知识点学习推荐博客glibc2.29下的off-by-null。同时作为堆题,保护全开,没有可用的show功能函数,必须使用IO_FILE来leak libc,知识点学习推荐博客pwn题堆利用的一些姿势 – IO_FILE。最后,题目使用了沙箱进制进行保护,禁用了execve系统调用,所以得用setcontext这个点,知识点学习推荐博客pwn堆利用的一些姿势 – setcontext。当然这里setcontext的使用略有不同,后面利用分析中会讲解。

漏洞定位

  在main函数由于使用了jmp rax,所以反编译会有点问题,导致后面的菜单功能调用不能直接看伪代码,不过问题不大直接看汇编就好了,具体功能很容易分析的,此处不再详述。
  这里我们直接定位到有漏洞的代码处,如下截图所示,有问题的代码位于具有edit功能的函数中。在已经修改完堆块内容后,edi函数中会调用如下代码对堆内容的每个字节做个检查,有一个字节的值是0xf的倍数的话都会导致v3值增加1,如果v3的值最后也是0xf的倍数,那么就会造成off-by-null漏洞。

vuln

利用分析

  好了,经过前面的分析,漏洞也算是比较直接的吧,其它菜单功能也很简单,所以基本上分析不会耗太多的时间,这里难的是在利用上。在最开始的题目信息介绍中,我已经介绍了相关的知识点,在利用思路上来说,其实也算是很直接,off-by-null漏洞点,没有leak函数,开了沙箱,每一步都是水到渠成的,难的是在多种知识考点的结合,编写exp确实要花费一定的时间。
  这里将完整的利用流程叙述一遍。首先是libc-2.31.so下的off-by-null漏洞利用,该利用步骤大致可以分为四步:第一,利用large bin构造一个fake chunk;第二,利用small bin的性质构造fd->bk = fake chunk;第三,利用fast bin的性质构造bk->fd = fake chunk;第四,利用off-by-null修改prev_size和chunk_in_use标志位,最后unlink完事。当然在编写过程中会略显繁琐,需要仔细并且要算好堆块的一些偏移。
  unlink之后的步骤是利用_IO_2_1_stdout_这个结构来泄露libc,具体操作的话需要将堆块分配到该结构体处,这里需要爆破一位(末三位是固定的),调试的话建议先关闭本地的随机化。之后我们修改其值为p64(0xfbad3887)+p64(0)*3 + p8(0)就会leak出libc信息。
  在泄露出libc后,我们就来到最后一大步了,首先我们先把orw链以及setcontext中的调用逻辑设置好。这里的细节在于,在libc-2.31.so中的setcontext是用rdx传递参数的,所以需要找一特殊的gadget来将rdi的参数传给rdx,具体见代码。最后我们再将堆块分配到free_hook上,将上述setcontext和orw组成的调用逻辑写在该堆块上,之后执行free就大功告成。

WP

  完整exp如下,注释写的很详细,大家可以细细分析一波。

from pwn import *


ld_path = ""
libc_path = "./libc.so.6"
# p = process([ld_path, "./babyheap"], env={"LD_PRELOAD":libc_path})
# p = process([ld_path, ""])
p = process("./babyheap", env={
   "LD_PRELOAD":libc_path})
# p = remote("")

# context.log_level = "debug"

r = lambda : p.recv()
rx = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
shell = lambda : p.interactive()


def add
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值