Windows XP 核心驱动 AFD.sys 本地权限提升漏洞分析(ms08066)

Author: Polymorphours
Email: [email protected]
Homepage:http://www.whitecell.org
Date: 2008-10-15

漏洞模块: AFD.sys
漏洞类型: 任意内核地址可写

这个漏洞又是一个可以写任意内核地址的漏洞,产生这个漏洞的原因是 ProbeForWrite 函数因为检查长度为 0 的Buffer被绕过。下面看下具体漏洞的情况,这个漏洞出现在函数AfdGetRemoteAddress 中,当传入的第7个参数为 0 的时候,ProbeForWrite的检查形同虚设了。
注意第六个参数 PVOID Address, 它是由 Irp->UserBuffer 传入的,而 SIZE_T Length 为OutputBufferLength,那么如果在 DeviceIoControl 中的 OutputBuffer 设置成内核需要写的地址,OutputBufferLength 设置为 0,并设置正确的 IoDeviceCode 即可触发这个漏洞.

PAGE:00017D17 ; int __stdcall AfdGetRemoteAddress(int,int,char,int,int,PVOID Address,SIZE_T Length,int)
PAGE:00017D17 __stdcall AfdGetRemoteAddress(x, x, x, x, x, x, x, x) proc near
PAGE:00017D17 ; DATA XREF: .data:0001230Co
PAGE:00017D17
PAGE:00017D17 var_24 = dword ptr -24h
PAGE:00017D17 var_20 = dword ptr -20h
PAGE:00017D17 var_1C = dword ptr -1Ch
PAGE:00017D17 ms_exc = CPPEH_RECORD ptr -18h
PAGE:00017D17 arg_0 = dword ptr 8
PAGE:00017D17 arg_8 = byte ptr 10h
PAGE:00017D17 Address = dword ptr 1Ch
PAGE:00017D17 Length = dword ptr 20h
PAGE:00017D17 arg_1C = dword ptr 24h
PAGE:00017D17
PAGE:00017D17 push 14h
PAGE:00017D19 push offset unk_11B00
PAGE:00017D1E call __SEH_prolog
PAGE:00017D1E
PAGE:00017D23 mov eax, [ebp+arg_0]
PAGE:00017D26 mov ebx, [eax+0Ch]
PAGE:00017D29 mov [ebp+var_24], ebx
PAGE:00017D2C xor esi, esi
PAGE:00017D2E mov eax, [ebp+arg_1C]
PAGE:00017D31 mov [eax], esi
PAGE:00017D33 push ebx
PAGE:00017D34 call AfdLockEndpointContext(x)
PAGE:00017D34
PAGE:00017D39 mov [ebp+var_20], eax
PAGE:00017D3C cmp eax, esi
PAGE:00017D3E jz loc_17DE0
PAGE:00017D3E
PAGE:00017D44 cmp word ptr [ebx], 0AFD2h
PAGE:00017D49 jnz loc_17DE0
PAGE:00017D49
PAGE:00017D4F cmp byte ptr [ebx+2], 3
PAGE:00017D53 jnz loc_17DE0
PAGE:00017D53
PAGE:00017D59 movzx eax, word ptr [ebx+5Ah]
PAGE:00017D5D movzx ecx, word ptr [ebx+58h]
PAGE:00017D61 add ecx, eax
PAGE:00017D63 cmp ecx, [ebx+74h]
PAGE:00017D66 ja short loc_17DE0
PAGE:00017D66
PAGE:00017D68 cmp [ebp+Length], eax
<—-这里检查Buffer大小,如果Buffer大于规定的大小就有默认的大小来代替
PAGE:00017D6B jnb short loc_17D76
PAGE:00017D6B
PAGE:00017D6D mov [ebp+var_1C], 80000005h
PAGE:00017D74 jmp short loc_17D7C
<—-最终导致问题点: 如果BufferLength小于的话,居然还能继续运行它向下运行
PAGE:00017D74
PAGE:00017D76 ; —————————————————————————
PAGE:00017D76
PAGE:00017D76 loc_17D76: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+54j
PAGE:00017D76 mov [ebp+Length], eax
<—用规定的长度代替
PAGE:00017D79 mov [ebp+var_1C], esi
PAGE:00017D79
PAGE:00017D7C
PAGE:00017D7C loc_17D7C: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+5Dj
PAGE:00017D7C mov [ebp+ms_exc.disabled], esi
PAGE:00017D7F cmp [ebp+arg_8], 0
PAGE:00017D83 jz short loc_17D93
PAGE:00017D83
PAGE:00017D85 push 1 ; Alignment
PAGE:00017D87 push [ebp+Length] ; Length
PAGE:00017D8A push [ebp+Address] ; Address
PAGE:00017D8D call ds:ProbeForWrite(x,x,x)
<—如果 ebp+Length为0,那么检查被绕过
PAGE:00017D8D
PAGE:00017D93
PAGE:00017D93 loc_17D93: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+6Cj
PAGE:00017D93 movzx ecx, word ptr [ebx+5Ah]
PAGE:00017D97 movzx esi, word ptr [ebx+58h]
PAGE:00017D9B add esi, [ebp+var_20]
PAGE:00017D9E mov edi, [ebp+Address]
<— memcpy的代码,拷贝数据到UserBuffer中
PAGE:00017DA1 mov eax, ecx
PAGE:00017DA3 shr ecx, 2
PAGE:00017DA6 rep movsd
PAGE:00017DA8 mov ecx, eax
PAGE:00017DAA and ecx, 3
PAGE:00017DAD rep movsb
PAGE:00017DAF mov eax, [ebx+74h]
PAGE:00017DB2 mov ecx, [ebp+arg_1C]
PAGE:00017DB5 mov [ecx], eax
PAGE:00017DB7 or [ebp+ms_exc.disabled], 0FFFFFFFFh
PAGE:00017DBB jmp short loc_17DE7
PAGE:00017DBB
PAGE:00017DBB ; —————————————————————————
PAGE:00017DBD align 10h
PAGE:00017DC0 db 2 dup(90h)
PAGE:00017DC2 ; —————————————————————————
PAGE:00017DC2
PAGE:00017DC2 loc_17DC2: ; DATA XREF: .rdata:00011B04o
PAGE:00017DC2 lea eax, [ebp-1Ch]
PAGE:00017DC5 push eax
PAGE:00017DC6 push dword ptr [ebp-14h]
PAGE:00017DC9 call AfdExceptionFilter(x,x)
PAGE:00017DC9
PAGE:00017DCE retn

