首页
社区
课程
招聘
[原创]fuzz在ctf中的基础利用
发表于: 2025-7-8 22:35 3311

[原创]fuzz在ctf中的基础利用

2025-7-8 22:35
3311

如果你也遇到过:

IDA反编译出来的数据结构充满了各种交叉引用与奇奇怪怪的数据结构,无论是逆向分析,还是用gdb调试出来都是越看越晕✋别担心,fuzzing会帮你解决一切


Fuzzing,中文一般翻译为“模糊测试”,是一种自动化测试技术,主要用于发现程序中的漏洞和异常行为。它的核心思想就像是:

向程序里灌各种奇怪、乱七八糟的输入,看看程序会不会崩溃

比如有个程序需要用户输入用户名,那Fuzzer就会试着输入:

* 超长字符串(比如上万字节的“AAAAAAAA...”)
* 特殊字符(比如 `"; DROP TABLE users; --` )
* 随机的二进制数据
* 不合规范的结构化数据(比如错误格式的PNG、PDF)

通过不断“瞎试”,来诱发程序中的各种bug,比如:

* 崩溃(Crash)
* 越界访问
* Use-After-Free(UAF)
* 内存泄露
* 未处理的异常

当我们完全看不懂数据结构的内部逻辑时,我们可以通过灌入大量数据,通过python捕捉uaf,overflow等错误,以此我们可以找到达成漏洞利用的具体手段,作为一个模块用来稳定获得一个漏洞,再在这个漏洞上不断利用,最后getshell


Fuzzerctf中一般由python脚本或文本文件+shell脚本组成,核心业务为捕捉漏洞触发记录输入数据

题目链接: nssctf


我们可以看到main中拥有五个操作函数:每个操作函数函数(insert,delet,edit,show和query)都由大量子函数进行数据结构的维护

这导致如果我们从IDA分析,逆向难度会非常大,通过题目名字和几个维护函数我们也能猜出来本题采用管理堆块的数据结构是R树


R树(Rectangle-tree 或 Region-tree是一种用来存储多维空间数据(比如矩形、坐标点、地理位置)的数据结构。它就像是空间版本的 B 树,用于高效地执行:


范围查询(range query):找出所有在某个区域内的点或图形

邻近查询(nearest neighbor):找出离你最近的对象

插入、删除、更新空间对象

比起传统的哈希表或数组,R树在"处理空间位置"的能力更 强大


R树是一种高度平衡的树结构,跟 B 树有点像,但它的每个节点存的不是单个值,而是:


一个“最小包围矩形(MBR,Minimum Bounding Rectangle)”——用来包住子节点或实际对象。

使用css表示为

综上,R树的结构非常复杂,出题人极有可能把漏洞藏在一个不起眼的维护函数中,导致我们使用传统逆向方法会非常困难


add函数

通过输入x,y确定堆块的索引

可以申请0x30的堆块,并以某种规则插上R树,可以且必须输入0x20的数据

delet函数


通过x,y索引寻找堆块,然后对堆块进行释放,置零(我们没法简单double free)

edit函数


通过x,y索引寻找堆块,编辑堆块,必须输入0x20的内容

show函数


通过x,y索引寻找堆块,使用write函数打印堆块中的内容

query函数


接收用户输入的矩形范围(左下角和右上角),然后在 R 树中查找所有在这个区域内的元素并输出它们的名字(功能与show重合)

我们首先猜测漏洞为uaf(每次输入的长度的限制很明显,不可能是溢出)

使用python脚本模拟我们的输入,要求保证

每次的输入随机化,在add与free中产生,且要求操作的下标随机

每次有效操作必须被记录下来

由于R树的大小有限制,所以当树被装满时必须退出并重新开始fuzz

要捕捉到产生的异常(此处要求捕捉double free)

根据这些要求可以写出如下脚本

运行以上脚本,最终我们可以得到一系列能够产生uaf漏洞的操作

经过测试,此处的uaf与传统uaf不同,此处如果清空堆块内容后进行double free,再申请两个堆块,并不会造成两个堆块重叠,而是第一个堆块消失,这给我们的后续利用带来了一定的困难


目前我们可以利用的包括

基于fuzz的堆风水已经让堆很乱了,再次堆风水创造一个double free对我而言基本上不可能

我们有一次任意地址写0x20字符,且必须写满0x20

teachebins从libc2.26引入,用于管理较小堆块,其中负责管理的数据结构称为teache_struct



这个结构体由一个int8/int16数组和一个指针数组组成,其中

回到题目,此时我们使用gdb观察劫持前的bins情况



这个是我们可以利用的double free chunk

由于每次申请的堆块太小了,我们想要劫持teache_struct需要分两次:number数组,指针数组

但是目前我们只能劫持一次,所以我们可以

保持(4,2)中不小于等于0,在(4,3)中写入想要劫持的地址


每次我们只能建立一个0x30的堆块,很明显放不进unsortbins


但是我们可以任意堆地址写,我们人为把堆的head中的size改一下不就行了


随便一找,找到几个总大小为0x220的堆块,且不直接接触top_chunk


修改后的堆如下



顺便在(4,2)中把0x220的teachebins数量改为7,这样就会直接进入unsortbins中了



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-7-8 23:06 被zer00ne编辑 ,原因:
上传的附件:
收藏
免费 3
支持
分享
最新回复 (1)
雪    币: 2557
活跃值: (10610)
能力值: (RANK:438 )
在线值:
发帖
回帖
粉丝
2
方便的话,麻烦上传一下附件,方便其他师傅复现,谢谢!
2025-7-8 22:43
1
游客
登录 | 注册 方可回帖
返回