国外安全技术高手谈卡巴斯基存在隐患

互联网 | 编辑: 杨剑锋 2007-06-18 09:30:00转载 一键看全文

允许用户层代码访问内核内存

允许用户层代码访问内核内存

当前操作系统所使用的划分内核/用户的主要原则是:不允许用户层直接访问内核层的内存。这对维持系统稳定十分重要,比如它可以阻止有bug的用户层程序造成内核崩溃,甚至使整个系统崩溃。不幸的是,KAV的程序员们似乎认为这个原则根本不重要。

KAV所执行的不安全操作里最奇怪的地方就在于:它允许用户层直接调用他们内核驱动的一部分(在内核地址空间内!),而不是只加载用户层DLL(或者在目标进程中加载用户层代码)。

该机制似乎是用来在加载DLL时,调查这些DLL的——这种工作本来最好应当由PsSetLoadImageNotifyRoutine来完成。

创建新进程后,KAV给Kernel32.dll打上补丁,这样输出表就会指向所有的DLL——往调用内核层kav的驱动部分的thunk中加载例行程序(例如LoadLibraryA)。另外,KAV还修改它的代码的部分保护以及数据段,以便允许用户层进行读操作。

KAV设置了PsLoadImageNotifyRoutine关联来检测kernel32.dll的加载,以便确定什么时候给kernel32的输出表打补丁。笔者想知道为什么KAV不只在PsLoadImageNotifyRoutine中直接工作,而是费尽千辛万苦地通过允许用户层来调用内核层来进行LoadLibrary关联。

在新进程加载图片的时候,KAV会调用CheckInjectCodeForNewProcess函数,并且核查 kernel32是否被加载。如果Kernel32已经加载,那么它将安排APC队列给要执行补丁程序的进程。

.text:F82218B0 
; int __stdcall CheckInjectCodeForNewProcess(wchar_t *,PUCHAR ImageBase) .text:F82218B0 CheckInjectCodeForNewProcess proc near
; CODE XREF: KavLoadImageNotifyRoutine+B5p .text:F82218B0 ; KavDoKernel32Check+41p .text:F82218B0 .text:F82218B0 arg_0 = dword ptr 4 .text:F82218B0 ImageBase = dword ptr 8 .text:F82218B0 .text:F82218B0 mov al, byte_F82282F9 .text:F82218B5 push esi .text:F82218B6 test al, al .text:F82218B8 push edi .text:F82218B9 jz short loc_F8221936 .text:F82218BB mov eax, [esp+8+arg_0] .text:F82218BF push offset aKernel32_dll ; "kernel32.dll" .text:F82218C4 push eax ; wchar_t * .text:F82218C5 call ds:_wcsicmp .text:F82218CB add esp, 8 .text:F82218CE test eax, eax .text:F82218D0 jnz short loc_F8221936 .text:F82218D2 mov al, g_FoundKernel32Exports .text:F82218D7 mov edi, [esp+8+ImageBase] .text:F82218DB test al, al .text:F82218DD jnz short KavInitializePatchApcLabel .text:F82218DF push edi .text:F82218E0 call KavCheckFindKernel32Exports .text:F82218E5 test al, al .text:F82218E7 jz short loc_F8221936 .text:F82218E9 .text:F82218E9 KavInitializePatchApcLabel:
; CODE XREF: CheckInjectCodeForNewProcess+2Dj .text:F82218E9 push '3SeB' ; Tag .text:F82218EE push 30h ; NumberOfBytes .text:F82218F0 push 0 ; PoolType .text:F82218F2 call ds:ExAllocatePoolWithTag .text:F82218F8 mov esi, eax .text:F82218FA test esi, esi .text:F82218FC jz short loc_F8221936 .text:F82218FE push edi .text:F82218FF push 0 .text:F8221901 push offset KavPatchNewProcessApcRoutine .text:F8221906 push offset loc_F82218A0 .text:F822190B push offset loc_F8221890 .text:F8221910 push 0 .text:F8221912 call KeGetCurrentThread .text:F8221917 push eax .text:F8221918 push esi .text:F8221919 call KeInitializeApc .text:F822191E push 0 .text:F8221920 push 0 .text:F8221922 push 0 .text:F8221924 push esi .text:F8221925 call KeInsertQueueApc .text:F822192B test al, al .text:F822192D jnz short loc_F822193D .text:F822192F push esi ; P .text:F8221930 call ds:ExFreePool .text:F8221936 .text:F8221936 loc_F8221936:
; CODE XREF: CheckInjectCodeForNewProcess+9j .text:F8221936 ; CheckInjectCodeForNewProcess+20j ... .text:F8221936 pop edi .text:F8221937 xor al, al .text:F8221939 pop esi .text:F822193A retn 8 .text:F822193D ; -------------------------------------------------- .text:F822193D .text:F822193D loc_F822193D:
; CODE XREF: CheckInjectCodeForNewProcess+7Dj .text:F822193D pop edi .text:F822193E mov al, 1 .text:F8221940 pop esi .text:F8221941 retn 8

APC例行程序本身给kernel32的输出表打了补丁(并且生成thunk来调用内核层)并调整KAV的驱动镜像的PTE属性,以便允许用户层访问。

