Advisory NTIADV0904
Avast! (AavmKer4.sys) Local Privilege Escalation Vulnerability
VendorALWIL Software a.s.
Affected SoftwareAvast! Home Edition < 4.8.1356
Avast! Professional Edition < 4.8.1356
Affected DriverAvast! Base Kernel-Mode Device Driver for Windows NT/2000/XP - AavmKer4.sys < 4.8.1356
Date Reported2009-08-25
Release Date2009-09-25
StatusFixed - avast! 4 Home/Professional Revision History
avast! Home Edition - English / avast! Professional Edition - English
ExploitAavmKer4_Exp.zip - Local Privilege Escalation Exploit
Disclosure Timeline 2009-08-25 - Vulnerability reported to vendor
2009-08-26 - Vendor response
2009-09-15 - Vendor asked for PoC Exploit
2009-09-18 - PoC Exploit sent to the vendor
2009-09-25 - Update released by the vendor
2009-09-29 - Full technical details released to general public
Description
Avast! software is prone to local privilege escalation vulnerabilities that occurs in the AavmKer4.sys driver.
Details
The vulnerability is caused due to an error in the AavmKer4.sys kernel driver when processing IOCTLs (0xB2D6000C and 0xB2D60034). The problem specifically exists because the driver allows untrusted user mode code to pass kernel addresses as arguments to the driver. This can be exploited to overwrite an arbitrary address and execute arbitrary code in kernel space via a specially crafted IOCTLs.

		...
		.text:000108A5 @@ioctl_B2D6000C:
		.text:000108A5                 cmp     esi, 0Ch                       ; InputBufferLength == 0x0C ??
		.text:000108A8                 jz      short @@valid_buffer_size
		.text:000108AA                 push    offset bad_buffer_size         ; "******* IOCTL_AAVM_SENDEVENTS bad buffe"...
		.text:000108AF                 jmp     @@dbg_print
		.text:000108B4
		.text:000108B4 @@valid_buffer_size:
		.text:000108B4                 mov     eax, [ebx+0Ch]                 ; SystemBuffer
		.text:000108B7                 mov     [ebp+0Ch], eax
		.text:000108BA                 mov     eax, [eax]
		.text:000108BC                 xor     esi, esi
		.text:000108BE                 cmp     eax, esi                       ; InputBuffer[0] == 0 ??
		.text:000108C0                 jz      short @@dereference_object1
		.text:000108C2                 push    esi                            ; HandleInformation
		.text:000108C3                 push    offset Object1                 ; Object
		.text:000108C8                 push    esi                            ; AccessMode
		.text:000108C9                 push    esi                            ; ObjectType
		.text:000108CA                 mov     edi, 1F0003h
		.text:000108CF                 push    edi                            ; DesiredAccess
		.text:000108D0                 push    eax                            ; Handle
		.text:000108D1                 call    ds:ObReferenceObjectByHandle
		.text:000108D7                 call    ds:PsGetCurrentProcessId
		.text:000108DD                 mov     UniqueProcess, eax
		.text:000108E2                 mov     Flag, esi
		.text:000108E8                 jmp     short @@reference_object2
		.text:000108EA
		.text:000108EA @@dereference_object1:
		.text:000108EA                 mov     ecx, Object1
		.text:000108F0                 cmp     ecx, esi
		.text:000108F2                 jz      short @@set_flag
		.text:000108F4                 call    ds:ObfDereferenceObject
		.text:000108FA                 mov     Object1, esi
		.text:00010900
		.text:00010900 @@set_flag:
		.text:00010900                 or      UniqueProcess, 0FFFFFFFFh
		.text:00010907                 mov     Flag, 1
		.text:00010911                 push    0C7Ch
		.text:00010916                 push    esi
		.text:00010917                 push    offset Buffer
		.text:0001091C                 call    memset
		.text:00010921                 add     esp, 0Ch
		.text:00010924                 push    esi                            ; Wait
		.text:00010925                 push    esi                            ; Increment
		.text:00010926                 push    offset Event                   ; Event
		.text:0001092B                 call    ds:KeSetEvent
		.text:00010931                 mov     edi, 1F0003h
		.text:00010936
		.text:00010936 @@reference_object2:
		.text:00010936                 mov     eax, [ebp+0Ch]                 ; SystemBuffer
		.text:00010939                 mov     eax, [eax+8]
		.text:0001093C                 cmp     eax, esi                       ; InputBuffer[2] == 0 ??
		.text:0001093E                 jz      short @@dereference_object2
		.text:00010940                 push    esi
		.text:00010941                 push    offset Object2
		.text:00010946                 push    esi
		.text:00010947                 push    esi
		.text:00010948                 push    edi
		.text:00010949                 push    eax
		.text:0001094A                 call    ds:ObReferenceObjectByHandle
		.text:00010950                 mov     Flag, esi
		.text:00010956                 jmp     short @@reference_object3
		.text:00010958
		.text:00010958 @@dereference_object2:
		.text:00010958                 mov     ecx, Object2
		.text:0001095E                 cmp     ecx, esi
		.text:00010960                 jz      short @@reference_object3
		.text:00010962                 call    ds:ObfDereferenceObject
		.text:00010968                 mov     Object2, esi
		.text:0001096E
		.text:0001096E @@reference_object3:
		.text:0001096E                 mov     eax, [ebp+0Ch]                 ; SystemBuffer
		.text:00010971                 mov     eax, [eax+4]
		.text:00010974                 cmp     eax, esi                       ; InputBuffer[1] == 0 ??
		.text:00010976                 jz      short @@dereference_object3
		.text:00010978                 push    esi
		.text:00010979                 push    offset Object3
		.text:0001097E                 push    esi
		.text:0001097F                 push    esi
		.text:00010980                 push    edi
		.text:00010981                 push    eax
		.text:00010982                 call    ds:ObReferenceObjectByHandle
		.text:00010988                 mov     Flag, esi
		.text:0001098E                 jmp     @@complete_request
		.text:00010993
		.text:00010993 @@dereference_object3:
		.text:00010993                 mov     ecx, Object3
		.text:00010999                 cmp     ecx, esi
		.text:0001099B                 jz      @@complete_request
		.text:000109A1                 call    ds:ObfDereferenceObject
		.text:000109A7                 mov     Object3, esi
		.text:000109AD                 jmp     @@complete_request
		...
		
... .text:00010B3F @@ioctl_B2D60034: .text:00010B3F cmp esi, 8 ; InputBufferLength == 8 ?? .text:00010B42 jnz short @@invalid_parameter .text:00010B44 call ds:PsGetCurrentProcessId .text:00010B4A cmp UniqueProcess, eax .text:00010B50 jnz short @@invalid_parameter .text:00010B52 mov esi, [ebx+0Ch] ; SystemBuffer .text:00010B55 mov dword ptr [ebx+1Ch], 4 .text:00010B5C cmp GetRoutineAddressesFlag, 0 .text:00010B63 jz @@set_information .text:00010B69 call ds:KeGetCurrentThread .text:00010B6F push 2 ; ImpersonationLevel .text:00010B71 push 1 ; EffectiveOnly .text:00010B73 push 1 ; CopyOnOpen .text:00010B75 push dword ptr [esi] ; Token <- InputBuffer[0] .text:00010B77 push eax ; Thread .text:00010B78 call PsImpersonateClient .text:00010B7E mov [ebx+18h], eax .text:00010B81 jmp @@complete_request ...
Copyright © 2oo8-2oo9 NT Internals. All rights reserved.