[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[TKADV2010-003] avast! 4.8 and 5.0 aavmker4.sys Kernel Memory Corruption

Please find attached a detailed advisory of the vulnerability.

Alternatively, the advisory can also be found at:
Hash: SHA1

Advisory:               avast! 4.8 and 5.0 aavmker4.sys Kernel Memory 
Advisory ID:            TKADV2010-003
Revision:               1.0
Release Date:           2010/02/22
Last Modified:          2010/02/22
Date Reported:          2010/02/01
Author:                 Tobias Klein (tk at trapkit.de)
Affected Software:      avast! 4.8 <= 4.8.1368.0
                        avast! 5.0 < 5.0.418.0
Remotely Exploitable:   No
Locally Exploitable:    Yes
Vendor URL:             http://www.avast.com
Vendor Status:          Vendor has released an updated version
Patch development time: 10 days

Vulnerability Details: 

The kernel driver aavmker4.sys shipped with avast! 4.8 and 5.0 contains a
vulnerability in the code that handles IOCTL requests. Exploitation of this
vulnerability can result in:

1) local denial of service attacks (system crash due to a kernel panic), or

2) local execution of arbitrary code at the kernel level (complete system

The issue can be triggered by sending a specially crafted IOCTL request.

No special user rights are required to exploit the vulnerability.

Technical Details:

The IOCTL call 0xb2d60030 of the aavmker4.sys kernel driver shipped with
avast! 4.8 and 5.0 accepts user supplied input that doesn't get validated 
enough. In consequence it is possible to overwrite arbitrary kernel space 
and user space memory addresses with arbitrary values. This can be 
exploited to control the kernel execution flow and to execute
arbitrary code at the kernel level.

Disassembly of aavmker4.sys (avast! 4.8, file version 4.8.1356.0):

.text:00010E46 [1]  cmp    eax, 0B2D60030h ; vulnerable IOCTL
.text:00010E4B      jz     loc_10EEF
.text:00010EEF    loc_10EEF: 
.text:00010EEF      cmp    byte_1262C, 0
.text:00010EF6      jz     short loc_10F0C
.text:00010F0C    loc_10F0C:
.text:00010F0C [2]  mov    edi, [ebx+0Ch]
.text:00010F0F [3]  cmp    esi, 878h       ; InputBufferSize == 0x878?
.text:00010F15      jz     short loc_10F21

[1] Vulnerable IOCTL  
[2] EDI now points to user controlled IOCTL input data
[3] The size of the IOCTL input data must be equal to 0x878 

.text:00010F21    loc_10F21: 
.text:00010F21      and    [ebp+var_4], 0
.text:00010F25      cmp    dword ptr [edi], 0
.text:00010F28      jz     loc_10FC5
.text:00010F2E [4]  mov    esi, [edi+870h]
.text:00010F34      mov    [ebp+v34_uc], esi
.text:00010F37      mov    eax, ds:MmUserProbeAddress
.text:00010F3C [5]  cmp    esi, [eax]      ; user space or kernel space?
.text:00010F3E      jnb    short loc_10F46

[4] If the input size equals 0x878 a pointer value gets extracted from the 
    user supplied IOCTL input data and saved in ESI
[5] It is checked if ESI points into user space or kernel space

.text:00010F46    loc_10F46: 
.text:00010F46      push   esi             ; VirtualAddress
.text:00010F47 [6]  call   ds:MmIsAddressValid
.text:00010F4D      test   al, al
.text:00010F4F      jz     short loc_10F5F
.text:00010F51      lea    eax, [esi+8]
.text:00010F54      push   eax             ; VirtualAddress
.text:00010F55 [7]  call   ds:MmIsAddressValid
.text:00010F5B      test   al, al
.text:00010F5D      jnz    short loc_10F65

[6] + [7] If ESI points to an address in kernel space it is checked if ESI 
          and ESI+8 are pointing to valid memory addresses

.text:00010F65    loc_10F65:
.text:00010F65 [8]  mov    eax, [esi]
.text:00010F67      mov    [ebp+v32_uc], eax
.text:00010F6A [9]  mov    esi, [esi+4]
.text:00010F6D      mov    [ebp+var_4C], esi
.text:00010F70 [10] xor    [ebp+v32_uc], 55667788h
.text:00010F77 [11] xor    esi, 11223344h
.text:00010F7D      mov    [ebp+var_4C], esi
.text:00010F80      mov    eax, dword_125E8
.text:00010F85 [12] cmp    eax, [ebp+v32_uc] ; check pattern1
.text:00010F88      jnz    short loc_10F93
.text:00010F8A      mov    eax, dword_125EC
.text:00010F8F [13] cmp    eax, esi        ; check pattern2
.text:00010F91      jz     short loc_10F99

[8] + [9] If the addresses are valid, EAX and ESI are filled with data 
          from the user defined kernel space address (pointed to by ESI)

The first value (EAX) is xor'ed with 0x55667788 (see [10]) and then 
compared with the value 0x85B8DA8F found at dword_125E8 (see [12]).

.data:000125E8 dword_125E8     dd 85B8DA8Fh  

The second value (ESI) is xor'ed with 0x11223344 (see [11]) and then 
compared with the value 0x198E3FE found at dword_125EC (see [13]).

.data:000125EC dword_125EC     dd 198E3FEh 

If both patterns match, the following code gets executed:

.text:00010F99    loc_10F99:
.text:00010F99      xor    edx, edx
.text:00010F9B      mov    eax, [ebp+v34_uc]
.text:00010F9E      mov    [eax], edx
.text:00010FA0      mov    [eax+4], edx
.text:00010FA3      lea    esi, [edi+4]    ; src
.text:00010FA6      mov    ecx, 21Ah       ; len
.text:00010FAB      mov    edi, [eax+18h]  ; dst
.text:00010FAE [14] rep movsd              ; memcpy

The memcpy function at [14] gets called with the following parameters: 

memcpy (EDI, ESI, ECX); 
EDI (dst): this value is extracted from a user defined kernel space address
ESI (src): points to user controlled IOCTL input data
ECX (len): 0x21A


If an attacker were able to (temporarily) store user controlled data at a 
user defined address in kernel space, the check at [5] could be passed and 
the memcpy() call would lead to an exploitable memory corruption condition.

Unfortunately, the aavmker4.sys driver supports at least one IOCTL that 
allows an unprivileged user to temporarily store arbitrary data at a known 
kernel space address.


STEP 1: Use one of the IOCTLs supported by aavmker4.sys to temporarily 
store arbitrary data at a known kernel space address (e.g. the IOCTL 
0xb2d6001c). This data has to start with the two patterns that are checked 
at [12] and [13].

STEP 2: Send a request to the vulnerable IOCTL. Store a pointer at offset 
0x870 of the IOCTL data that points to the kernel space address of STEP 1.


  Update to avast! 5.0 >= 5.0.418.

Disclosure Timeline: 
  Format: year/month/day
  2010/01/24 - Vendor notified using info@xxxxxxxxx
  2010/01/29 - Vendor response with PGP key
  2010/02/01 - Detailed vulnerability information sent to the vendor 
  2010/02/01 - Vendor confirms the vulnerability  
  2010/02/09 - Status update by ALWIL Software
  2010/02/11 - Vendor releases updated version
  2010/02/22 - Release date of this security advisory


  Vulnerability found and advisory written by Tobias Klein.


 [REF1] http://forum.avast.com/index.php?topic=55484.0
 [REF2] http://www.trapkit.de/advisories/TKADV2010-003.txt


  Revision 0.1 - Initial draft release to the vendor
  Revision 1.0 - Public release


The information within this advisory may change without notice. Use
of this information constitutes acceptance for use in an AS IS
condition. There are no warranties, implied or express, with regard
to this information. In no event shall the author be liable for any
direct or indirect damages whatsoever arising out of or in connection
with the use or spread of this information. Any use of this
information is at the user's own risk.

PGP Signature Key: 


Copyright 2010 Tobias Klein. All rights reserved.

Version: PGP
Charset: utf-8