.text:F8221810 KavPatchNewProcessApcRoutine proc near 
; DATA XREF: CheckInjectCodeForNewProcess+51o .text:F8221810 .text:F8221810 var_8 = dword ptr -8 .text:F8221810 var_4 = dword ptr -4 .text:F8221810 ImageBase = dword ptr 8 .text:F8221810 .text:F8221810 push ebp .text:F8221811 mov ebp, esp .text:F8221813 sub esp, 8 .text:F8221816 mov eax, [ebp+ImageBase] .text:F8221819 push esi .text:F822181A push eax ; ImageBase .text:F822181B call KavPatchImageForNewProcess .text:F8221820 mov esi, dword_F8230518 .text:F8221826 mov eax, dword_F823051C .text:F822182B and esi, 0FFFFF000h .text:F8221831 cmp esi, eax .text:F8221833 mov [ebp+ImageBase], esi .text:F8221836 jnb short loc_F8221883 .text:F8221838 .text:F8221838 loc_F8221838: ; CODE XREF: KavPatchNewProcessApcRoutine+71j .text:F8221838 push esi .text:F8221839 call KavPageTranslation0 .text:F822183F push esi .text:F8221840 mov [ebp+var_8], eax .text:F8221843 call KavPageTranslation1 .text:F8221849 mov [ebp+var_4], eax .text:F822184C mov eax, [ebp+var_8] .text:F822184F lock or dword ptr [eax], 4 .text:F8221853 lock and dword ptr [eax], 0FFFFFEFFh .text:F822185A mov eax, [ebp+var_4] .text:F822185D invlpg byte ptr [eax] .text:F8221860 lock or dword ptr [eax], 4 .text:F8221864 lock and dword ptr [eax], 0FFFFFEFDh .text:F822186B mov eax, [ebp+ImageBase] .text:F822186E invlpg byte ptr [eax] .text:F8221871 mov eax, dword_F823051C .text:F8221876 add esi, 1000h .text:F822187C cmp esi, eax .text:F822187E mov [ebp+ImageBase], esi .text:F8221881 jb short loc_F8221838 .text:F8221883 .text:F8221883 loc_F8221883: ; CODE XREF: KavPatchNewProcessApcRoutine+26j .text:F8221883 pop esi .text:F8221884 mov esp, ebp .text:F8221886 pop ebp .text:F8221887 retn 0Ch .text:F8221887 KavPatchNewProcessApcRoutine endp .text:F8221750 ; int __stdcall KavPatchImageForNewProcess(PUCHAR ImageBase) .text:F8221750 KavPatchImageForNewProcess proc near
; CODE XREF: KavPatchNewProcessApcRoutine+Bp .text:F8221750 .text:F8221750 ImageBase = dword ptr 8 .text:F8221750 .text:F8221750 push ebx .text:F8221751 call ds:KeEnterCriticalRegion .text:F8221757 mov eax, dword_F82282F4 .text:F822175C push 1 ; Wait .text:F822175E push eax ; Resource .text:F822175F call ds:ExAcquireResourceExclusiveLite .text:F8221765 push 1 .text:F8221767 call KavSetPageAttributes1 .text:F822176C mov ecx, [esp+ImageBase] .text:F8221770 push ecx ; ImageBase .text:F8221771 call KavPatchImage .text:F8221776 push 0 .text:F8221778 mov bl, al .text:F822177A call KavSetPageAttributes1 .text:F822177F mov ecx, dword_F82282F4 ; Resource .text:F8221785 call ds:ExReleaseResourceLite .text:F822178B call ds:KeLeaveCriticalRegion .text:F8221791 mov al, bl .text:F8221793 pop ebx .text:F8221794 retn 4 .text:F8221794 KavPatchImageForNewProcess endp

真正的镜像补丁会保护 kernel32的输出表,它将输出地址表的入口改成LoadLibrary* 函数族,指向thunk,该thunk被写进Kernel32 镜像的空闲空间,并将真正的thunk代码写出:

