从像素到漏洞利用:MSRC团队如何通过模糊线索挖掘CVE-2016-0040

本文详细讲述了微软安全响应中心(MSRC)如何仅凭一条推特截图中的崩溃指令,在24小时内逆向分析出Windows内核未初始化内存漏洞(CVE-2016-0040)并完成概念验证的全过程。

从像素到概念验证(POC)

在MSRC,我们通常通过secure@microsoft.com接收漏洞报告。但有时我们只会收到关于漏洞存在的模糊提示,这就需要我们自行推敲问题所在。这是一个关于我们如何通过单条崩溃指令的截图,在不到24小时内创建漏洞概念验证的故事。

像素线索

2015年10月19日,@R00tkitSMM发推文称发现了一个可从Windows沙盒进程触发的内核崩溃。虽然表面信息有限(仅提示问题不在win32k.sys中),但我们决定深入调查。通过放大崩溃指令截图,我们发现前后指令部分可见:

1
2
mov     eax, [ecx]
mov     [eax+8], edx

这个指令序列相当独特,我们开始在多个内核二进制文件中搜索匹配模式。

大海捞针

约一小时后,我们在ntoskrnl.exe的WMI代码中发现了一个高度匹配的候选位置:

1
2
3
WmipReceiveNotifications+0x1e3:
mov     eax, [ecx]
mov     [eax+8], edx

我们进一步通过Windows错误报告(WER)系统验证,发现少量崩溃报告与该推文描述的崩溃指令完全匹配,这增加了我们对该代码存在漏洞的信心。

漏洞定位

通过分析WmipReceiveNotifications函数,我们发现了问题根源:未初始化内存使用导致内存写入漏洞。当提供的HandleCount为零时,代码会使用未初始化的ObjectArray(局部数组),并在后续代码中基于该未初始化值进行内存写入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

if (HandleCount <= 4) {
    ObjectArray = LocalArray;
} else {
    ObjectArray = ExAllocatePoolWithTag(...);
}


#if DBG
RtlFillMemory(ObjectArray, ...);
#endif


if (NotificationAction == CreateThread) {
    Object = ObjectArray[0];  // 使用未初始化值
    *((DWORD*)Object + 2) = Value;  // 写入任意地址
}

概念验证

次日上午,我们构建了概念验证代码,成功触发了与推文完全相同的崩溃指令,确认了漏洞存在。从收到模糊线索到完成POC,整个过程不到24小时。

后续时间线

2015年10月25日,@R00tkitSMM通过正式渠道报告了该漏洞,但此时我们已提前一周开启MSRC案例并开始修复工作。我们最终在CVE-2016-0040的致谢中认可了研究员的贡献。

此事件也凸显了公开漏洞信息(即使看似最小化)的风险,我们鼓励研究人员避免此类做法。

总结

本文展示了如何利用模糊线索结合内部工具(二进制搜索、WER系统)快速定位漏洞。特别感谢Axel Souchet (@0vercl0k)、Elia Florio和Mark Wodrich (@markwo)在本漏洞分析中的贡献。

Matt Miller
MSRC漏洞与缓解措施团队

相关修复:MS16-014安全更新

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计