网易首页 > 网易号 > 正文 申请入驻

Windows图像解析Fuzzing(一):颜色配置文件

0
分享至

图像解析和渲染是任何现代操作系统(OS)的基础功能。同时,图像解析也是一个易于访问的攻击面,这一功能可以导致远程代码执行或信息泄露风险,对攻击者来说非常有价值。在这一系列文章中,我将回顾Windows操作系统内置的图像解析器和相关文件格式,特别关注构建工具、寻找语料库(Corpus)以及通过模糊测试(Fuzzing)发现漏洞的过程。在第一部分中,我们重点分析颜色配置文件。该文件并不是图像格式本身,而是规则嵌入在图像中的颜色。

二、ICC颜色配置文件分析

在维基百科上,提供了对ICC颜色配置文件的定义:“在颜色管理过程中,根据国际颜色协会(ICC)发布的标准,ICC配置文件是一组定义颜色输入输出设备以及颜色空间的数据。配置文件通过定义设备源或目标颜色空间与配置文件连接空间(PCS)之间的映射,描述特定设备的颜色属性或预览要求。这里的PCS可以是CIELAB (L*a*b*),或者是CIEXYZ。可以使用定义插值(Interpolation)的表格来指定映射,也可以通过一系列参数进行转换。

简而言之,ICC颜色配置文件是一个二进制文件,该文件会嵌入到图像中,并在ICC支持的软件处理图像时进行解析。

三、ICC规范

ICC规范大概有100页,相对比较容易浏览。通读规范可以更好地理解文件格式,不同类型的颜色配置文件以及颜色转换背后的数学原理。此外,了解文件格式的内部结构可以为我们提供信息,以便更好地优化模糊测试、选择良好的语料库以及准备模糊测试的字典。

四、关于Windows颜色管理

从Windows 95开始,发布了图像颜色管理(ICM)的1.0版本,从Windows 98以后开始发布2.0版本。从Windows Vista开始,对Windows色彩系统(WCS)1.0版本进行了大幅改动。ICC颜色配置文件是二进制文件,而WCS颜色配置文件则使用XML作为其文件格式。在这篇文章中功能,我们专注于分析ICC颜色配置文件。

Microsoft曾发布过支持的Windows API的列表,其中就包含一些名称非常明显的API,例如OpenColorProfile,我们可以看到它是在MSCMS.dll中实现的。这个DLL是通用入口点,支持加载Microsoft的颜色管理模块(CMM)和第三方颜色管理模块(例如Adobe的CMM)。Microsoft的CMM(即ICM)可以在system32目录中找到,名称为ICM32.dll。

ICM32:

Windows的CMM是在Windows 95时代由第三方编写的,发展至今仍然或多或少地包含当时的代码,但已经经过了数十年来的安全修复。既然是如此古老的模块,我们就有希望在其中发现新的漏洞。但是,这也是一个非常小的模块,可能经过了多轮审计和模糊测试,包括内部产品安全团队和外部研究人员,这个事实在一定程度上降低了我们找到漏洞的希望。我们检索近期发现的ICM32漏洞,可以发现Project Zero和ZDI的研究人员在2017-2018年期间发现了多个漏洞,但从2019年开始就没有找到更多的研究成果。

五、构建工具

尽管在MSDN上有ICM API的列表,但我们需要找到Windows用于所有ICC相关操作的API序列。要查找API序列,一种方式是搜索Windows DLL和EXE的反汇编并寻找用到的颜色配置文件API,另一种方式是找到适用于开源色彩管理系统(例如Little CMS,LCMS)的工具。使用这两种方式,最终共同指向了很少的几个API,这些API具有打开颜色配置文件和创建颜色转换的功能。

基于上述信息,我编写了一个简单的初始工具:

#include < stdio.h >

#include < Windows.h >

#include < Icm.h >

#pragma comment(lib, "mscms.lib")

int main(int argc, char** argv)