.text:F8221680 ; int __stdcall KavPatchImage(PUCHAR ImageBase)
.text:F8221680 KavPatchImage   proc near  ; CODE XREF: KavPatchImageForNewProcess+21p
.text:F8221680
.text:F8221680 var_C           = dword ptr -0Ch
.text:F8221680 FunctionVa      = dword ptr -8
.text:F8221680 var_4           = dword ptr -4
.text:F8221680 ImageBase       = dword ptr  4
.text:F8221680
.text:F8221680    mov     eax, [esp+ImageBase]
.text:F8221684    sub     esp, 0Ch
.text:F8221687    push    ebp
.text:F8221688    push    3Ch
.text:F822168A    push    eax
.text:F822168B    call    KavReprotectExportTable
.text:F8221690    mov     ebp, eax
.text:F8221692    test    ebp, ebp
.text:F8221694    jnz     short loc_F822169F
.text:F8221696    xor     al, al
.text:F8221698    pop     ebp
.text:F8221699    add     esp, 0Ch
.text:F822169C    retn    4
.text:F822169F ; ----------------------------------
.text:F822169F
.text:F822169F loc_F822169F:              ; CODE XREF: KavPatchImage+14j
.text:F822169F    push    ebx
.text:F82216A0    push    esi
.text:F82216A1    push    edi
.text:F82216A2    xor     ebx, ebx
.text:F82216A4    mov     edi, ebp
.text:F82216A6    mov     esi, offset ExportedFunctionsToCheckTable
.text:F82216AB
.text:F82216AB CheckNextFunctionInTable:       ; CODE XREF: KavPatchImage+B4j
.text:F82216AB    mov     edx, [esi+0Ch]
.text:F82216AE    mov     eax, [esp+1Ch+ImageBase]
.text:F82216B2    lea     ecx, [esp+1Ch+var_C]
.text:F82216B6    push    ecx
.text:F82216B7    push    edx
.text:F82216B8    push    eax
.text:F82216B9    call    LookupExportedFunction
.text:F82216BE    test    eax, eax
.text:F82216C0    mov     [esp+1Ch+FunctionVa], eax
.text:F82216C4    jz      short loc_F8221725
.text:F82216C6    mov     edx, [esp+1Ch+var_C]
.text:F82216CA    lea     ecx, [esp+1Ch+var_4]
.text:F82216CE    push    ecx
.text:F82216CF    push    40h
.text:F82216D1    push    4
.text:F82216D3    push    edx
.text:F82216D4    call    KavExecuteNtProtectVirtualMemoryInt2E
.text:F82216D9    test    al, al
.text:F82216DB    jz      short loc_F8221725
.text:F82216DD    cmp     dword ptr [esi], 0
.text:F82216E0    jnz     short loc_F82216EF
.text:F82216E2    mov     eax, [esp+1Ch+FunctionVa]
.text:F82216E6    mov     ecx, [esp+1Ch+var_C]
.text:F82216EA    mov     [esi], eax
.text:F82216EC    mov     [esi+8], ecx
.text:F82216EF
.text:F82216EF loc_F82216EF:              ; CODE XREF: KavPatchImage+60j
.text:F82216EF    mov     eax, edi
.text:F82216F1    mov     edx, 90909090h
.text:F82216F6    mov     [eax], edx
.text:F82216F8    mov     [eax+4], edx
.text:F82216FB    mov     [eax+8], edx
.text:F82216FE    mov     [eax+0Ch], dx
.text:F8221702    mov     [eax+0Eh], dl
.text:F8221705    mov     byte ptr [edi], 0E9h
.text:F8221708    mov     ecx, [esi+4]
.text:F822170B    mov     edx, ebx
.text:F822170D    sub     ecx, ebx
.text:F822170F    sub     ecx, ebp
.text:F8221711    sub     ecx, 5
.text:F8221714    mov     [edi+1], ecx
.text:F8221717    mov     ecx, [esp+1Ch+ImageBase]
.text:F822171B    mov     eax, [esp+1Ch+var_C]
.text:F822171F    sub     edx, ecx
.text:F8221721    add     edx, ebp
.text:F8221723    mov     [eax], edx      ;
.text:F8221723               ; Patching Export Table here
.text:F8221723               ; e.g. write to 7c802f58
.text:F8221723               ; (kernel32 EAT entry for LoadLibraryA)
.text:F8221723               ;
.text:F8221723               ; 578  241 00001D77 LoadLibraryA = _LoadLibraryA@4
.text:F8221723               ;  579  242 00001D4F LoadLibraryExA = _LoadLibraryExA@12
.text:F8221723               ; 580  243 00001AF1 LoadLibraryExW = _LoadLibraryExW@12
.text:F8221723               ; 581  244 0000ACD3 LoadLibraryW = _LoadLibraryW@4
.text:F8221723               ;
.text:F8221723               ; KAV在这写入一个新的RVA指向它自己的钩子代码。
.text:F8221725
.text:F8221725 loc_F8221725:              ; CODE XREF: KavPatchImage+44j
.text:F8221725               ; KavPatchImage+5Bj
.text:F8221725    add     esi, 10h
.text:F8221728    add     ebx, 0Fh
.text:F822172B    add     edi, 0Fh
.text:F822172E    cmp     esi, offset byte_F82357E0
.text:F8221734    jb      CheckNextFunctionInTable
.text:F822173A    pop     edi
.text:F822173B    pop     esi
.text:F822173C    pop     ebx
.text:F822173D    mov     al, 1
.text:F822173F    pop     ebp
.text:F8221740    add     esp, 0Ch
.text:F8221743    retn    4
.text:F8221743 KavPatchImage   endp

KAV的输出表保护代码做了这样一个假设:用户层的PE页头是形式正确的并且不包含指向内核层地址的偏移地址:

