背景
Check Point Research (CPR) 在Windows图形设备接口(GDI)中发现了三个安全漏洞。我们及时向微软报告了这些问题,微软已在2025年5月、7月和8月的补丁星期二更新中修复了这些漏洞。
这些漏洞包括:
- CVE-2025-30388:评级为重要,被认为更有可能被利用
- CVE-2025-53766:评级为严重,可能允许远程攻击者在受影响系统上执行任意代码
- CVE-2025-47984:同样评级为重要,可能导致通过网络未经授权披露敏感信息
几何图形失控 - CVE-2025-30388
我们发现了与处理EmfPlusDrawString、EmfPlusFillRects和EmfPlusFillClosedCurve记录相关的三个独立崩溃。所有三个案例都有一个共同的根本原因:另一个记录为利用设置了舞台。然而,结果因执行期间处理的其他记录而异。
在GdiPlus.dll模块版本10.0.26100.3037中,ScanOperation::AlphaMultiply_sRGB()、ScanOperation::Blend_sRGB_sRGB_MMX()和EpAntialiasedFiller::OutputSpan()函数中发生了多个访问违规异常。这些异常在系统尝试读取或写入4000/0xFA0字节堆块末尾的内存时触发,或者在尝试访问保留但未分配的内存时触发。
此漏洞可能允许远程攻击者使用特制的EMF+元文件执行越界读取或写入内存操作。
在我们的崩溃样本中,作为重现漏洞的概念证明(PoC),EmfPlusClear记录位于元文件中的EmfPlusDrawString记录之前。此记录清除输出坐标空间并使用背景颜色和透明度进行初始化,如其Color字段所定义。该字段包含一个指定红、绿、蓝和alpha分量的EmfPlusARGB对象。此细节很重要,因为它允许攻击者在利用期间控制写入内存的值。
进一步调查显示,EmfPlusClear记录处理程序使用EpScanBitmap::Start()函数分配一个堆块来存储4000字节(0xFA0)。然后使用指定的EmfPlusARGB对象填充此缓冲区,该对象在处理EmfPlusDrawString记录期间经过AlphaMultiply_sRGB()函数的alpha乘法。
存储在ebx寄存器中的循环计数器从0x950开始。由于每次迭代将4字节对象写入ecx + edx处的目标缓冲区,当计数器达到0x567时,函数在1000字节后越界写入。
Alpha值乘以颜色值以确保透明区域(alpha值为0)不贡献任何颜色(R = G = B = 0)。因此,半透明区域中的颜色显得更暗,因为这些对象比不透明对象发出更少的光。
第四个字节是alpha值,范围可以从0x00到0xFF。将alpha值设置为0xFF允许攻击者几乎完全控制写入缓冲区的内容,因为RGB值保持不变。
补丁分析证实,在处理各种元文件记录期间发生的崩溃都有一个共同的根源:在观察到崩溃的其他记录之前的EmfPlusSetTSClip记录中存在无效的RECT对象。
处理无效的RECT对象会导致基于堆的缓冲区溢出,可能允许攻击者执行越界内存操作。攻击者可以通过使用各种其他元文件记录来写入或读取内存来利用此漏洞,因为损坏的EmfPlusSetTSClip记录为利用设置了舞台。
从Microsoft Word 365中的结果图像可以看出,每次渲染的输出都不同,这表明此崩溃样本泄漏内存,最终Word意外终止。此行为已经跨越了安全边界,因为如果攻击者可以读回渲染的图像(例如,在Web浏览器中使用JavaScript),则可能导致信息泄露。
微软在GdiPlus.dll版本10.0.26100.4061中的SetTSClipEPR::Play()处理程序函数中修复了此漏洞,通过引入ValidateAndSet()和IsRectValid()函数来验证RECT对象。
此错误在2025年5月补丁星期二的KB5058411中作为重要严重性的远程代码执行漏洞得到解决,跟踪为CVE-2025-30388。值得注意的是,此问题也影响Microsoft Office for Mac和Android。此外,MSRC的可利用性评估为"更可能被利用",表明此漏洞对攻击者来说是一个高价值目标。
负空间 - CVE-2025-53766
我们在处理EmfPlusDrawRects记录时发现了第四次崩溃。在GdiPlus.dll版本10.0.26100.4202中的ScanOperation::AlphaDivide_sRGB()函数中发生了访问违规异常,因为它尝试写入保留但未分配的内存。
此漏洞可能允许远程攻击者使用特制的EMF+元文件执行越界内存写入。
此问题与我们之前讨论的CVE-2025-30388漏洞类似。该错误是由EmfPlusSetTSClip记录中的无效RECT对象引起的,该记录位于发生崩溃的其他记录之前。在这个新案例中,漏洞源于受影响的EmfPlusDrawRects记录中的一系列EmfPlusRect对象。
EmfPlusDrawRects记录前面有一个EmfPlusObject记录,该记录指定在图形操作中使用的EmfPlusPen对象。EmfPlusPen对象定义与笔关联的图形画笔。画笔是纯色画笔,由EmfPlusARGB值表征。通过此值,攻击者可以控制eax寄存器中写入操作的源。
在位图图像中,扫描线是一行水平像素。逐行处理图像意味着一次处理一条扫描线,从左到右,从上到下。进一步分析显示,EpScanBitmap::NextBuffer()函数从未验证要处理的扫描线数量是否适合目标位图,这意味着如果调用请求的扫描线多于存在的扫描线,则可能诱使函数读取或写入图像底部边缘之外。
假设为缩略图生成分配的位置为100×100 (0x64 × 0x64)像素,PoC元文件中的矩形数据故意将扫描位置推到位图底部边缘之外,并触发越界写入。这些矩形中的任何一个都强制光栅化器(将矢量图形转换为像素网格)处理其Y坐标远超出位图0-99范围的扫描线。
微软在GdiPlus.dll版本10.0.26100.4946中的EpScanBitmap::NextBuffer()函数中修复了此漏洞,通过添加检查来检测请求的扫描线数量是否超过位图高度。该函数现在自动修剪请求的扫描线以适应剩余行,防止任何越界访问。
此漏洞在2025年8月补丁星期二的KB5063878中作为严重严重性的远程代码执行漏洞得到解决,跟踪为CVE-2025-53766。值得注意的是,此漏洞不需要特权或用户交互,并且可以通过网络远程利用,使其成为解析特制元文件的Web服务的高风险威胁。
未完成的事务 - CVE-2025-48984
我们在处理EMR_STARTDOC记录时发现了第五次崩溃,这立即似乎与CVE-2022-35837漏洞相关。在gdi32full.dll版本10.0.26100.3624中的StringLengthWorkerW()函数中发生了访问违规异常,同时尝试在288/0x120字节堆块末尾读取内存。
堆栈跟踪表明问题可能在于StringLengthWorkerW()函数,该函数对用户控制的数据执行长度检查,并假定输入是以空字符结尾的字符串。但是,如果提供的字符串不是以空字符结尾,则函数可能读取超出分配的缓冲区,导致潜在的信息泄露。
反编译的MRSTARTDOC::bPlay()函数源代码表明,CVE-2022-35837通过将值分配给lpszDocName和lpszOutput字段(如果它们各自的字段非空)通过存储在v5变量中的计算偏移量来解决。
越界读取发生是因为MRSTARTDOC::bPlay()函数验证记录内的字符串偏移量。特制的元文件可能填充lpszDocName字段中的第一个字符串,使其几乎到达记录的末尾。复制该字符串后,代码将其内部光标推进到该点之外,但对lpszOutput字段的下一个验证仍然将提供的偏移量视为相对于记录的原始基址。
这种差异允许攻击者提供一个通过MR::bValidOff()函数检查的值,同时实际指向堆块外部。由于找不到空终止符,StringLengthWorkerW()函数继续读取相邻内存,暴露其内容。崩溃样本通过将EMF_HEADER.nBytes字段设置为仅0x120 (288)字节来加剧问题,导致分配的缓冲区小于嵌入数据,并保证过度读取。
微软在gdi32full.dll版本10.0.26100.4652中的MRSTARTDOC::bPlay()处理程序函数中通过更正偏移算法修复了此漏洞。修补后的函数现在在重新验证之前将指针转换回记录开始的偏移量,并将相同的逻辑应用于lpszOutput字段。因此,检查与将被解引用的数据匹配。
此错误在2025年7月补丁星期二的KB5062553中作为重要严重性的信息泄露漏洞得到解决,跟踪为CVE-2025-47984。MSRC将其分类为CWE-693:保护机制失败,在这种情况下,确实意味着解决CVE-2022-35837的安全修复不完整。
结论
我们在Windows GDI中发现了可能对系统安全产生严重影响的漏洞。我们对EMF+文件的广泛调查表明,要领先于潜在威胁需要持续的关注和适应。通过分享这些发现,我们希望提高认识,并为所有Windows用户提供有价值的见解和建议以增强安全性。
安全漏洞可能持续多年未被发现,通常由于不完整的修复而重新出现。特定的信息泄露漏洞,尽管通过安全补丁正式解决,但由于原始问题仅得到部分修复,仍然活跃多年。这个例子突显了研究人员面临的基本难题:引入漏洞通常很容易,修复它可能很困难,而验证修复是否彻底有效则更具挑战性。
这些问题突显了为什么全面和持续的安全测试至关重要,使用必须不断更新和改进的验证技术。供应商和安全研究人员之间的密切合作可以大大增强这一努力,包括与最初报告问题的研究人员共享计划的修复。这种协作方法增加了额外的审查层,有助于及早发现潜在差距,并加强软件生态系统的整体安全性。