{

char dstProfilePath[] = "sRGB Color Space Profile.icm";

tagPROFILE destinationProfile;

HPROFILE hDstProfile = nullptr;

destinationProfile.dwType = PROFILE_FILENAME;

destinationProfile.pProfileData = dstProfilePath;

destinationProfile.cbDataSize = (strlen(dstProfilePath) + 1);

hDstProfile = OpenColorProfileA(&destinationProfile, PROFILE_READ,

FILE_SHARE_READ, OPEN_EXISTING);

if (nullptr == hDstProfile)

{

return -1;

}

tagPROFILE sourceProfile;

HPROFILE hSrcProfile = nullptr;

HTRANSFORM hColorTransform = nullptr;

DWORD dwIntent[] = { INTENT_PERCEPTUAL, INTENT_PERCEPTUAL };

HPROFILE hProfileList[2];

sourceProfile.dwType = PROFILE_FILENAME;

sourceProfile.pProfileData = argv[1];

sourceProfile.cbDataSize = (strlen(argv[1]) + 1);

hSrcProfile = OpenColorProfileA(&sourceProfile, PROFILE_READ,

FILE_SHARE_READ, OPEN_EXISTING);

if (nullptr == hSrcProfile)

{

return -1;

}

hProfileList[0] = hSrcProfile;

hProfileList[1] = hDstProfile;

hColorTransform = CreateMultiProfileTransform(

hProfileList,

2,

dwIntent,

2,

USE_RELATIVE_COLORIMETRIC | BEST_MODE,

INDEX_DONT_CARE

);

if (nullptr == hColorTransform)

{

return -1;

}

DeleteColorTransform(hColorTransform);

CloseColorProfile(hSrcProfile);

CloseColorProfile(hDstProfile);

return 0;

}

六、寻找语料库和字典

在互联网上,可以找到大量提供颜色配置文件的网站。颜色配置文件的另一个主要来源是图像。有许多图像文件都包含颜色配置文件,但需要一些工具将颜色配置文件转储到单独的文件中。

简单浏览规范,我们还可以保证语料库至少包含来自7个不同颜色配置文件的所有样本。而将它与代码覆盖率信息结合,可以准备第一套语料,用于模糊测试。

我们可以在梳理规范的过程中,创建唯一标签名称和对应值的列表,从而准备字典,帮助模糊工具查找其他代码路径。另外,还可以从LCMS这样的开源模糊测试尝试过程中找到字典。

七、模糊测试

我使用16核主机对第一套语料进行模糊处理,同时将来自MSCMS.dll和ICM32.dll的代码覆盖率信息作为我的模糊工具的反馈。在几天后,开始出现崩溃。

八、CVE-2020-1117:InitNamedColorProfileData中的堆溢出

在尝试越界读取时,icm32!SwapShortOffset中发生了以下崩溃:

0:000 > r

rax=0000023690497000 rbx=0000000000000000 rcx=00000000000000ff

rdx=000000000000ffff rsi=0000023690496f00 rdi=0000023690496fee

rip=00007ffa46bf3790 rsp=000000c2a56ff5a8 rbp=0000000000000001

r8=0000000000000014 r9=0000023690497002 r10=0000000000000014

r11=0000000000000014 r12=000000c2a56ff688 r13=0000023690492de0

r14=000000000000000a r15=000000004c616220

iopl=0 nv up ei ng nz ac pe cy

cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000293

icm32!SwapShortOffset+0x10:

00007ffa`46bf3790 0fb610 movzx edx,byte ptr [rax] ds:00000236`90497000=??

0:000 > !heap -p -a @rax

address 0000023690497000 found in

_DPH_HEAP_ROOT @ 23690411000

in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)

23690412b60: 23690496f00 100 - 23690496000 2000

00007ffa51644807 ntdll!RtlDebugAllocateHeap+0x000000000000003f

00007ffa515f49d6 ntdll!RtlpAllocateHeap+0x0000000000077ae6

00007ffa5157babb ntdll!RtlpAllocateHeapInternal+0x00000000000001cb

00007ffa51479da0 msvcrt!malloc+0x0000000000000070

00007ffa46bf3805 icm32!SmartNewPtr+0x0000000000000011