.text:F8221360 KavReprotectExportTable proc near       ; CODE XREF: KavPatchImage+Bp
.text:F8221360
.text:F8221360 var_10          = dword ptr -10h
.text:F8221360 var_C           = dword ptr -0Ch
.text:F8221360 var_8           = dword ptr -8
.text:F8221360 var_4           = dword ptr -4
.text:F8221360 arg_0           = dword ptr  4
.text:F8221360 arg_4           = dword ptr  8
.text:F8221360
.text:F8221360    mov     eax, [esp+arg_0]
.text:F8221364    sub     esp, 10h
.text:F8221367    cmp     word ptr [eax], 'ZM'
.text:F822136C    push    ebx
.text:F822136D    push    ebp
.text:F822136E    push    esi
.text:F822136F    push    edi
.text:F8221370    jnz     loc_F8221442
.text:F8221376    mov     esi, [eax+3Ch]
.text:F8221379    add     esi, eax
.text:F822137B    mov     [esp+20h+var_C], esi
.text:F822137F    cmp     dword ptr [esi], 'EP'
.text:F8221385    jnz     loc_F8221442
.text:F822138B    lea     eax, [esp+20h+var_8]
.text:F822138F    xor     edx, edx
.text:F8221391    mov     dx, [esi+14h]
.text:F8221395    push    eax
.text:F8221396    xor     eax, eax
.text:F8221398    push    40h
.text:F822139A    mov     ax, [esi+6]
.text:F822139E    lea     ecx, [eax+eax*4]
.text:F82213A1    lea     eax, [edx+ecx*8+18h]
.text:F82213A5    push    eax
.text:F82213A6    push    esi
.text:F82213A7    call    KavExecuteNtProtectVirtualMemoryInt2E 
; NtProtectVirtualMemory .text:F82213AC test al, al .text:F82213AE jz loc_F8221442 .text:F82213B4 mov ecx, [esi+8] .text:F82213B7 mov [esp+20h+var_10], 0 .text:F82213BF inc ecx .text:F82213C0 mov [esi+8], ecx .text:F82213C3 xor ecx, ecx .text:F82213C5 mov cx, [esi+14h] .text:F82213C9 cmp word ptr [esi+6], 0 .text:F82213CE lea edi, [ecx+esi+18h] .text:F82213D2 jbe short loc_F8221442 .text:F82213D4 mov ebp, [esp+20h+arg_4] .text:F82213D8 .text:F82213D8 loc_F82213D8: ; CODE XREF: KavReprotectExportTable+E0j .text:F82213D8 mov ebx, [edi+10h] .text:F82213DB test ebx, 0FFFh .text:F82213E1 jz short loc_F82213EA .text:F82213E3 or ebx, 0FFFh .text:F82213E9 inc ebx .text:F82213EA .text:F82213EA loc_F82213EA: ; CODE XREF: KavReprotectExportTable+81j .text:F82213EA mov ecx, [edi+8] .text:F82213ED mov edx, ebx .text:F82213EF sub edx, ecx .text:F82213F1 cmp edx, ebp .text:F82213F3 jle short loc_F822142C .text:F82213F5 mov esi, [edi+0Ch] .text:F82213F8 mov ecx, [esp+20h+arg_0] .text:F82213FC sub esi, ebp .text:F82213FE push ebp .text:F82213FF add esi, ebx .text:F8221401 add esi, ecx .text:F8221403 push esi .text:F8221404 call KavFindSectionName .text:F8221409 test al, al .text:F822140B jz short loc_F8221428 .text:F822140D cmp dword ptr [edi+1], 'TINI' .text:F8221414 jz short loc_F8221428 .text:F8221416 lea eax, [esp+20h+var_4] .text:F822141A push eax .text:F822141B push 40h .text:F822141D push ebp .text:F822141E push esi .text:F822141F call KavExecuteNtProtectVirtualMemoryInt2E
; NtProtectVirtualMemory .text:F8221424 test al, al .text:F8221426 jnz short loc_F822144E .text:F8221428 .text:F8221428 loc_F8221428: ; CODE XREF: KavReprotectExportTable+ABj .text:F8221428 ; KavReprotectExportTable+B4j .text:F8221428 mov esi, [esp+20h+var_C] .text:F822142C .text:F822142C loc_F822142C: ; CODE XREF: KavReprotectExportTable+93j .text:F822142C mov eax, [esp+20h+var_10] .text:F8221430 xor ecx, ecx .text:F8221432 mov cx, [esi+6] .text:F8221436 add edi, 28h .text:F8221439 inc eax .text:F822143A cmp eax, ecx .text:F822143C mov [esp+20h+var_10], eax .text:F8221440 jb short loc_F82213D8 .text:F8221442 .text:F8221442 loc_F8221442: ; CODE XREF: KavReprotectExportTable+10j .text:F8221442 ; KavReprotectExportTable+25j ... .text:F8221442 pop edi .text:F8221443 pop esi .text:F8221444 pop ebp .text:F8221445 xor eax, eax .text:F8221447 pop ebx .text:F8221448 add esp, 10h .text:F822144B retn 8 .text:F822144E ; ------------------------------------------------ .text:F822144E .text:F822144E loc_F822144E: ; CODE XREF: KavReprotectExportTable+C6j .text:F822144E mov eax, [edi+8] .text:F8221451 mov [edi+10h], ebx .text:F8221454 add eax, ebp .text:F8221456 mov [edi+8], eax .text:F8221459 mov eax, esi .text:F822145B pop edi .text:F822145C pop esi .text:F822145D pop ebp .text:F822145E pop ebx .text:F822145F add esp, 10h .text:F8221462 retn 8 .text:F8221462 KavReprotectExportTable endp

KAV用来保护用户层代码的机制也是一种黑客机制。KAV动态地判定系统调用NtProtectVirtualMemory系统服务的序数,然后用它自己的int 2e thunk来调用该服务。

