Advisory NTIADV0814
ArcaVir (ps_drv.sys) Multiple Privilege Escalation Vulnerabilities
VendorArcaBit Sp. z o.o.
Affected SoftwareArcaVir 2009 Antivirus Protection < 9.4.3201.9
ArcaVir 2009 Internet Security < 9.4.3202.9
ArcaVir 2009 System Protection < 9.4.3203.9
ArcaVir 2009 Home Protection < 9.4.3204.9
Affected Driverps_drv.sys
Date Reported2008-12-23
Release Date2009-05-23
StatusPartially Fixed
ArcaVir 2009 Antivirus Protection 9.4.3201.9
ArcaVir 2009 Internet Security 9.4.3202.9
ArcaVir 2009 System Protection 9.4.3203.9
ArcaVir 2009 Home Protection 9.4.3204.9
ExploitPsDrv_Exp.zip - Local Privilege Escalation Exploit
Disclosure Timeline 2008-12-23 - Vulnerability reported to vendor
2009-01-02 - Vendor response
2009-01-13 - First incomplete update released
2009-01-24 - Status update request
2009-01-25 - Vendor response
2009-01-27 - Vulnerability description sent to vendor
2009-01-27 - Vendor response
2009-04-10 - Status update request
2009-04-11 - Vendor response
2009-04-15 - Second update released by vendor
2009-04-16 - Vulnerability description sent to vendor
2009-04-16 - Vendor response
2009-04-22 - Third update released by vendor
2009-05-19 - Status update request (no response)
2009-05-23 - Full technical details released to general public
Description
ArcaVir is prone to a local privilege escalation vulnerabilities that occurs in the ps_drv.sys driver. This driver allows any user to open the device "\\Device\\ps_drv" and issue IOCTLs with a buffering mode of METHOD_NEITHER.
Details
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 IOCTL.

