Kaspersky AntiVirus – CHM Parsing Stack Buffer Overflow

  • 作者: Google Security Research
    日期: 2015-09-22
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/38285/
  • Source: https://code.google.com/p/google-security-research/issues/detail?id=524
    
    Fuzzing CHM files with Kaspersky Antivirus produced the attached crash.
    
    (83c.fec): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=0bd3e470 ebx=00000ef1 ecx=00000000 edx=0b002fb0 esi=00000018 edi=0bd3e473
    eip=15edb522 esp=0bd3e234 ebp=0bd3e240 iopl=0 nv up ei pl nz na pe nc
    cs=0023ss=002bds=002bes=002bfs=0053gs=002b efl=00010206
    15edb522 8a12mov dl,byte ptr [edx]ds:002b:0b002fb0=??
    
    Where does edx come from?
    
    0:085> uf 15edb4f0
    15edb4f0 55pushebp
    ...
    15edb520 8b10mov edx,dword ptr [eax]
    15edb522 8a12mov dl,byte ptr [edx]
    15edb524 8817mov byte ptr [edi],dl
    15edb526 ff00inc dword ptr [eax]
    15edb528 47inc edi
    15edb529 83c6ffadd esi,0FFFFFFFFh
    15edb52c 83d1ffadc ecx,0FFFFFFFFh
    15edb52f 8bd6mov edx,esi
    15edb531 0bd1oredx,ecx
    15edb533 75ebjne 15edb520
    
    ...
    
    Edx is a parameter, and this is a simple memcpy loop.
    
    for (i = ArgSize; i > 0; i--) {
    *argDestPtr++ = *argSrcPtr++;
    }
    
    But why is the input pointer corrupt, that should be a pointer to the input buffer (i.e. the CHM being scanned)?
    
    0:018> kvn1
     # ChildEBP RetAddrArgs to Child
    00 03f4e1c0 15edb73b 0000022f 00000000 0afda8d4 0x15edb522
    0:018> ub 15edb73b 
    15edb725 3bc1cmp eax,ecx
    15edb727 774fja15edb778
    15edb729 52pushedx
    15edb72a 50pusheax
    15edb72b 8d95e8fdfffflea edx,[ebp-218h]<-- destination buffer
    15edb731 8bcbmov ecx,ebx
    15edb733 8d45fclea eax,[ebp-4]
    15edb736 e8b5fdffffcall15edb4f0
    
    
    Ah, the destination is a fixed size stack buffer (I'm guessing 512 bytes), so if the size read from the input is greater than 512 (in this case it's 0x22f), the stack will be corrupted.
    
    The input pointer is corrupt because the loop overwrites the src pointer with attacker controlled input and then it crashes trying to read from it. That can obviously be fixed by an attacker, so this is an exploitable stack buffer overflow.
    
    It seems likely /GS would have made this unexploitable.
    
    Proof of Concept:
    https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38285.zip