.text:F8221320 KavExecuteNtProtectVirtualMemoryInt2E proc near
.text:F8221320               ; CODE XREF: KavReprotectExportTable+47p
.text:F8221320               ; KavReprotectExportTable+BFp ...
.text:F8221320
.text:F8221320 arg_0           = dword ptr  4
.text:F8221320 arg_4           = dword ptr  8
.text:F8221320 arg_8           = dword ptr  0Ch
.text:F8221320 arg_C           = dword ptr  10h
.text:F8221320
.text:F8221320    mov     eax, [esp+arg_0]
.text:F8221324    mov     ecx, [esp+arg_C]
.text:F8221328    mov     edx, [esp+arg_8]
.text:F822132C    push    ebx
.text:F822132D    mov     [esp+4+arg_0], eax
.text:F8221331    push    ecx
.text:F8221332    lea     eax, [esp+8+arg_4]
.text:F8221336    push    edx
.text:F8221337    mov     edx, NtProtectVirtualMemoryOrdinal
.text:F822133D    lea     ecx, [esp+0Ch+arg_0]
.text:F8221341    push    eax
.text:F8221342    push    ecx
.text:F8221343    push    0FFFFFFFFh
.text:F8221345    push    edx
.text:F8221346    xor     bl, bl
.text:F8221348    call    KavInt2E
.text:F822134D    test    eax, eax
.text:F822134F    mov     al, 1
.text:F8221351    jge     short loc_F8221355
.text:F8221353    mov     al, bl
.text:F8221355
.text:F8221355 loc_F8221355: ; CODE XREF: KavExecuteNtProtectVirtualMemoryInt2E+31j
.text:F8221355    pop     ebx
.text:F8221356    retn    10h
.text:F8221356 KavExecuteNtProtectVirtualMemoryInt2E endp


.user:F8231090 KavInt2E        proc near  
; CODE XREF: KavExecuteNtProtectVirtualMemoryInt2E+28p .user:F8231090 .user:F8231090 arg_0 = dword ptr 8 .user:F8231090 arg_4 = dword ptr 0Ch .user:F8231090 .user:F8231090 push ebp .user:F8231091 mov ebp, esp .user:F8231093 mov eax, [ebp+arg_0] .user:F8231096 lea edx, [ebp+arg_4] .user:F823109C int 2Eh .user:F823109C .user:F823109E pop ebp .user:F823109F retn 18h .user:F823109F KavInt2E endp .user:F823109F

KAV的输出查询代码没有正确地验证就使用从PE页头储存的那些偏移地址:

