来源链接:http://www.freebuf.com/vuls/90501.html
FreeBuf黑客与极客(FreeBuf.COM)
原文地址:http://hdwsec.fr/blog/CVE-2015-0057.html,编译/FB小编鸢尾
**概述**
这是一个use-after-free内核漏洞,它能获取一个专属的write primitive操作,之后侵染临近的一个对象。这个yields语句可以在内核空间或者用户空间随意写入。
更准确的说,这个use-after-free触发器利用scrollbar对象,然后通过一个新的proplist对象(同样大小)替换freed对象。正是因为use-after-free,新对象的header会被一个OR primitive修改。
win32k !xxxEnableWndSBArrows+0xaa:
fffff960`0036cdfe 0903 or dword ptr [rbx],eax
该漏洞导致对象属性的最大值增加,这样你就可以将数据push到堆中。通过SetProp(HWND hWnd, LPCTSTR lpString, HANDLE hData)增加一个新属性,可以覆盖下一个对象。
在下文中,我们将使用"SetProp(hWnd, V1, V2)"来代替表示"SetProp(HWND hWnd, LPCTSTR lpString, HANDLE hData)"
**在Windows 8.1 (64-bit)上利用**
根据FireEye的报告,有恶意软件使用了上面我们讨论的技术侵染一个临近的菜单对象。事实上,其中有一张截图就显示了tagMENU.rgItems和tagMENU.cItems的值被覆盖。
typedef struct _MENU
{
…
DWORD cItems // number of items contained by the items array
…
PITEM rgItems // pointer to the items array
…
}
这在Windows XP下提供了一个write primitive操作,覆盖nt!HalDispatchTable+0×4。接下来我们根据FireEye以及NCC Group所提供的技术细节,在Windows 8.1 64-bit下尝试进行漏洞复现。
我们可能会遇到以下障碍:
1.攻击者不能完全控制每个属性中的内容;虽然V2的8个字节是被完全控制的,但是V1只能使用2个字节。
2.上面提到的_MENU结构有变化,并且由于V1的内容缺乏控制,cItems和rgItems无法完全控制
3.需要绕过ASLR和SMEP
4.需要绕过heap entry编码机制
5.最后覆盖的对象还要记得恢复,以避免当内核释放时造成崩溃
**获取任意写入操作**
为了替代直接覆盖rgItems和cItems,NCC Group发现并提供的一个解决方案涉及对堆的header操作和两个覆盖,以便最终控制一个窗口结构,提供一个读写primitive操作。在此我建议大家可以看看他们提供的解决方案[3],其中的技巧已经写的非常详细了。
我选择控制一个菜单对象,因为它在各种操作系统(从Windows XP到8.1)下提供了一个常见的write primitive;在这种情况下,read primitive的不足对于我们来说也就不存在问题了。
虽然Dyre恶意软件损坏cItems和rgItems,然而我们要做的仅仅只是损坏rgItems字段:
a.创建了一个item的菜单,使用CreateMenu()以及InsertMenuItem()
b.使用NCC Group提供的覆盖控制方法损坏rgItems(item数组的地址)
c.数组的第一个item指向rgItems包含的一个wID字段(我们使用SetMenuItemInfo()进行修改的字段),这也导致我们获得任意write primitive操作
接下来的这一步骤十分经典:nt!HalDispatchTable+8中的一个函数指针被覆盖,然后会运行的payload包括两个阶段:
1.首先恢复桌面堆(desktop heap)以及原始的函数指针
2.第二阶段是一个用于改变当前系统进程token的Shellcode
**绕过heap header编码**
在该利用例子中,第一个覆盖的heap header是必须要修改的,之后我们必须在第二个覆盖内容中建立一个假的heap header。这里由于Windows 8.1的heap header是由一个cookie进行编码,为进一步的了解细节,有必要去看看Chris Valasek以及Tarjei Mandt所提供的参考[9][10]
NCC Group提供的解决方案依赖于桌面堆(desktop heap)映射的只读用户区域,暴露cookie的值。
首先我们必须找到用于编码heap header的cookie,进而确认桌面堆(desktop heap)的heap base。然后我们可以获取到存储在0×80下的cookie:
nt!_HEAP
+0x000 Entry : _HEAP_ENTRY
+0x010 SegmentSignature : Uint4B
[…]
+0x07c EncodeFlagMask : Uint4B
+0x080 Encoding : _HEAP_ENTRY
[…]
现在就可以通过对编码字段进行xor操作解码heap header
接着解码并修改Entry后,我们只需计算新的SmallTagIndex的校验和:
Entry.SmallTagIndex = Entry.SizeLow ^ Entry.SizeHigh ^ Entry.Flags;
**在中等完整性等级下绕过ASLR**
在中等完整性权限下ASLR对我们来说没有啥问题:
a.使用NtQuerySystemInformation()获取ntoskrnl以及hal.dll的基地址
b.动态获取ROP小工具偏移量,之后恢复后的hal!HaliQuerySystemInformation()会分别读取ntoskrnl.exe和hal.dll
在低等完整性等级下绕过ASLR
NtQuerySystemInformation()是不能从一个低等完整性等级下进行调用的。尽管在exploit源代码中没有实现,但是Alex Ionescu [5]提出了一种使用SIDT作为内核信息泄漏的方法,该方法是不会理会完整性等级的。
**绕过SMEP**
早在2011年5月,为了使用户模式页面从内核中执行,Dan Rosenberg就提出了一种十分新颖的方式绕过Linux下的SMEP[6]。j00ru以及Gynvael Coldwind将这一技术进一步应用到到Windows[7]。对于该exploit,我使用了siberas在2014 pwn2own所展示的方法[8]
**防止post-exploitation崩溃**
为了防止post-exploitation崩溃,记得一定要清理桌面堆(desktop heap)。事实上,已损坏的对象以及hal!HaliQuerySystemInformation()的原始指针都是需要进行恢复的。
![](http://image.3001.net/images/20151221/14506967759349.png)
Exp放送
链接: http://pan.baidu.com/s/1kUyvFTH 密码: x5pd
参考文献
[1] http://breakingmalware.com/vulnerabilities/one-bit-rule-bypassing-windows-10-protections-using-single-bit/
[2] https://www.fireeye.com/blog/threat-research/2015/07/dyre_banking_trojan.html
[3] https://www.nccgroup.trust/globalassets/newsroom/uk/blog/documents/2015/07/exploiting-cve-2015.pdf
[4] https://media.blackhat.com/bh-us-11/Mandt/BH_US_11_Mandt_win32k_WP.pdf
[5] http://recon.cx/2013/slides/Recon2013-Alex%20Ionescu-I%20got%2099%20problems%20but%20a%20kernel%20pointer%20ain't%20one.pdf
[6] http://vulnfactory.org/blog/2011/06/05/smep-what-is-it-and-how-to-beat-it-on-linux/
[7] http://j00ru.vexillium.org/?p=783
[8] http://www.siberas.de/papers/Pwn2Own_2014_AFD.sys_privilege_escalation.pdf
[9] http://illmatics.com/Understanding_the_LFH.pdf
[10] http://illmatics.com/Windows%208%20Heap%20Internals.pdf
暂无评论