![]() |
Windows XP 核心驱动 AFD.sys 本地权限提升漏洞分析(ms08066) |
漏洞模块: 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 |