00007ffa46bf37c8 icm32!SmartNewPtrClear+0x0000000000000014

00007ffa46c02d05 icm32!InitNamedColorProfileData+0x0000000000000085

00007ffa46bf6e39 icm32!Create_LH_ProfileSet+0x0000000000004e15

00007ffa46bf1973 icm32!PrepareCombiLUTs+0x0000000000000117

00007ffa46bf1814 icm32!CMMConcatInitPrivate+0x00000000000001f4

00007ffa46bf12a1 icm32!CWConcatColorWorld4MS+0x0000000000000075

00007ffa46bf11f4 icm32!CMCreateMultiProfileTransformInternal+0x00000000000000e8

00007ffa46bf1039 icm32!CMCreateMultiProfileTransform+0x0000000000000029

00007ffa48f16e6c mscms!CreateMultiProfileTransform+0x000000000000024c

00007ff774651191 ldr+0x0000000000001191

00007ff7746514b4 ldr+0x00000000000014b4

00007ffa505a7bd4 KERNEL32!BaseThreadInitThunk+0x0000000000000014

00007ffa515aced1 ntdll!RtlUserThreadStart+0x0000000000000021

icm32!SwapShortOffset读取无符号的短值,对其进行bswap,并将它们存储在相同的位置,这会导致读写原语崩溃。

反编译的SwapShortOffset:

unsigned __int16 *__fastcall SwapShortOffset(void *sourceBuff, unsigned int offset, unsigned int len)

{

unsigned __int16 *endBuff; // r9

unsigned __int16 *result; // rax

endBuff = (sourceBuff + len);

for ( result = (sourceBuff + offset); result < endBuff; ++result )

*result = _byteswap_ushort(*result); // read, bswap and write

return result;

}

崩溃的函数icm32!SwapShortOffset并不能立即指向导致该问题的根本原因。为此,我们需要查看icm32!InitNamedColorProfileData。

反编译的InitNamedColorProfileData:

__int64 __fastcall InitNamedColorProfileData(__int64 a1, void *hProfile, int a3, _DWORD *a4)

