GIMP Heap Overflow Re-Discovery and Exploitation (CVE-2025–6035)
Craig Young
5 min read · Jun 15, 2025
481
Listen
Share
四月份,我分享了一篇操作指南,介绍如何编写一个用于发现可疑 malloc 调用的 Ghidra 脚本。在上篇文章中,我通过分析一个已知的漏洞程序对该脚本进行了测试。由此引发的常见问题之一,也是我将在 Black Hat 上更详细讲解的内容,就是如何评估这个(及其他)脚本的发现结果。该脚本标记了 6 处可疑的 malloc 调用,但我直接跳到了 Synacktiv 识别出的那个位置——因为识别出了函数名,而不是逐个检查每个调用点。本文将再次用该脚本测试一个真实世界的漏洞,但这次我会更详细地完整确认一个最近发现的漏洞的可利用性。
目标选择
我首先让一个 LLM 帮助找一个好的例子:
用 LLM 寻找目标
这看起来是一个合理的候选,于是我拉取了一个存在漏洞的 Ubuntu 软件包并解压找到漏洞程序文件:
$ apt download gimp=2.10.36-3build3 && dpkg-deb -x gimp*.deb ./vuln
分析 GIMP 插件
我在 ./vuln/usr/lib/gimp/2.0/plug-ins/despeckle/despeckle 中找到了存在漏洞的 despeckle 插件。我将该程序加载到 Ghidra 中进行分析,并运行我的脚本,得到以下控制台输出:
控制台错误:缺少 malloc
原因是 GIMP 使用了 glib,因此我们需要脚本查找对 g_malloc 的调用,而不是 malloc,更新如下:
将脚本更新为查找 g_malloc
应用该更改后重新运行脚本,得到 4 个潜在可疑的 g_malloc 调用列表:
可疑的 g_malloc 调用
审查发现
下一步,我加载反编译插件并跳转到第一个位置:
(按回车或点击查看全尺寸图像)
在可疑 g_malloc 处的反编译视图
有问题的 g_malloc 调用使用了 lVar9,我们可以看到它是通过三个其他变量相乘计算得到的:
lVar9 = (long)(iVar1 * iVar3 * iVar4);
uVar7 = g_malloc(lVar9);
uVar8 = g_malloc(lVar9);
在此截图中我们还可以看到 iVar1 和 iVar3 是从函数的某个参数的 struct 成员赋值的。该参数作为第一个实参传递给外部函数 gimp_preview_get_position。根据 GIMP 开发者文档,该函数的第一个参数是一个 GimpPreview。通过进一步分析,应该可以确定这些偏移量引用的值(无需查看源代码)。一种方法是在调试器下测试,另一种方法是查找对该 struct 偏移量的其他引用,然后寻找日志消息或下游用法来推断成员变量是什么。
在这种情况下,我通常会记下这两个发现看起来很有希望,然后继续分析 00104575 处的下一个发现:
(按回车或点击查看全尺寸图像)
下一个可疑 g_malloc 调用的反编译
这次我们看到另外两个 g_malloc 调用,其中 size 参数是通过乘法计算的。使用 Ghidra 中的光标文本高亮,我们可以快速发现这些变量很可能是由外部函数 gimp_drawable_mask_intersect 设置的:
(按回车或点击查看全尺寸图像)
使用光标高亮追踪变量
查阅该库调用的文档,我们看到:
gboolean gimp_drawable_mask_intersect(GimpDrawable* drawable,
gint* x, gint* y,
gint* width, gint* height)
由此我们可以识别出第 4 个和第 5 个参数分别代表 width 和 height。还需要注意,这个乘法中的第三个因子来自 babl_format_get_bytes_per_pixel。这在上下文中有意义,因为应用程序需要根据像素数量(高乘宽)乘以每像素字节数来计算分配多少字节。
更大视角
如果回看之前的 g_malloc 调用,它们也遵循相同的形式:将两个数字与每像素字节数相乘。可以合理地认为输入的值实际上也是高度和宽度。很可能会因为对具有超大画布的图像运行此插件而导致堆内存损坏。话虽如此,当然可能有多种因素会复杂化甚至使此类 bug 无法被利用。这种情况下需要问的问题是:软件是否能够处理如此大的可绘制区域,从而能够触发这个 bug。
概念验证测试
为了回答这个问题,我再次求助于 LLM,这次让它生成一个 Python 脚本来生成一个具有精心构造尺寸的 PNG 文件。我用 GIMP for Windows 打开生成的文件,它顺利打开,让我能够应用 Despeckle 增强滤镜:
(按回车或点击查看全尺寸图像)
你能增强那个吗?
这弹出了一个配置滤镜的模态窗口:
Despeckle 插件模态窗口
点击该对话框的“确定”后,再次点击画布,我得到了崩溃:
(按回车或点击查看全尺寸图像)
来自 PoC 文件的 GIMP 崩溃
结论
大多数样本没有这个例子这么直接,但评估这个 malloc 检查器结果的一般思路是:回溯算术运算的输入,寻找边界检查,并考虑输入是否受攻击者控制(例如污点数据)。有时会存在实际限制,使得变量不可能溢出。一个常见的例子是当 strlen 值相加来计算分配大小时。虽然技术上可能可以利用,但这通常需要实际提供大量 GB 级的输入数据,往往不切实际。
如果你觉得这类分析有趣,并想了解更多关于我分析编译程序和固件的技术,欢迎今年夏天来拉斯维加斯参加我的 Black Hat USA 培训课程(周六/周日)。在这两天的密集课程中,我将讲解像这样的示例,并给学生时间自己探索和提问。更多培训材料中的示例可以在我的 Medium 和 GitHub 个人资料(用户名 cy1337)中找到。 CSD0tFqvECLokhw9aBeRqsr9OwBdVGXlAi/DE7rpJABs6O5nLHI41kzSMGlHPaveBa/x85FOEMFEO80vewpQ0r4N9QFbyZuP/MlhcWRFgL0=