.text:F8220CA0 LookupExportedFunction proc near        ; CODE XREF: sub_F8217A60+C9p
.text:F8220CA0               ; sub_F82181D0+Dp ...
.text:F8220CA0
.text:F8220CA0 var_20          = dword ptr -20h
.text:F8220CA0 var_1C          = dword ptr -1Ch
.text:F8220CA0 var_18          = dword ptr -18h
.text:F8220CA0 var_14          = dword ptr -14h
.text:F8220CA0 var_10          = dword ptr -10h
.text:F8220CA0 var_C           = dword ptr -0Ch
.text:F8220CA0 var_8           = dword ptr -8
.text:F8220CA0 var_4           = dword ptr -4
.text:F8220CA0 arg_0           = dword ptr  4
.text:F8220CA0 arg_4           = dword ptr  8
.text:F8220CA0 arg_8           = dword ptr  0Ch
.text:F8220CA0
.text:F8220CA0    mov     edx, [esp+arg_0]
.text:F8220CA4    sub     esp, 20h
.text:F8220CA7    cmp     word ptr [edx], 'ZM'
.text:F8220CAC    push    ebx
.text:F8220CAD    push    ebp
.text:F8220CAE    push    esi
.text:F8220CAF    push    edi
.text:F8220CB0    jnz     loc_F8220DE1
.text:F8220CB6    mov     eax, [edx+3Ch]
.text:F8220CB9    add     eax, edx
.text:F8220CBB    cmp     dword ptr [eax], 'EP'
.text:F8220CC1    jnz     loc_F8220DE1
.text:F8220CC7    mov     eax, [eax+78h]
.text:F8220CCA    mov     edi, [esp+30h+arg_4]
.text:F8220CCE    add     eax, edx
.text:F8220CD0    mov     [esp+30h+var_14], eax
.text:F8220CD4    mov     esi, [eax+1Ch]
.text:F8220CD7    mov     ebx, [eax+24h]
.text:F8220CDA    mov     ecx, [eax+20h]
.text:F8220CDD    add     esi, edx
.text:F8220CDF    add     ebx, edx
.text:F8220CE1    add     ecx, edx
.text:F8220CE3    cmp     edi, 1000h
.text:F8220CE9    mov     [esp+30h+var_4], esi
.text:F8220CED    mov     [esp+30h+var_C], ebx
.text:F8220CF1    mov     [esp+30h+var_18], ecx
.text:F8220CF5    jnb     short loc_F8220D27
.text:F8220CF7    mov     ecx, [eax+10h]
.text:F8220CFA    mov     eax, edi
.text:F8220CFC    sub     eax, ecx
.text:F8220CFE    mov     eax, [esi+eax*4]
.text:F8220D01    add     eax, edx
.text:F8220D03    mov     edx, [esp+30h+arg_8]
.text:F8220D07    test    edx, edx
.text:F8220D09    jz      loc_F8220DE3
.text:F8220D0F    mov     ebx, ecx
.text:F8220D11    shl     ebx, 1Eh
.text:F8220D14    sub     ebx, ecx
.text:F8220D16    add     ebx, edi
.text:F8220D18    pop     edi
.text:F8220D19    lea     ecx, [esi+ebx*4]
.text:F8220D1C    pop     esi
.text:F8220D1D    pop     ebp
.text:F8220D1E    mov     [edx], ecx
.text:F8220D20    pop     ebx
.text:F8220D21    add     esp, 20h
.text:F8220D24    retn    0Ch
.text:F8220D27 ; ----------------------------------------------
.text:F8220D27
.text:F8220D27 loc_F8220D27:              ; CODE XREF: LookupExportedFunction+55j
.text:F8220D27    mov     edi, [eax+14h]
.text:F8220D2A    mov     [esp+30h+arg_0], 0
.text:F8220D32    test    edi, edi
.text:F8220D34    mov     [esp+30h+var_8], edi
.text:F8220D38    jbe     loc_F8220DE1
.text:F8220D3E    mov     [esp+30h+var_1C], esi
.text:F8220D42
.text:F8220D42 loc_F8220D42:              ; CODE XREF: LookupExportedFunction+13Bj
.text:F8220D42    cmp     dword ptr [esi], 0
.text:F8220D45    jz      short loc_F8220DC5
.text:F8220D47    mov     ecx, [eax+18h]
.text:F8220D4A    xor     ebp, ebp
.text:F8220D4C    test    ecx, ecx
.text:F8220D4E    mov     [esp+30h+var_10], ecx
.text:F8220D52    jbe     short loc_F8220DC5
.text:F8220D54    mov     edi, [esp+30h+var_18]
.text:F8220D58    mov     [esp+30h+var_20], ebx
.text:F8220D5C
.text:F8220D5C loc_F8220D5C:              ; CODE XREF: LookupExportedFunction+11Bj
.text:F8220D5C    mov     ebx, [esp+30h+var_20]
.text:F8220D60    xor     esi, esi
.text:F8220D62    mov     si, [ebx]
.text:F8220D65    mov     ebx, [esp+30h+arg_0]
.text:F8220D69    cmp     esi, ebx
.text:F8220D6B    jnz     short loc_F8220DAA
.text:F8220D6D    mov     eax, [edi]
.text:F8220D6F    mov     esi, [esp+30h+arg_4]
.text:F8220D73    add     eax, edx
.text:F8220D75
.text:F8220D75 loc_F8220D75:              ; CODE XREF: LookupExportedFunction+F3j
.text:F8220D75    mov     bl, [eax]
.text:F8220D77    mov     cl, bl
.text:F8220D79    cmp     bl, [esi]
.text:F8220D7B    jnz     short loc_F8220D99
.text:F8220D7D    test    cl, cl
.text:F8220D7F    jz      short loc_F8220D95
.text:F8220D81    mov     bl, [eax+1]
.text:F8220D84    mov     cl, bl
.text:F8220D86    cmp     bl, [esi+1]
.text:F8220D89    jnz     short loc_F8220D99
.text:F8220D8B    add     eax, 2
.text:F8220D8E    add     esi, 2
.text:F8220D91    test    cl, cl
.text:F8220D93    jnz     short loc_F8220D75
.text:F8220D95
.text:F8220D95 loc_F8220D95:              ; CODE XREF: LookupExportedFunction+DFj
.text:F8220D95    xor     eax, eax
.text:F8220D97    jmp     short loc_F8220D9E
.text:F8220D99 ; ---------------------------------------------
.text:F8220D99
.text:F8220D99 loc_F8220D99:              ; CODE XREF: LookupExportedFunction+DBj
.text:F8220D99               ; LookupExportedFunction+E9j
.text:F8220D99    sbb     eax, eax
.text:F8220D9B    sbb     eax, 0FFFFFFFFh
.text:F8220D9E
.text:F8220D9E loc_F8220D9E:              ; CODE XREF: LookupExportedFunction+F7j
.text:F8220D9E    test    eax, eax
.text:F8220DA0    jz      short loc_F8220DED
.text:F8220DA2    mov     eax, [esp+30h+var_14]
.text:F8220DA6    mov     ecx, [esp+30h+var_10]
.text:F8220DAA
.text:F8220DAA loc_F8220DAA:              ; CODE XREF: LookupExportedFunction+CBj
.text:F8220DAA    mov     esi, [esp+30h+var_20]
.text:F8220DAE    inc     ebp
.text:F8220DAF    add     esi, 2
.text:F8220DB2    add     edi, 4
.text:F8220DB5    cmp     ebp, ecx
.text:F8220DB7    mov     [esp+30h+var_20], esi
.text:F8220DBB    jb      short loc_F8220D5C
.text:F8220DBD    mov     ebx, [esp+30h+var_C]
.text:F8220DC1    mov     edi, [esp+30h+var_8]
.text:F8220DC5
.text:F8220DC5 loc_F8220DC5:              ; CODE XREF: LookupExportedFunction+A5j
.text:F8220DC5               ; LookupExportedFunction+B2j
.text:F8220DC5    mov     ecx, [esp+30h+arg_0]
.text:F8220DC9    mov     esi, [esp+30h+var_1C]
.text:F8220DCD    inc     ecx
.text:F8220DCE    add     esi, 4
.text:F8220DD1    cmp     ecx, edi
.text:F8220DD3    mov     [esp+30h+arg_0], ecx
.text:F8220DD7    mov     [esp+30h+var_1C], esi
.text:F8220DDB    jb      loc_F8220D42
.text:F8220DE1
.text:F8220DE1 loc_F8220DE1:              ; CODE XREF: LookupExportedFunction+10j
.text:F8220DE1               ; LookupExportedFunction+21j ...
.text:F8220DE1    xor     eax, eax
.text:F8220DE3
.text:F8220DE3 loc_F8220DE3:              ; CODE XREF: LookupExportedFunction+69j
.text:F8220DE3               ; LookupExportedFunction+162j
.text:F8220DE3    pop     edi
.text:F8220DE4    pop     esi
.text:F8220DE5    pop     ebp
.text:F8220DE6    pop     ebx
.text:F8220DE7    add     esp, 20h
.text:F8220DEA    retn    0Ch
.text:F8220DED ; ---------------------------------------------
.text:F8220DED
.text:F8220DED loc_F8220DED:              ; CODE XREF: LookupExportedFunction+100j
.text:F8220DED    mov     eax, [esp+30h+var_4]
.text:F8220DF1    mov     ecx, [esp+30h+arg_0]
.text:F8220DF5    lea     ecx, [eax+ecx*4]
.text:F8220DF8    mov     eax, [ecx]
.text:F8220DFA    add     eax, edx
.text:F8220DFC    mov     edx, [esp+30h+arg_8]
.text:F8220E00    test    edx, edx
.text:F8220E02    jz      short loc_F8220DE3
.text:F8220E04    pop     edi
.text:F8220E05    pop     esi
.text:F8220E06    pop     ebp
.text:F8220E07    mov     [edx], ecx
.text:F8220E09    pop     ebx
.text:F8220E0A    add     esp, 20h
.text:F8220E0D    retn    0Ch
.text:F8220E0D LookupExportedFunction endp

