为什么这个iframe标记导致x64 Windows上的Safari崩溃?

时间:2011-12-21 14:55:00

标签: windows crash bsod

如果你没有听说过这段代码会在Safari中运行时在x64位Windows 7上导致BSoD崩溃

<iframe height='18082563'></iframe>

当然,问题是它究竟是如何发生的,为什么18082563而不是说“1808256 4 ”?

2 个答案:

答案 0 :(得分:8)

这是对它的解释。

http://pastebin.com/XTWnLF3p

由于一个NineGrid请求通过代表UX主题DLL发送的GdiDrawStream发出错误,该主题DLL处理从XP及更高版本开始的Windows主题。

Webkit浏览器(连同IE8 - 但不是IE9,似乎)尝试使用操作系统的本机皮肤在页面上呈现HTML元素。在这种情况下,在drawControl函数中(参见http://www.opensource.apple.com/source/WebCore/WebCore-658.28/rendering/RenderThemeWin.cpp),调用DrawThemeBackground,它处理操作系统控件的外观。

发送96(0x60)字节缓冲区(GdiDrawStream的参数2和3是大小和缓冲区地址,参数1是HDC)。

Draw Steam缓冲区以魔术值开头,然后是32字节市场识别的一系列命令。以下是在Safari中查看时使用特殊iframe发送的流:

44727753 ='DrwS'= DrawStream Magic

命令缓冲区:

#0: 00000000 <SET TARGET>
    3b01017a // Destination DC (hdc) *** Must match HDC in GdiDrawStream argument 1 ***
    // Destination Clip (ERECTL):
    0000011b // Left
    00000011 // Top
    0000012c // Right
    0089f580 // Bottom               *** Multiply by 2, and you get the "magic" value used in the iframe PoC ***
#1: 00000001 <SET SOURCE>
    058506a3 // Source Surface (pso)  *** Dumped the surface from kernel mode, got a 13x5 32BPP bitmap which is the Luna/Aero scrollbar slider control ***
#2: 00000009 <NINEGRID>
// Destination Clip (ERECTL):          *** Should match the Destination Clip of the Target
    0000011b // Left
    00000011 // Top
    0000012c // Right
    0089f580 // Bottom
// Source Clip (ERECTL):                 *** Should be within the bounds of the surface (which is 13x5 in this case)
    00000000 // Left
    00000000 // Top
    0000000e // Right
    00000001 // Bottom
// NINEGRID_BITMAP_INFO             *** Documented in RDP docs. Should fit within the surface and destination.
    00000001 // Flags (DSDNG_STRETCH)
    0000000a // Left Width
    00000003 // Right Width
    00000000 // Top Height
    00000000 // Bottom Height
    00000000 // Transparent

这是原始转储:

0: kd> dds @r8 l18
00000000`003be664  44727753
00000000`003be668  00000000
00000000`003be66c  2b0108d5   // HDC, this will change from dump to dump
00000000`003be670  0000011b
00000000`003be674  00000011
00000000`003be678  0000012c
00000000`003be67c  0089f580
00000000`003be680  00000001
00000000`003be684  018503c2   // Bitmap Surface, this will change from dump to dump
00000000`003be688  00000009
00000000`003be68c  0000011b
00000000`003be690  00000011
00000000`003be694  0000012c
00000000`003be698  0089f580
00000000`003be69c  00000000
00000000`003be6a0  00000000
00000000`003be6a4  0000000e
00000000`003be6a8  00000001
00000000`003be6ac  00000001
00000000`003be6b0  0000000a
00000000`003be6b4  00000003
00000000`003be6b8  00000000
00000000`003be6bc  00000000
00000000`003be6c0  00000000

你基本上看到的是一个iframe,它有一个特别有趣的高度,当滚动条被绘制和主题化时,NineGrid变换中的数学错误会导致越界写入。这个PoC可以在IE 8中运行,但IE 8有一个众所周知的CSS错误,它有一个最大像素限制(大约1342177),这就是为什么它不会立即显现出来。

其他高度是可以开发的,有些可能足够小,甚至IE 8也会击中NineGrid高度角落。

IE9似乎根本没有使用UxTheme的主题控件,它的滚动条行为与IE 8不同,所以即使像素限制不再存在,PoC也不起作用。 Firefox未经过测试。

不只是IFRAMES是脆弱的。使用相同高度的HTML进行测试也会导致Safari崩溃。

这意味着任何客户端,本地或远程,对控件进行蒙皮(即:几乎所有这些 - 甚至闪存PDF上的按钮)都可能导致NineGrid碰到这个bug的转换。它完全不是WebKit特有的。

答案 1 :(得分:1)

作为一个说明,MS最近发布了修复此问题的MS12-008。