This is only one example (IOCTL 0x2A7B802B) of many vulnerable IOCTLs.

		seg000:00023F3C RootkitMemoryBlock proc near
		seg000:00023F3C
		seg000:00023F3C ArcaStruct = dword ptr -14h
		seg000:00023F3C Buffer = dword ptr -10h
		seg000:00023F3C InputBuffer = dword ptr -0Ch
		seg000:00023F3C BufferLength = dword ptr -8
		seg000:00023F3C Address = dword ptr -4
		seg000:00023F3C
		seg000:00023F3C           push  ebp
		seg000:00023F3D           mov   ebp, esp
		seg000:00023F3F           sub   esp, 14h
		seg000:00023F42           mov   [ebp+ArcaStruct], ecx
		seg000:00023F45           push  offset StrRootkitMemBlock    ; "ROOTKIT_MEMBLOCK\n"
		seg000:00023F4A           call  DbgPrint
		seg000:00023F4F           add   esp, 4
		seg000:00023F52           mov   eax, [ebp+ArcaStruct]
		seg000:00023F55           cmp   [eax+_ARCA_STRUCT.InputBufferLength], 8
		seg000:00023F5C           jnz   short @@invalid_input_buffer_size
		seg000:00023F5E           mov   ecx, [ebp+ArcaStruct]
		seg000:00023F61           cmp   [ecx+_ARCA_STRUCT.Type3InputBuffer], 0
		seg000:00023F68           jnz   short @@check_passed_parameters
		seg000:00023F6A
		seg000:00023F6A @@invalid_input_buffer_size:
		seg000:00023F6A           push  offset StrInvalidInputBufferSize ; "Zły rozmiar input bufora\n"
		seg000:00023F6F           call  DbgPrint
		seg000:00023F74           add   esp, 4
		seg000:00023F77           mov   eax, STATUS_INVALID_BUFFER_SIZE
		seg000:00023F7C           jmp   @@exit
		seg000:00023F81
		seg000:00023F81 @@check_passed_parameters:
		seg000:00023F81           mov   edx, [ebp+ArcaStruct]
		seg000:00023F84           mov   eax, [edx+_ARCA_STRUCT.Type3InputBuffer]
		seg000:00023F8A           mov   ecx, [eax]
		seg000:00023F8C           mov   edx, [eax+4]
		seg000:00023F8F           mov   [ebp+InputBuffer], ecx
		seg000:00023F92           mov   [ebp+BufferLength], edx
		seg000:00023F95           cmp   [ebp+BufferLength], 0
		seg000:00023F99           jnz   short @@check_output_buffer
		seg000:00023F9B           push  offset StrInvalidInputAddress ; "Zerowy rozmiar bufora do odczytu\n"
		seg000:00023FA0           call  DbgPrint
		seg000:00023FA5           add   esp, 4
		seg000:00023FA8           mov   eax, STATUS_INVALID_PARAMETER
		seg000:00023FAD           jmp   @@exit
		seg000:00023FB2
		seg000:00023FB2 @@check_output_buffer:
		seg000:00023FB2           mov   eax, [ebp+ArcaStruct]
		seg000:00023FB5           mov   ecx, [eax+_ARCA_STRUCT.OutputBufferLength]
		seg000:00023FBB           cmp   ecx, [ebp+BufferLength]
		seg000:00023FBE           jnz   short @@invalid_output_buffer_size
		seg000:00023FC0           mov   edx, [ebp+ArcaStruct]
		seg000:00023FC3           cmp   [edx+_ARCA_STRUCT.UserBuffer], 0
		seg000:00023FCA           jnz   short @@check_address
		seg000:00023FCC
		seg000:00023FCC @@invalid_output_buffer_size:
		seg000:00023FCC           push  offset StrInvalidOutputBufferSize ; "Zły rozmiar output bufora\n"
		seg000:00023FD1           call  DbgPrint
		seg000:00023FD6           add   esp, 4
		seg000:00023FD9           mov   eax, STATUS_INVALID_BUFFER_SIZE
		seg000:00023FDE           jmp   short @@exit
		seg000:00023FE0
		seg000:00023FE0 @@check_address:
		seg000:00023FE0           mov   eax, [ebp+InputBuffer]
		seg000:00023FE3           mov   [ebp+Buffer], eax
		seg000:00023FE6           mov   ecx, [ebp+BufferLength]
		seg000:00023FE9           mov   edx, [ebp+InputBuffer]
		seg000:00023FEC           lea   eax, [edx+ecx-1]
		seg000:00023FF0           mov   [ebp+Address], eax
		seg000:00023FF3           mov   ecx, [ebp+Address]
		seg000:00023FF6           push  ecx
		seg000:00023FF7           mov   edx, [ebp+Buffer]
		seg000:00023FFA           push  edx
		seg000:00023FFB           call  CheckAddress
		seg000:00024000           movsx eax, ax
		seg000:00024003           test  eax, eax
		seg000:00024005           jnz   short @@copy_memory
		seg000:00024007           push  offset StrInvalidMemoryRange ; "Niedostepny zakres pamięci\n"
		seg000:0002400C           call  DbgPrint
		seg000:00024011           add   esp, 4
		seg000:00024014           mov   eax, STATUS_RANGE_NOT_FOUND
		seg000:00024019           jmp   short @@exit
		seg000:0002401B
		seg000:0002401B @@copy_memory:
		seg000:0002401B           mov   ecx, [ebp+BufferLength]
		seg000:0002401E           push  ecx
		seg000:0002401F           mov   edx, [ebp+InputBuffer]
		seg000:00024022           push  edx
		seg000:00024023           mov   eax, [ebp+ArcaStruct]
		seg000:00024026           mov   ecx, [eax+_ARCA_STRUCT.UserBuffer]
		seg000:0002402C           push  ecx
		seg000:0002402D           call  memcpy
		seg000:00024032           add   esp, 0Ch
		seg000:00024035           mov   edx, [ebp+ArcaStruct]
		seg000:00024038           mov   eax, [edx+_ARCA_STRUCT.IoStatus]
		seg000:0002403E           mov   ecx, [ebp+BufferLength]
		seg000:00024041           mov   [eax+_IO_STATUS_BLOCK.Information], ecx
		seg000:00024044           mov   edx, [ebp+ArcaStruct]
		seg000:00024047           mov   eax, [edx+_ARCA_STRUCT.IoStatus]
		seg000:0002404D           mov   [eax+_IO_STATUS_BLOCK.Status], 0
		seg000:00024053           xor   eax, eax
		seg000:00024055
		seg000:00024055 @@exit:
		seg000:00024055           mov   esp, ebp
		seg000:00024057           pop   ebp
		seg000:00024058           retn
		seg000:00024058 RootkitMemoryBlock endp
		
Copyright © 2oo8-2oo9 NT Internals. All rights reserved.