未经过 ring 0 转换就在用户模式下直接调用 KAV 核心代码:

kd> bp f824d820
kd> g
Breakpoint 0 hit
klif!sub_F8231820:
001b:f824d820 83ec08      sub     esp,0x8
kd> kv
ChildEBP RetAddr  Args to Child    
          
WARNING: Stack unwind information not available. Following frames may be wrong.

0006f4ec 7432f69c 74320000 00000001 00000000 klif!sub_F8231820
0006f50c 7c9011a7 74320000 00000001 00000000 0x7432f69c
0006f52c 7c91cbab 7432f659 74320000 00000001 
ntdll!LdrpCallInitRoutine+0x14 0006f634 7c916178 00000000 c0150008 00000000
ntdll!LdrpRunInitializeRoutines+0x344 (FPO: [Non-Fpo]) 0006f8e0 7c9162da 00000000 0007ced0 0006fbd4
ntdll!LdrpLoadDll+0x3e5 (FPO: [Non-Fpo]) 0006fb88 7c801bb9 0007ced0 0006fbd4 0006fbb4
ntdll!LdrLoadDll+0x230 (FPO: [Non-Fpo]) 0006fc20 f824d749 0106c0f0 0000000e 0107348c 0x7c801bb9 0006fd14 7c918dfa 7c90d625 7c90eacf 00000000 klif!loc_F823173D+0xc 0006fe00 7c910551 000712e8 00000044 0006ff0c
ntdll!_LdrpInitialize+0x246 (FPO: [Non-Fpo]) 0006fecc 00000000 00072368 00000000 00078c48
ntdll!RtlFreeHeap+0x1e9 (FPO: [Non-Fpo]) kd> t klif!sub_F8231820+0x3: 001b:f824d823 53 push ebx kd> r eax=0006f3cc ebx=00000000 ecx=00005734 edx=0006f3ea esi=7c882fd3 edi=7432f608 eip=f824d823 esp=0006ef00 ebp=0006f4ec iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 klif!sub_F8231820+0x3: 001b:f824d823 53 push ebx kd> dg 1b P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- -------- -------- ---------- - -- -- -- -- -------- 001B 00000000 ffffffff Code RE 3 Bg Pg P Nl 00000cfa kd> !pte eip VA f824d823 PDE at C0300F80 PTE at C03E0934 contains 01010067 contains 06B78065 pfn 1010 ---DA--UWEV pfn 6b78 ---DA--UREV

当在用户调用模式下逐步转换它的核心模式代码时KAV便在开始破坏系统了 (毕竟很明显这是不可靠的!):

Breakpoint 0 hit
klif!sub_F8231820:
001b:f824d820 83ec08      sub     esp,0x8
kd> u eip
klif!sub_F8231820:
f824d820 ebfe             jmp     klif!sub_F8231820 (f824d820)
f824d822 085355           or      [ebx+0x55],dl
f824d825 56               push    esi
f824d826 57               push    edi
f824d827 33ed             xor     ebp,ebp
f824d829 6820d824f8       push    0xf824d820
f824d82e 896c2418         mov     [esp+0x18],ebp
f824d832 896c2414         mov     [esp+0x14],ebp
kd> g
Breakpoint 0 hit
klif!sub_F8231820:
001b:f824d820 ebfe        jmp     klif!sub_F8231820 (f824d820)
kd> g
Breakpoint 0 hit
klif!sub_F8231820:
001b:f824d820 ebfe        jmp     klif!sub_F8231820 (f824d820)
kd> bd 0
kd> g
Break instruction exception - code 80000003 (first chance)
*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run kd.exe) or,                                        *
*       CTRL+BREAK (if you run WinDBG),                                       *
*   on your debugger machine's keyboard.                                      *
*                                                                             *
*                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
*                                                                             *
* If you did not intend to break into the debugger, press the "g" key, then   *
* press the "Enter" key now.  This message might immediately reappear.  If it *
* does, press "g" and "Enter" again.                                          *
*                                                                             *
*******************************************************************************
nt!RtlpBreakWithStatusInstruction:
804e3592 cc               int     3
kd> gu