{

...

...

errCode = CMGetPartialProfileElement(hProfile, 'ncl2', 0, pBuffSize, 0i64); // getting size of ncl2 element

if ( errCode )

return errCode;

minSize = pBuffSize[0];

if ( pBuffSize[0] < 0x55 )

minSize = 0x55;

pBuffSize[0] = minSize;

outBuff = SmartNewPtrClear(minSize, &errCode); // allocating the buffer for ncl2

...

...

errCode = CMGetPartialProfileElement(hProfile, 'ncl2', 0, pBuffSize, outBuff); // reading ncl2 elements to buffer

if ( !errCode )

{

...

...

totalSizeToRead = count * totalDeviceCoord;

if ( totalSizeToRead < 0xFFFFFFFFFFFFFFAEui64 && totalSizeToRead + 0x51 <= pBuffSize[0] ) // totalSizeToRead + 0x51 <= element size?

{

currPtr = outBuff + 0x54; // wrong offset of 0x54 is used

...

...

do

{

SwapShortOffset((currPtr + 0x20), 0, 6u);

...

--count;

}while(count)

在这里,代码尝试读取“ncl2”标签/元素,并从文件中获取流的大小。一个缓冲区会被分配,并再次进行相同的调用,以读取元素ncl2的完整内容。该缓冲区将被解析,以查找设备位置的计数和编号,并通过确保读写操作位于缓冲区大小中来验证该值。其中存在一个漏洞,用于验证的偏移量(0x51)小于缓冲区指针的偏移量(0x54),该漏洞导致可以超过边界读写3个字节。

该漏洞的修复方法非常简单,将用于验证的偏移量修改为0x54即可,这也是Microsoft实际修复此漏洞的方式。

九、其他漏洞

在分析上面的漏洞时,我们发现过程中会使用到CMGetPartialProfileElement函数读取大小、进行分配和读取内容。而这种模式可能会引入漏洞,例如大小不受限制、整数溢出、导致偏移量增加等。我决定分析这个函数,并寻找ICM32.dll中是否存在这样的实例。

最终发现有3个实例具有未经检查的偏移量访问,分别是:CMConvIndexToNameProfile、CMConvNameToIndexProfile和CMGetNamedProfileInfoProfile。所有这些函数都可以通过导出的、有详细说明的MSCMS函数进行访问,分别是ConvertIndexToColorName、CMConvertColorNameToIndex和GetNamedProfileInfo。

反编译后的CMConvIndexToNameProfile:

__int64 __fastcall CMConvIndexToNameProfile(HPROFILE hProfile, __int64 a2, __int64 a3, unsigned int a4)

{

...

...

errCode = CMGetPartialProfileElement(hProfile, 'ncl2', 0, pBuffSize, 0i64); // read size

if ( !errCode )

{

allocBuff = SmartNewPtr(pBuffSize[0], &errCode);

if ( !errCode )

{

errCode = CMGetPartialProfileElement(hProfile, 'ncl2', 0, pBuffSize, allocBuff); // read to buffer

if ( !errCode )

{

SwapLongOffset((allocBuff + 12), 0, 4u); // 12 > *pBuffSize ?

SwapLongOffset((allocBuff + 16), v12, v13);

在CMConvIndexToNameProfile和其他两个函数中,我们发现了漏洞,并没有检查ncl2元素的最小长度,且偏移量12和16可以直接访问以进行读取和写入。那么如果allocBuffer的大小小于12,就可以实现对allocBuffer的越界读写。

由于在Windows中没有二进制文件使用这些函数,因此Microsoft决定不会立即修复这三个漏洞。此外,我们也没有找到使用这些API的任何Windows软件或第三方软件。

十、总结

在这一系列文章的第一部分中,我们对颜色配置文件进行了深入分析,编写工具并成功找到了多个漏洞。请大家继续关注第二部分,在第二部分中,我们将分析很少有人研究的一类漏洞——内存未初始化漏洞。

参考及来源:https://www.fireeye.com/blog/threat-research/2020/09/fuzzing-image-parsing-in-windows-color-profiles.html

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
中国队晋级决赛第2天,安东尼奥喜获新身份?日本球员放出豪言!

中国队晋级决赛第2天,安东尼奥喜获新身份?日本球员放出豪言!

大秦壁虎白话体育
2026-01-22 20:32:30
世界级铁矿首船矿石直抵中国!澳巴垄断被破,美西方铁矿石霸权的噩梦来了!

世界级铁矿首船矿石直抵中国!澳巴垄断被破,美西方铁矿石霸权的噩梦来了!

华山穹剑
2026-01-22 20:13:41
排超四强:上海女排一枝独秀,江苏靠吴梦洁,山东北京都不稳定

排超四强:上海女排一枝独秀,江苏靠吴梦洁,山东北京都不稳定

金毛爱女排
2026-01-23 00:00:03
向余望爆发了 20号被低估了!有美甲少年能出线吗?刘诚宇可惜了

向余望爆发了 20号被低估了!有美甲少年能出线吗?刘诚宇可惜了

刀锋体育
2026-01-22 20:17:45
约旦、阿联酋、印尼、巴基斯坦、土耳其、沙特、卡塔尔、埃及发表联合声明!普京表态

约旦、阿联酋、印尼、巴基斯坦、土耳其、沙特、卡塔尔、埃及发表联合声明!普京表态

每日经济新闻
2026-01-22 07:35:15
国羽2胜1负!男双提前丢冠,陈雨菲PK世界冠军,混双剑指2席8强!

国羽2胜1负!男双提前丢冠,陈雨菲PK世界冠军,混双剑指2席8强!

刘姚尧的文字城堡
2026-01-22 17:04:47
高市孤注一掷,誓言备战台海!中日联合国交锋,中方重提东京审判

高市孤注一掷,誓言备战台海!中日联合国交锋,中方重提东京审判

知鉴明史
2026-01-22 06:25:03
李昊:在海外踢球时因位置问题机会有限;目前想先把中超踢好

李昊:在海外踢球时因位置问题机会有限;目前想先把中超踢好

懂球帝
2026-01-22 21:36:19
中方已做好最坏打算!南海发生激烈对峙,黄岩岛突现072登陆舰队

中方已做好最坏打算!南海发生激烈对峙,黄岩岛突现072登陆舰队

老范谈史
2026-01-22 01:41:37
沪银收涨5.68%

沪银收涨5.68%

财联社
2026-01-23 02:32:05
藏得很深的“亲美疏中”的郑丽文,佩服国台办迟迟未发出的邀请函

藏得很深的“亲美疏中”的郑丽文,佩服国台办迟迟未发出的邀请函

开着车去流浪
2026-01-21 23:52:57
委内瑞拉已经倒下,另一个反美兄弟绝不能倒,中国这次终于出手了

委内瑞拉已经倒下,另一个反美兄弟绝不能倒,中国这次终于出手了

吕甒极限手工
2026-01-23 01:20:43
湖北一男子勇救落水女,3个月后却将女子杀害,真相让人冒出冷汗

湖北一男子勇救落水女,3个月后却将女子杀害,真相让人冒出冷汗

谈史论天地
2026-01-21 18:30:03
“8大症状说明你已经老了”,你占了几项?我全占了!!

“8大症状说明你已经老了”,你占了几项?我全占了!!

社评
2026-01-02 12:24:58
步行者鹈鹕谈判交易!核心框架马瑟林换米西 另有两队也想抢中锋

步行者鹈鹕谈判交易!核心框架马瑟林换米西 另有两队也想抢中锋

罗说NBA
2026-01-23 06:06:27
男人注意:女人若有过很多男人,多半有这5个表现,别傻傻看不清

男人注意:女人若有过很多男人,多半有这5个表现,别傻傻看不清

伊人河畔
2025-12-04 11:27:19
42岁王冠定居上海,住800平独栋别墅穿188拖鞋,老公手上纹她名字

42岁王冠定居上海,住800平独栋别墅穿188拖鞋,老公手上纹她名字

疯说时尚
2026-01-22 15:58:27
蓝白迎战弹劾审查会,赖清德不出席,现场摆出“清德宗”看板

蓝白迎战弹劾审查会,赖清德不出席,现场摆出“清德宗”看板

海峡导报社
2026-01-21 09:52:03
我那兄弟娶了个洋媳妇,天天哀嚎:搂着俄罗斯老婆睡,堪比抱刺猬

我那兄弟娶了个洋媳妇,天天哀嚎:搂着俄罗斯老婆睡,堪比抱刺猬

前沿天地
2025-12-29 11:22:33
“让我睡一次,不然死给你看!”17岁少年持刀,威胁舅妈发生关系

“让我睡一次,不然死给你看!”17岁少年持刀,威胁舅妈发生关系

有书
2026-01-09 21:30:59
2026-01-23 07:00:49
嘶吼RoarTalk incentive-icons
嘶吼RoarTalk
不一样的互联网安全新视界
8134文章数 10545关注度
往期回顾 全部

科技要闻

几千亿只是开胃菜,AI基建还得再砸几万亿

头条要闻

特朗普起诉美国最大银行 索赔至少50亿美元

头条要闻

特朗普起诉美国最大银行 索赔至少50亿美元

体育要闻

跑个步而已,他们在燃什么?

娱乐要闻

车银优赚800亿 涉嫌逃税200亿!

财经要闻

西贝拿到“救命钱”,然后呢

汽车要闻

配备多块娱乐屏 极氪8X内饰曝光

态度原创

亲子
时尚
本地
手机
军事航空

亲子要闻

真相很可怕!终于揭秘:为什么你记不住3岁前的事?

这些才是最日常的冬季穿搭!不露腿、不扮嫩,简约舒适又保暖

本地新闻

云游中国|格尔木的四季朋友圈,张张值得你点赞

手机要闻

性能最激进+唯一真全面屏的Air手机!红魔11 Air首销翻倍

军事要闻

普京:愿意向"和平委员会"提供10亿美元

无障碍浏览 进入关怀版