Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:13198
HistoryJun 15, 2006 - 12:00 a.m.

Allowing User-mode Code to Access Kernel Memory

2006-06-1500:00:00
vulners.com
19

Allowing User-mode Code to Access Kernel Memory

One of the most important principles of the kernel/user division that modern operating systems enforce is that user mode is not allowed to directly access kernel mode memory. This is necessary to enforce system stability, such as to prevent a buggy user mode program from corrupting the kernel and bringing down the whole system. Unfortunately, the KAV programmers appear to think that this distinction is not really so important after all.

One of the strangest of the unsafe practices implemented by KAV is to allow user mode to directly call some portions of their kernel driver (within kernel address space!) instead of just loading a user mode DLL (or otherwise loading user mode code in the target process).

This mechanism appears to be used to inspect DLLs as they are loaded - a task which would be much better accomplished with PsSetLoadImageNotifyRoutine.

KAV patches kernel32.dll as a new process is created, such that the export table points all of the DLL-loading routines (e.g. LoadLibraryA) to a thunk that calls portions of KAV's driver in kernel mode. Additionally, KAV modifies protections on parts of its code and data sections to allow user mode read access.

KAV sets a PsLoadImageNotifyRoutine hook to detect kernel32.dll being loaded in order to know when to patch kernel32's export table. The author wonders why KAV did not just do their work from within PsSetLoadImageNotifyRoutine directly instead of going through all the trouble to allow user mode to call kernel mode for a LoadLibrary hook.

The CheckInjectCodeForNewProcess function is called when a new process loads an image, and checks for kernel32 being loaded. If this is the case, it will queue an APC to the process that will perform patching.

.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

The APC routine itself patches kernel32's export table (and generates the thunks to call kernel mode) and adjusts PTE attributes on KAV's driver image to allow user mode access.

.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

The actual image patching reprotects the export table of kernel32, changes the export address table entries for the LoadLibrary* family of functions to point to a thunk that is written into spare space within the kernel32 image, and writes the actual thunk code out:

.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 writes a new RVA pointing to its hook code here.
.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's export table reprotecting code assumes that the user mode PE header is well-formed and does not contain offsets pointing to kernel mode addresses:

.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+eax4]
.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

The mechanism that KAV uses to reprotect user mode code is much of a hack as well. KAV dynamically determines the system call ordinal of the NtProtectVirtualMemory system service and uses its own int 2e thunk to call the service.

.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's export lookup code does not correctly validate offsets garnered from the PE header before using them:

.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+eax4]
.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

User mode calling KAV kernel code directly without a ring 0 transition:

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 crashing the system when stepping through its kernel mode code when called from user mode (apparently not that reliable after all!):

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]