*** Fatal System Error: 0x000000d1
                       (0x00003592,0x0000001C,0x00000000,0x00003592)

Break instruction exception - code 80000003 (first chance)
*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run kd.exe) or,                                        *
*       CTRL+BREAK (if you run WinDBG),                                       *
*   on your debugger machine's keyboard.                                      *
*                                                                             *
*                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
*                                                                             *
* If you did not intend to break into the debugger, press the "g" key, then   *
* press the "Enter" key now.  This message might immediately reappear.  If it *
* does, press "g" and "Enter" again.                                          *
*                                                                             *
*******************************************************************************
nt!RtlpBreakWithStatusInstruction:
804e3592 cc               int     3
kd> g
Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Loading Kernel Symbols
..........................
Loading User Symbols
................................
Loading unloaded module list
............
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck D1, {3592, 1c, 0, 3592}

*** ERROR: Module load completed but symbols could not be loaded for klif.sys
Probably caused by : hardware

Followup: MachineOwner
---------
 *** Possible invalid call from 804e331f ( nt!KeUpdateSystemTime+0x160 )
 *** Expected target 804e358e ( nt!DbgBreakPointWithStatus+0x0 )

nt!RtlpBreakWithStatusInstruction:
804e3592 cc               int     3
kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: 00003592, memory referenced
Arg2: 0000001c, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: 00003592, address which referenced memory

Debugging Details:
------------------


READ_ADDRESS:  00003592 

CURRENT_IRQL:  1c

FAULTING_IP: 
+3592
00003592 ??               ???

PROCESS_NAME:  winlogon.exe

DEFAULT_BUCKET_ID:  INTEL_CPU_MICROCODE_ZERO

BUGCHECK_STR:  0xD1

LAST_CONTROL_TRANSFER:  from 804e3324 to 00003592

FAILED_INSTRUCTION_ADDRESS: 
+3592
00003592 ??               ???

POSSIBLE_INVALID_CONTROL_TRANSFER:  from 804e331f to 804e358e

TRAP_FRAME:  f7872ce0 -- (.trap fffffffff7872ce0)
ErrCode = 00000000
eax=00000001 ebx=000275fc ecx=8055122c edx=000003f8 esi=00000005 edi=ddfff298
eip=00003592 esp=f7872d54 ebp=f7872d64 iopl=0         nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
00003592 ??               ???
Resetting default scope

STACK_TEXT:  
WARNING: Frame IP not in any known module. Following frames may be wrong.
f7872d50 804e3324 00000001 f7872d00 000000d1 0x3592
f7872d50 f824d820 00000001 f7872d00 000000d1 nt!KeUpdateSystemTime+0x165
0006f4ec 7432f69c 74320000 00000001 00000000 klif+0x22820
0006f50c 7c9011a7 74320000 00000001 00000000 ODBC32!_DllMainCRTStartup+0x52
0006f52c 7c91cbab 7432f659 74320000 00000001 ntdll!LdrpCallInitRoutine+0x14
0006f634 7c916178 00000000 c0150008 00000000 ntdll!LdrpRunInitializeRoutines+0x344
0006f8e0 7c9162da 00000000 0007ced0 0006fbd4 ntdll!LdrpLoadDll+0x3e5
0006fb88 7c801bb9 0007ced0 0006fbd4 0006fbb4 ntdll!LdrLoadDll+0x230
0006fbf0 7c801d6e 7ffddc00 00000000 00000000 kernel32!LoadLibraryExW+0x18e
0006fc04 7c801da4 0106c0f0 00000000 00000000 kernel32!LoadLibraryExA+0x1f
0006fc20 f824d749 0106c0f0 0000000e 0107348c kernel32!LoadLibraryA+0x94
00000000 00000000 00000000 00000000 00000000 klif+0x22749


STACK_COMMAND:  .trap 0xfffffffff7872ce0 ; kb

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME:  hardware

IMAGE_NAME:  hardware

DEBUG_FLR_IMAGE_TIMESTAMP:  0

BUCKET_ID:  CPU_CALL_ERROR

Followup: MachineOwner
---------
 *** Possible invalid call from 804e331f ( nt!KeUpdateSystemTime+0x160 )
 *** Expected target 804e358e ( nt!DbgBreakPointWithStatus+0x0 )

kd> u 804e331f 
nt!KeUpdateSystemTime+0x160:
804e331f e86a020000       call    nt!DbgBreakPointWithStatus (804e358e)
804e3324 ebb4             jmp     nt!KeUpdateSystemTime+0x11b (804e32da)
804e3326 90               nop
804e3327 fb               sti
804e3328 8d09             lea     ecx,[ecx]
nt!KeUpdateRunTime:
804e332a a11cf0dfff       mov     eax,[ffdff01c]
804e332f 53               push    ebx
804e3330 ff80c4050000     inc     dword ptr [eax+0x5c4]

提示:试试键盘 “← →” 可以实现快速翻页 

一键看全文

本文导航

相关阅读

每日精选

点击查看更多

首页 手机 数码相机 笔记本 游戏 DIY硬件 硬件外设 办公中心 数字家电 平板电脑