fuzz模糊测试libexif详细解析
sn0w 历史精选 188浏览 · 2025-03-14 00:04

libexif介绍

漏洞介绍

环境搭建

libexif环境搭建



image.png
图片加载失败


搭建libexif成功

exif环境搭建

第一次的时候报错了 缺少popt

image.png
图片加载失败


安装一下再执行就可以了

image.png
图片加载失败


现在我们的环境就搭建完成了

漏洞分析-踩坑

以下是我的踩坑经历(想看正确分析 请跳转漏洞分析-正确)

根据漏洞描述可以发现在exif_entry_fix函数中

image.png
图片加载失败


去静态分析加漏扫 定位到: ps(后面根据crashes分析 发现漏扫定位错了 当个思路参考一下)

image.png
图片加载失败


image.png
图片加载失败


image.png
图片加载失败


接下来用afl-clang-lto重新编译:

libexif

exif

开始fuzz



image.png
图片加载失败


验证之后发现确实把程序打崩了 我们这里通过调试去看一下

image.png
图片加载失败




从这个调用栈可以看出来 exif_entry_fix - > exif_entry_realloc 导致的报错

继续跟踪发现就三个地方调用了 exif_entry_realloc 分别断点看逻辑发现最后是断在了0x014D9D这个位置 帮助我们更好的分析

但是跟进到后面 我感觉 非常的怪异 因为是进入realloc导致分配地址不对而形成的中止,并不符合上面两条CVE的描述 仔细看了一下 发现是我crash太少了 这可能是因为我只fuzz几分钟的原因....... 有点太急着调了 但是还是不对 跑了1小时还是有问题 并没有和cve描述的报错一样

这里踩坑发现是用的0.6.18版本去弄的 如果要复现的话建议是用0.6.14

漏洞分析-正确

换版本重新编译 具体指令和上面一样

这里提一个小tips虽然麻烦但会方便我们调试 此时已经有了crash能导致崩溃的样本 此时我们尽量不要用插桩的代码去分析了 利用已有样本 去调试正常编译的 会比较方便

我们可以通过下面的图直观的看出插桩对代码审计造成的影响、

fuzz前

image.png
图片加载失败


fuzz后

image.png
图片加载失败


这回fuzz了一个小时:

image.png
图片加载失败


fuzz出了三个 测试一下

image.png


并且分别看了几个样本

image.png
图片加载失败


image.png
图片加载失败


发现这回没啥问题了 然后我们把样本都保存下来 最后 正常编译进行分析

先对第二个样本进行分析

image.png
图片加载失败


调用链二分析

main->->exif_data_load_data->exif_data_load_data_content->memcpy_xxx

通过漏扫快速定位

image.png
图片加载失败


问题就在memcpy这里

image.png
图片加载失败


这里exif_data_alloc是自定义的一个创建堆块 这里v35是堆地址 我们直接断点断到这里可以发现 memcpy了多次 最后一次在0x21这个位置 出现了一字节溢出

image.png
图片加载失败


image.png
图片加载失败


这条路线的成因基本就到这里 但要是就这么结束了 那功利性就有点太强了,我们仔细去分析一下整个路线的逻辑 以及什么参数导致的这个漏洞产生

image.png
图片加载失败


这里分别设置了本地日志 然后取出参数 并且把这个参数进行检测 如果小于等于1 就弹出 帮助也就是--help的输出 然后

处理 IFD 字符串,使用 将字符串转换为 IFD 类型,并检查该 IFD 是否有效。如果无效,记录一条日志。exif_ifd_from_string

处理 EXIF 标签字符串,将其转换为实际的 EXIF 标签。如果标签无效,则记录错误日志。

这里加一点IFD和EXIF这方面的知识补充

image.png
图片加载失败


这个是-s指令

然后就进到了这个部分

image.png
图片加载失败


前面是创建一个内存管理实例 和 日志 然后把内容写入到创建的实例中

image.png
图片加载失败


image.png
图片加载失败


这里和上面的逻辑基本一样 都是创建一个实例 然后读入日志 和 内容

image.png
图片加载失败


image.png
图片加载失败


这里的话就是检测你loader的几个部分 buf bytes 是否都有 况且还有对字节的限制 如果太小会报错

上面这代码 就是各种检测和输出

这段代码从给定的数据块中读取 EXIF 信息,并按条目逐一存储。每个条目由 结构体表示,并包含标签、格式、组件数等信息。如果条目包含数据,还会分配内存并将数据存储在 中。特殊的 标签会单独处理,确保相关数据被正确存储。整个过程通过递归加载数据,直到所有的 EXIF 数据都被处理并存储到对应的 IFD 中

调用链一分析

main->exif_loader_get_data->exif_data_load_data->exif_get_sshort

image.png
图片加载失败


这里就是访问到不存在地址buf的代码 这里由于gdb优化代码编译我们不能直接调出 所以手动gdb调试查看一下参数

image.png
图片加载失败


可以看到offset的值是0xffffffff

前面对offset只有一个检测就是offset+6+2 要小于0x7c3很明显满足

就导致buf这段 直接加了0xffffffff 自然就不存在这个地址

修复

修复的话很简单

关于调用链一 就只需要加一个offset的检测就行、

关于调用链二 加一个对size大小和堆大小方面的检测 防止溢出

0 条评论
某人
表情
可输入 255

没有评论