在看看补丁的情况

PAGE:00017D17 ; int __stdcall AfdGetRemoteAddress(int,int,char,int,int,PVOID Address,int,int)
PAGE:00017D17 __stdcall AfdGetRemoteAddress(x, x, x, x, x, x, x, x) proc near
PAGE:00017D17 ; DATA XREF: .data:0001230Co
PAGE:00017D17
PAGE:00017D17 var_24 = dword ptr -24h
PAGE:00017D17 var_20 = dword ptr -20h
PAGE:00017D17 var_1C = dword ptr -1Ch
PAGE:00017D17 ms_exc = CPPEH_RECORD ptr -18h
PAGE:00017D17 arg_0 = dword ptr 8
PAGE:00017D17 arg_8 = byte ptr 10h
PAGE:00017D17 Address = dword ptr 1Ch
PAGE:00017D17 arg_18 = dword ptr 20h
PAGE:00017D17 arg_1C = dword ptr 24h
PAGE:00017D17
PAGE:00017D17 push 14h
PAGE:00017D19 push offset unk_11B00
PAGE:00017D1E call __SEH_prolog
PAGE:00017D1E
PAGE:00017D23 mov eax, [ebp+arg_0]
PAGE:00017D26 mov ebx, [eax+0Ch]
PAGE:00017D29 mov [ebp+var_24], ebx
PAGE:00017D2C xor esi, esi
PAGE:00017D2E mov eax, [ebp+arg_1C]
PAGE:00017D31 mov [eax], esi
PAGE:00017D33 push ebx
PAGE:00017D34 call AfdLockEndpointContext(x)
PAGE:00017D34
PAGE:00017D39 mov [ebp+var_20], eax
PAGE:00017D3C cmp eax, esi
PAGE:00017D3E jz loc_17DDB
PAGE:00017D3E
PAGE:00017D44 cmp word ptr [ebx], 0AFD2h
PAGE:00017D49 jnz loc_17DDB
PAGE:00017D49
PAGE:00017D4F cmp byte ptr [ebx+2], 3
PAGE:00017D53 jnz loc_17DDB
PAGE:00017D53
PAGE:00017D59 movzx eax, word ptr [ebx+5Ah]
PAGE:00017D5D movzx ecx, word ptr [ebx+58h]
PAGE:00017D61 add ecx, eax
PAGE:00017D63 cmp ecx, [ebx+74h]
PAGE:00017D66 ja short loc_17DDB
PAGE:00017D66
PAGE:00017D68 cmp [ebp+arg_18], eax
PAGE:00017D6B jnb short loc_17D76
PAGE:00017D6B
PAGE:00017D6D mov [ebp+var_1C], 80000005h
PAGE:00017D74 jmp short loc_17DE2
<—补丁就是在这里,如果访问的BufferLength小于规定的大小,那么直接返回错误
PAGE:00017D74
PAGE:00017D76 ; —————————————————————————
PAGE:00017D76
PAGE:00017D76 loc_17D76: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+54j
PAGE:00017D76 mov [ebp+var_1C], esi
PAGE:00017D79 mov [ebp+ms_exc.disabled], esi
PAGE:00017D7C cmp [ebp+arg_8], 0
PAGE:00017D80 jz short loc_17D8E
PAGE:00017D80
PAGE:00017D82 push 1 ; Alignment
PAGE:00017D84 push eax ; Length
PAGE:00017D85 push [ebp+Address] ; Address
PAGE:00017D88 call ds:ProbeForWrite(x,x,x)
PAGE:00017D88
PAGE:00017D8E
PAGE:00017D8E loc_17D8E: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+69j
PAGE:00017D8E movzx ecx, word ptr [ebx+5Ah]
PAGE:00017D92 movzx esi, word ptr [ebx+58h]
PAGE:00017D96 add esi, [ebp+var_20]
PAGE:00017D99 mov edi, [ebp+Address]
PAGE:00017D9C mov eax, ecx
PAGE:00017D9E shr ecx, 2
PAGE:00017DA1 rep movsd
PAGE:00017DA3 mov ecx, eax
PAGE:00017DA5 and ecx, 3
PAGE:00017DA8 rep movsb
PAGE:00017DAA mov eax, [ebx+74h]
PAGE:00017DAD mov ecx, [ebp+arg_1C]
PAGE:00017DB0 mov [ecx], eax
PAGE:00017DB2 or [ebp+ms_exc.disabled], 0FFFFFFFFh
PAGE:00017DB6 jmp short loc_17DE2
PAGE:00017DB6
PAGE:00017DB6 ; —————————————————————————
PAGE:00017DB8 dd 90909090h
PAGE:00017DBC db 90h
PAGE:00017DBD ; —————————————————————————
PAGE:00017DBD
PAGE:00017DBD loc_17DBD: ; DATA XREF: .rdata:00011B04o
PAGE:00017DBD lea eax, [ebp-1Ch]
PAGE:00017DC0 push eax
PAGE:00017DC1 push dword ptr [ebp-14h]
PAGE:00017DC4 call AfdExceptionFilter(x,x)
PAGE:00017DC4
PAGE:00017DC9 retn
PAGE:00017DC9
PAGE:00017DC9 ; —————————————————————————
PAGE:00017DCA align 4
PAGE:00017DCC db 3 dup(90h)
PAGE:00017DCF ; —————————————————————————
PAGE:00017DCF
PAGE:00017DCF loc_17DCF: ; DATA XREF: .rdata:00011B08o
PAGE:00017DCF mov esp, [ebp-18h]
PAGE:00017DD2 or dword ptr [ebp-4], 0FFFFFFFFh
PAGE:00017DD6 mov ebx, [ebp-24h]
PAGE:00017DD9 jmp short loc_17DE2
PAGE:00017DD9
PAGE:00017DDB ; —————————————————————————
PAGE:00017DDB
PAGE:00017DDB loc_17DDB: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+27j
PAGE:00017DDB ; AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+32j
PAGE:00017DDB ; AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+3Cj
PAGE:00017DDB ; AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+4Fj
PAGE:00017DDB mov [ebp+var_1C], 0C0000140h
PAGE:00017DDB
PAGE:00017DE2
PAGE:00017DE2 loc_17DE2: ; CODE XREF: AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+5Dj
PAGE:00017DE2 ; AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+9Fj
PAGE:00017DE2 ; AfdGetRemoteAddress(x,x,x,x,x,x,x,x)+C2j
PAGE:00017DE2 push [ebp+var_20]
PAGE:00017DE5 push ebx
PAGE:00017DE6 call AfdUnlockEndpointContext(x,x)
PAGE:00017DE6
PAGE:00017DEB mov eax, [ebp+var_1C]
PAGE:00017DEE call __SEH_epilog
PAGE:00017DEE
PAGE:00017DF3 retn 20h

剩下的就是exploit它了,具体的方法也很简单,可以参照以前在 www.whitecell.org 上的代码。

WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/

相关日志

发表评论