xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
添加文章 Xcon English Version

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


创建时间:2008-10-15
文章属性:原创
文章提交:whitecell (sinister_at_whitecell.org)

Author:  Polymorphours
Email:   Polymorphours@whitecell.org
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/