Changeset 52953 in vbox for trunk/src/VBox/HostDrivers/Support
- Timestamp:
- Oct 6, 2014 1:30:20 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 96395
- Location:
- trunk/src/VBox/HostDrivers/Support/win
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52949 r52953 229 229 static NTSTATUS (NTAPI * g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, 230 230 PLARGE_INTEGER, ULONG, ULONG, HANDLE); 231 /** Pointer to the NtCreateSection function in NtDll (for patching purposes). */ 232 static uint8_t *g_pbNtCreateSection; 233 /** The patched NtCreateSection bytes (for restoring). */ 234 static uint8_t g_abNtCreateSectionPatch[16]; 231 235 #if 0 232 236 /** The jump back address of the patched LdrLoadDll. */ … … 236 240 * LdrLoadDll operation. */ 237 241 static NTSTATUS (NTAPI * g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE); 242 /** Pointer to the LdrLoadDll function in NtDll (for patching purposes). */ 243 static uint8_t *g_pbLdrLoadDll; 244 /** The patched LdrLoadDll bytes (for restoring). */ 245 static uint8_t g_abLdrLoadDllPatch[16]; 246 238 247 /** The hash table of verifier cache . */ 239 248 static PVERIFIERCACHEENTRY volatile g_apVerifierCache[128]; … … 248 257 /** @ */ 249 258 259 /** Positive if the DLL notification callback has been registered, counts 260 * registration attempts as negative. */ 261 static int g_cDllNotificationRegistered = 0; 262 /** The registration cookie of the DLL notification callback. */ 263 static PVOID g_pvDllNotificationCookie = NULL; 250 264 251 265 /** Static error info structure used during init. */ … … 301 315 bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust, 302 316 bool *pfQuietFailure); 317 static void supR3HardenedWinRegisterDllNotificationCallback(void); 318 static void supR3HardenedWinReInstallHooks(bool fFirst); 319 303 320 304 321 #ifdef RT_ARCH_AMD64 … … 1667 1684 1668 1685 /* 1686 * Make sure the DLL notification callback is registered. If we could, we 1687 * would've done this during early process init, but due to lack of heap 1688 * and uninitialized loader lock, it's not possible that early on. 1689 * 1690 * The callback protects our NtDll hooks from getting unhooked by 1691 * "friendly" fire from the AV crowd. 1692 */ 1693 supR3HardenedWinRegisterDllNotificationCallback(); 1694 1695 /* 1669 1696 * Process WinVerifyTrust todo before and after. 1670 1697 */ … … 1965 1992 1966 1993 1994 /** 1995 * DLL load and unload notification callback. 1996 * 1997 * This is a safety against our LdrLoadDll hook being replaced by protection 1998 * software. Though, we prefer the LdrLoadDll hook to this one as it allows us 1999 * to call WinVerifyTrust more freely. 2000 * 2001 * @param ulReason The reason we're called, see 2002 * LDR_DLL_NOTIFICATION_REASON_XXX. 2003 * @param pData Reason specific data. (Format is currently the same for 2004 * both load and unload.) 2005 * @param pvUser User parameter (ignored). 2006 * 2007 * @remarks Vista and later. 2008 * @remarks The loader lock is held when we're called, at least on Windows 7. 2009 */ 2010 static VOID CALLBACK supR3HardenedDllNotificationCallback(ULONG ulReason, PCLDR_DLL_NOTIFICATION_DATA pData, PVOID pvUser) 2011 { 2012 NOREF(pvUser); 2013 2014 /* 2015 * Screen the image on load. We will normally get a verification cache 2016 * hit here because of the LdrLoadDll and NtCreateSection hooks, so it 2017 * should be relatively cheap to recheck. In case our NtDll patches 2018 * got re 2019 * 2020 * This ASSUMES that we get informed after the fact as indicated by the 2021 * available documentation. 2022 */ 2023 if (ulReason == LDR_DLL_NOTIFICATION_REASON_LOADED) 2024 { 2025 SUP_DPRINTF(("supR3HardenedDllNotificationCallback: load %p LB %#010x %.*ls [fFlags=%#x]\n", 2026 pData->Loaded.DllBase, pData->Loaded.SizeOfImage, 2027 pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, 2028 pData->Loaded.Flags)); 2029 2030 /* Convert the windows path to an NT path and open it. */ 2031 HANDLE hRootDir; 2032 UNICODE_STRING NtPathUniStr; 2033 int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, pData->Loaded.FullDllName->Buffer, 2034 pData->Loaded.FullDllName->Length / sizeof(WCHAR)); 2035 if (RT_FAILURE(rc)) 2036 { 2037 supR3HardenedFatal("supR3HardenedDllNotificationCallback: RTNtPathFromWinUtf16Ex failed on '%.*ls': %Rrc\n", 2038 pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, rc); 2039 return; 2040 } 2041 2042 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; 2043 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 2044 OBJECT_ATTRIBUTES ObjAttr; 2045 InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/); 2046 2047 NTSTATUS rcNt = NtCreateFile(&hFile, 2048 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE, 2049 &ObjAttr, 2050 &Ios, 2051 NULL /* Allocation Size*/, 2052 FILE_ATTRIBUTE_NORMAL, 2053 FILE_SHARE_READ, 2054 FILE_OPEN, 2055 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 2056 NULL /*EaBuffer*/, 2057 0 /*EaLength*/); 2058 if (NT_SUCCESS(rcNt)) 2059 rcNt = Ios.Status; 2060 if (!NT_SUCCESS(rcNt)) 2061 { 2062 supR3HardenedFatal("supR3HardenedDllNotificationCallback: NtCreateFile failed on '%.*ls' / '%.*ls': %#x\n", 2063 pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, 2064 NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt); 2065 RTNtPathFree(&NtPathUniStr, &hRootDir); 2066 return; 2067 } 2068 2069 /* Do the screening. */ 2070 ULONG fAccess = 0; 2071 ULONG fProtect = 0; 2072 bool fCallRealApi = false; 2073 bool fQuietFailure = false; 2074 rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi, 2075 "LdrLoadDll", true /*fAvoidWinVerifyTrust*/, &fQuietFailure); 2076 NtClose(hFile); 2077 if (!NT_SUCCESS(rcNt)) 2078 { 2079 supR3HardenedFatal("supR3HardenedDllNotificationCallback: supR3HardenedScreenImage failed on '%.*ls' / '%.*ls': %#x\n", 2080 pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, 2081 NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt); 2082 RTNtPathFree(&NtPathUniStr, &hRootDir); 2083 return; 2084 } 2085 RTNtPathFree(&NtPathUniStr, &hRootDir); 2086 } 2087 /* 2088 * Log the unload call. 2089 */ 2090 else if (ulReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED) 2091 { 2092 SUP_DPRINTF(("supR3HardenedDllNotificationCallback: Unload %p LB %#010x %.*ls [flags=%#x]\n", 2093 pData->Unloaded.DllBase, pData->Unloaded.SizeOfImage, 2094 pData->Unloaded.FullDllName->Length / sizeof(WCHAR), pData->Unloaded.FullDllName->Buffer, 2095 pData->Unloaded.Flags)); 2096 } 2097 /* 2098 * Just log things we don't know and then return without caching anything. 2099 */ 2100 else 2101 { 2102 static uint32_t s_cLogEntries = 0; 2103 if (s_cLogEntries++ < 32) 2104 SUP_DPRINTF(("supR3HardenedDllNotificationCallback: ulReason=%u pData=%p\n", ulReason, pData)); 2105 return; 2106 } 2107 2108 /* 2109 * Use this opportunity to make sure our NtDll patches are still in place, 2110 * since they may be replaced by indecent protection software solutions. 2111 */ 2112 supR3HardenedWinReInstallHooks(false /*fFirstCall */); 2113 } 2114 2115 2116 /** 2117 * Registers the DLL notification callback if it hasn't already been registered. 2118 */ 2119 static void supR3HardenedWinRegisterDllNotificationCallback(void) 2120 { 2121 /* 2122 * The notification API was added in Vista, so it's an optional (weak) import. 2123 */ 2124 if ( LdrRegisterDllNotification != NULL 2125 && g_cDllNotificationRegistered <= 0 2126 && g_cDllNotificationRegistered > -32) 2127 { 2128 NTSTATUS rcNt = LdrRegisterDllNotification(0, supR3HardenedDllNotificationCallback, NULL, &g_pvDllNotificationCookie); 2129 if (NT_SUCCESS(rcNt)) 2130 { 2131 SUP_DPRINTF(("Registered Dll notification callback with NTDLL.\n")); 2132 g_cDllNotificationRegistered = 1; 2133 } 2134 else 2135 { 2136 supR3HardenedError(rcNt, false /*fFatal*/, "LdrRegisterDllNotification failed: %#x\n", rcNt); 2137 g_cDllNotificationRegistered--; 2138 } 2139 } 2140 } 2141 2142 1967 2143 #ifdef RT_ARCH_AMD64 1968 2144 /** … … 2210 2386 2211 2387 /** 2388 * Installs or reinstalls the NTDLL patches. 2389 */ 2390 static void supR3HardenedWinReInstallHooks(bool fFirstCall) 2391 { 2392 struct 2393 { 2394 size_t cbPatch; 2395 uint8_t const *pabPatch; 2396 uint8_t **ppbApi; 2397 const char *pszName; 2398 } const s_aPatches[] = 2399 { 2400 { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" }, 2401 { sizeof(g_abLdrLoadDllPatch), g_abLdrLoadDllPatch, &g_pbLdrLoadDll, "LdrLoadDll" }, 2402 }; 2403 2404 ULONG fAmIAlone = ~(ULONG)0; 2405 2406 for (uint32_t i = 0; i < RT_ELEMENTS(s_aPatches); i++) 2407 { 2408 uint8_t *pbApi = *s_aPatches[i].ppbApi; 2409 if (memcmp(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch) != 0) 2410 { 2411 /* 2412 * Log the incident if it's not the initial call. 2413 */ 2414 static uint32_t volatile s_cTimes = 0; 2415 if (!fFirstCall && s_cTimes < 128) 2416 { 2417 s_cTimes++; 2418 SUP_DPRINTF(("supR3HardenedWinReInstallHooks: Reinstalling %s (%p: %.*Rhxs).\n", 2419 s_aPatches[i].pszName, pbApi, s_aPatches[i].cbPatch, pbApi)); 2420 } 2421 2422 Assert(s_aPatches[i].cbPatch >= 4); 2423 2424 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READWRITE)); 2425 2426 /* 2427 * If we're alone, just memcpy the patch in. 2428 */ 2429 2430 #if 0 /* For testing purposes. */ 2431 if (fAmIAlone == ~(ULONG)0) 2432 { 2433 ULONG cbIgn = 0; 2434 NTSTATUS rcNt = NtQueryInformationThread(NtCurrentThread(), ThreadAmILastThread, 2435 &fAmIAlone, sizeof(fAmIAlone), &cbIgn); 2436 fAmIAlone = NT_SUCCESS(rcNt) && fAmIAlone != 0; 2437 } 2438 #else 2439 fAmIAlone = 0; 2440 #endif 2441 if (fAmIAlone) 2442 memcpy(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch); 2443 else 2444 { 2445 /* 2446 * Not alone. Start by injecting a JMP $-2, then waste some 2447 * CPU cycles to get the other threads a good chance of getting 2448 * out of the code before we replace it. 2449 */ 2450 RTUINT32U uJmpDollarMinus; 2451 uJmpDollarMinus.au8[0] = 0xeb; 2452 uJmpDollarMinus.au8[1] = 0xfe; 2453 uJmpDollarMinus.au8[2] = pbApi[2]; 2454 uJmpDollarMinus.au8[3] = pbApi[3]; 2455 ASMAtomicXchgU32((uint32_t volatile *)pbApi, uJmpDollarMinus.u); 2456 2457 NtYieldExecution(); 2458 NtYieldExecution(); 2459 2460 /* Copy in the tail bytes of the patch, then xchg the jmp $-2. */ 2461 if (s_aPatches[i].cbPatch > 4) 2462 memcpy(&pbApi[4], &s_aPatches[i].pabPatch[4], s_aPatches[i].cbPatch - 4); 2463 ASMAtomicXchgU32((uint32_t volatile *)pbApi, *(uint32_t *)s_aPatches[i].pabPatch); 2464 } 2465 2466 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READ)); 2467 } 2468 } 2469 } 2470 2471 2472 /** 2212 2473 * Install hooks for intercepting calls dealing with mapping shared libraries 2213 2474 * into the process. … … 2224 2485 * and inflexible. 2225 2486 */ 2226 DECLHIDDEN(void)supR3HardenedWinInstallHooks(void)2487 static void supR3HardenedWinInstallHooks(void) 2227 2488 { 2228 2489 NTSTATUS rcNt; 2229 2230 #ifndef VBOX_WITHOUT_DEBUGGER_CHECKS2231 /*2232 * Install a anti debugging hack before we continue. This prevents most2233 * notifications from ending up in the debugger. (Also applied to the2234 * child process when respawning.)2235 */2236 rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);2237 if (!NT_SUCCESS(rcNt))2238 supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,2239 "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);2240 #endif2241 2490 2242 2491 /* … … 2294 2543 */ 2295 2544 uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection; 2545 g_pbNtCreateSection = pbNtCreateSection; 2546 memcpy(g_abNtCreateSectionPatch, pbNtCreateSection, sizeof(g_abNtCreateSectionPatch)); 2547 /** @todo This patch could be simplified iff we had our own syscall operational 2548 * from the get-go. */ 2296 2549 2297 2550 #ifdef RT_ARCH_AMD64 … … 2321 2574 && pbNtCreateSection[ 9] == 0x05 2322 2575 && pbNtCreateSection[10] == 0xc3 /* ret */ 2323 2324 /* b8 22 35 ed 0 48 63 c0 ff e0 c3 f 1f 44 0 0 - necros2 - agnitum firewall? */2325 2576 ) 2326 2577 { … … 2338 2589 g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack); 2339 2590 *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal; 2340 *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection; 2341 2342 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READWRITE)); 2343 2344 pbNtCreateSection[0] = 0xff; 2345 pbNtCreateSection[1] = 0x25; 2346 *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]); 2347 2348 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READ)); 2591 2592 /* Assemble the patch. */ 2593 g_abNtCreateSectionPatch[0] = 0xff; 2594 g_abNtCreateSectionPatch[1] = 0x25; 2595 *(uint32_t *)&g_abNtCreateSectionPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]); 2596 2597 *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection; 2349 2598 puJmpTab++; 2350 2599 … … 2415 2664 *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal; 2416 2665 2417 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READWRITE)); 2418 2419 pbNtCreateSection[0] = 0xe9; 2420 *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection 2421 - (uintptr_t)&pbNtCreateSection[1+4]; 2422 2423 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READ)); 2424 2666 /* Assemble the patch. */ 2667 g_abNtCreateSectionPatch[0] = 0xe9; 2668 *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection 2669 - (uintptr_t)&pbNtCreateSection[1+4]; 2425 2670 #endif 2671 2672 /* 2673 * Exec page setup & management. 2674 */ 2675 uint32_t offExecPage = 0; 2676 memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE); 2426 2677 2427 2678 /* … … 2435 2686 */ 2436 2687 uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll; 2437 uint32_t offExecPage = 0;2438 mem set(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);2688 g_pbLdrLoadDll = pbLdrLoadDll; 2689 memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch)); 2439 2690 2440 2691 #ifdef RT_ARCH_AMD64 … … 2442 2693 * Patch 64-bit hosts. 2443 2694 */ 2444 # if 02445 /* Pattern #1:2446 Windows 8.1:2447 0:000> u ntdll!LdrLoadDll2448 ntdll!LdrLoadDll:2449 00007ffa`814ccd44 488bc4 mov rax,rsp2450 00007ffa`814ccd47 48895808 mov qword ptr [rax+8],rbx2451 00007ffa`814ccd4b 48896810 mov qword ptr [rax+10h],rbp2452 00007ffa`814ccd4f 48897018 mov qword ptr [rax+18h],rsi2453 00007ffa`814ccd53 48897820 mov qword ptr [rax+20h],rdi2454 00007ffa`814ccd57 4156 push r142455 00007ffa`814ccd59 4883ec70 sub rsp,70h2456 00007ffa`814ccd5d f6059cd2100009 test byte ptr [ntdll!LdrpDebugFlags (00007ffa`815da000)],92457 */2458 if ( pbLdrLoadDll[0] == 0x48 /* mov rax,rsp */2459 && pbLdrLoadDll[1] == 0x8b2460 && pbLdrLoadDll[2] == 0xc42461 && pbLdrLoadDll[3] == 0x48 /* mov qword ptr [rax+8],rbx */2462 && pbLdrLoadDll[4] == 0x892463 && pbLdrLoadDll[5] == 0x582464 && pbLdrLoadDll[6] == 0x08)2465 {2466 offJmpBack = 7; /* the 3rd instruction. */2467 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;2468 }2469 /*2470 Pattern #2:2471 Windows 8.0:2472 0:000> u ntdll_w8_64!LdrLoadDll2473 ntdll_w8_64!LdrLoadDll:2474 00007ffa`52ffa7c0 48895c2408 mov qword ptr [rsp+8],rbx2475 00007ffa`52ffa7c5 4889742410 mov qword ptr [rsp+10h],rsi2476 00007ffa`52ffa7ca 48897c2418 mov qword ptr [rsp+18h],rdi2477 00007ffa`52ffa7cf 55 push rbp2478 00007ffa`52ffa7d0 4156 push r142479 00007ffa`52ffa7d2 4157 push r152480 00007ffa`52ffa7d4 488bec mov rbp,rsp2481 00007ffa`52ffa7d7 4883ec60 sub rsp,60h2482 00007ffa`52ffa7db 8b05df321000 mov eax,dword ptr [ntdll_w8_64!LdrpDebugFlags (00007ffa`530fdac0)]2483 00007ffa`52ffa7e1 4d8bf1 mov r14,r92484 2485 */2486 else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+8],rbx */2487 && pbLdrLoadDll[1] == 0x892488 && pbLdrLoadDll[2] == 0x5c2489 && pbLdrLoadDll[3] == 0x242490 && pbLdrLoadDll[4] == 0x082491 && pbLdrLoadDll[5] == 0x48 /* mov qword ptr [rsp+10h],rsi */2492 && pbLdrLoadDll[6] == 0x892493 && pbLdrLoadDll[7] == 0x742494 && pbLdrLoadDll[8] == 0x242495 && pbLdrLoadDll[9] == 0x10)2496 {2497 offJmpBack = 10; /* the 3rd instruction. */2498 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;2499 }2500 /*2501 Pattern #3:2502 Windows 7:2503 ntdll_w7_64!LdrLoadDll:2504 00000000`58be4a20 48895c2410 mov qword ptr [rsp+10h],rbx2505 00000000`58be4a25 48896c2418 mov qword ptr [rsp+18h],rbp2506 00000000`58be4a2a 56 push rsi2507 00000000`58be4a2b 57 push rdi2508 00000000`58be4a2c 4154 push r122509 00000000`58be4a2e 4883ec50 sub rsp,50h2510 00000000`58be4a32 f605976e100009 test byte ptr [ntdll_w7_64!ShowSnaps (00000000`58ceb8d0)],92511 00000000`58be4a39 498bf1 mov rsi,r92512 2513 */2514 else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+10h],rbx */2515 && pbLdrLoadDll[1] == 0x892516 && pbLdrLoadDll[2] == 0x5c2517 && pbLdrLoadDll[3] == 0x242518 && pbLdrLoadDll[4] == 0x10)2519 {2520 offJmpBack = 5; /* the 2nd instruction. */2521 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type3;2522 }2523 /*2524 Pattern #4:2525 Windows Vista:2526 0:000> u ntdll_vista_64!LdrLoadDll2527 ntdll_vista_64!LdrLoadDll:2528 00000000`58c11f60 fff3 push rbx2529 00000000`58c11f62 56 push rsi2530 00000000`58c11f63 57 push rdi2531 00000000`58c11f64 4154 push r122532 00000000`58c11f66 4155 push r132533 00000000`58c11f68 4156 push r142534 00000000`58c11f6a 4157 push r152535 00000000`58c11f6c 4881ecb0020000 sub rsp,2B0h2536 00000000`58c11f73 488b05367b0e00 mov rax,qword ptr [ntdll_vista_64!_security_cookie (00000000`58cf9ab0)]2537 00000000`58c11f7a 4833c4 xor rax,rsp2538 00000000`58c11f7d 48898424a0020000 mov qword ptr [rsp+2A0h],rax2539 2540 */2541 else if ( pbLdrLoadDll[0] == 0xff /* push rbx */2542 && pbLdrLoadDll[1] == 0xf32543 && pbLdrLoadDll[2] == 0x56 /* push rsi */2544 && pbLdrLoadDll[3] == 0x57 /* push rdi */2545 && pbLdrLoadDll[4] == 0x41 /* push r12 */2546 && pbLdrLoadDll[5] == 0x54)2547 {2548 offJmpBack = 6; /* the 5th instruction. */2549 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type4;2550 }2551 /*2552 Pattern #5:2553 Windows XP64:2554 0:000> u ntdll!LdrLoadDll2555 ntdll!LdrLoadDll:2556 00000000`78efa580 4c8bdc mov r11,rsp2557 00000000`78efa583 4881ece8020000 sub rsp,2E8h2558 00000000`78efa58a 49895bf8 mov qword ptr [r11-8],rbx2559 00000000`78efa58e 498973f0 mov qword ptr [r11-10h],rsi2560 00000000`78efa592 49897be8 mov qword ptr [r11-18h],rdi2561 00000000`78efa596 4d8963e0 mov qword ptr [r11-20h],r122562 00000000`78efa59a 4d896bd8 mov qword ptr [r11-28h],r132563 00000000`78efa59e 4d8973d0 mov qword ptr [r11-30h],r142564 00000000`78efa5a2 4d897bc8 mov qword ptr [r11-38h],r152565 00000000`78efa5a6 488b051bd10a00 mov rax,qword ptr [ntdll!_security_cookie (00000000`78fa76c8)]2566 00000000`78efa5ad 48898424a0020000 mov qword ptr [rsp+2A0h],rax2567 00000000`78efa5b5 4d8bf9 mov r15,r92568 00000000`78efa5b8 4c8bf2 mov r14,rdx2569 00000000`78efa5bb 4c8be9 mov r13,rcx2570 00000000`78efa5be 4c89442458 mov qword ptr [rsp+58h],r82571 00000000`78efa5c3 66c74424680000 mov word ptr [rsp+68h],02572 2573 */2574 else if ( pbLdrLoadDll[0] == 0x4c /* mov r11,rsp */2575 && pbLdrLoadDll[1] == 0x8b2576 && pbLdrLoadDll[2] == 0xdc2577 && pbLdrLoadDll[3] == 0x48 /* sub rsp,2e8h */2578 && pbLdrLoadDll[4] == 0x812579 && pbLdrLoadDll[5] == 0xec2580 && pbLdrLoadDll[6] == 0xe82581 && pbLdrLoadDll[7] == 0x022582 && pbLdrLoadDll[8] == 0x002583 && pbLdrLoadDll[9] == 0x00)2584 {2585 offJmpBack = 10; /* the 3rd instruction. */2586 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type5;2587 }2588 else2589 supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);2590 # else2591 2695 /* Just use the disassembler to skip 6 bytes or more. */ 2592 2696 DISSTATE Dis; … … 2603 2707 offJmpBack += cbInstr; 2604 2708 } 2605 # endif2606 2709 2607 2710 /* Assemble the code for resuming the call.*/ … … 2618 2721 offExecPage = RT_ALIGN_32(offJmpBack + 8, 16); 2619 2722 2620 /* Patch the function. */ 2723 /* Assemble the LdrLoadDll patch. */ 2724 Assert(offJmpBack >= 6); 2725 g_abLdrLoadDllPatch[0] = 0xff; 2726 g_abLdrLoadDllPatch[1] = 0x25; 2727 *(uint32_t *)&g_abLdrLoadDllPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]); 2728 2621 2729 *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll; 2622 2623 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE));2624 2625 Assert(offJmpBack >= 6);2626 pbLdrLoadDll[0] = 0xff;2627 pbLdrLoadDll[1] = 0x25;2628 *(uint32_t *)&pbLdrLoadDll[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);2629 2630 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READ));2631 2730 puJmpTab++; 2632 2731 … … 2635 2734 * Patch 32-bit hosts. 2636 2735 */ 2637 # if 02638 /* Pattern #1:2639 Windows 7:2640 0:000> u ntdll!LdrLoadDll2641 ntdll!LdrLoadDll:2642 77aff585 8bff mov edi,edi2643 77aff587 55 push ebp2644 77aff588 8bec mov ebp,esp2645 77aff58a 51 push ecx2646 77aff58b 51 push ecx2647 77aff58c a1f8bdaf77 mov eax,dword ptr [ntdll!LdrpLogLevelStateTable+0x24 (77afbdf8)]2648 2649 Windows 8 rtm:2650 0:000:x86> u ntdll_67150000!LdrLoadDll2651 ntdll_67150000!LdrLoadDll:2652 67189f3f 8bff mov edi,edi2653 67189f41 55 push ebp2654 67189f42 8bec mov ebp,esp2655 67189f44 8b0d10eb2467 mov ecx,dword ptr [ntdll_67150000!LdrpDebugFlags (6724eb10)]2656 2657 Windows 8.1:2658 0:000:x86> u ntdll_w81_32!LdrLoadDll2659 ntdll_w81_32!LdrLoadDll:2660 6718aade 8bff mov edi,edi2661 6718aae0 55 push ebp2662 6718aae1 8bec mov ebp,esp2663 6718aae3 83ec14 sub esp,14h2664 6718aae6 f6050040246709 test byte ptr [ntdll_w81_32!LdrpDebugFlags (67244000)],92665 2666 Pattern #2:2667 Windows XP:2668 0:000:x86> u ntdll_xp!LdrLoadDll2669 ntdll_xp!LdrLoadDll:2670 77f569d2 6858020000 push 258h2671 77f569d7 68d866f777 push offset ntdll_xp!`string'+0x12c (77f766d8)2672 77f569dc e83bb20200 call ntdll_xp!_SEH_prolog (77f81c1c)2673 77f569e1 33db xor ebx,ebx2674 77f569e3 66895de0 mov word ptr [ebp-20h],bx2675 77f569e7 33c0 xor eax,eax2676 77f569e9 8d7de2 lea edi,[ebp-1Eh]2677 77f569ec ab stos dword ptr es:[edi]2678 2679 Windows Server 2003:2680 0:000:x86> u ntdll_w2k3_32!LdrLoadDll2681 ntdll_w2k3_32!LdrLoadDll:2682 7c833f63 6840020000 push 240h2683 7c833f68 68b040837c push offset ntdll_w2k3_32!`string'+0x12c (7c8340b0)2684 7c833f6d e8a942ffff call ntdll_w2k3_32!_SEH_prolog (7c82821b)2685 7c833f72 a13077887c mov eax,dword ptr [ntdll_w2k3_32!__security_cookie (7c887730)]2686 7c833f77 8945e4 mov dword ptr [ebp-1Ch],eax2687 7c833f7a 8b4508 mov eax,dword ptr [ebp+8]2688 7c833f7d 8985b0fdffff mov dword ptr [ebp-250h],eax2689 7c833f83 8b450c mov eax,dword ptr [ebp+0Ch]2690 2691 Windows Vista SP0 & SP1:2692 0:000:x86> u ntdll_vista_sp0_32!LdrLoadDll2693 ntdll_vista_sp0_32!LdrLoadDll:2694 69b0eb00 6844020000 push 244h2695 69b0eb05 6838e9b269 push offset ntdll_vista_sp0_32! ?? ::FNODOBFM::`string'+0x39e (69b2e938)2696 69b0eb0a e835420300 call ntdll_vista_sp0_32!_SEH_prolog4_GS (69b42d44)2697 69b0eb0f 8b4508 mov eax,dword ptr [ebp+8]2698 69b0eb12 8985acfdffff mov dword ptr [ebp-254h],eax2699 69b0eb18 8b450c mov eax,dword ptr [ebp+0Ch]2700 69b0eb1b 8985c0fdffff mov dword ptr [ebp-240h],eax2701 69b0eb21 8b4510 mov eax,dword ptr [ebp+10h]2702 */2703 2704 if ( pbLdrLoadDll[0] == 0x8b /* mov edi, edi - for hot patching */2705 && pbLdrLoadDll[1] == 0xff2706 && pbLdrLoadDll[2] == 0x55 /* push ebp */2707 && pbLdrLoadDll[3] == 0x8b /* mov ebp,esp */2708 && pbLdrLoadDll[4] == 0xec)2709 {2710 offJmpBack = 5; /* the 3rd instruction. */2711 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;2712 }2713 else if (pbLdrLoadDll[0] == 0x68 /* push dword XXXXXXXX */)2714 {2715 offJmpBack = 5;2716 pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;2717 g_supR3HardenedJmpBack_LdrLoadDll_Type2_PushDword = *(uint32_t const *)&pbLdrLoadDll[1];2718 }2719 else2720 supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);2721 2722 g_pfnLdrLoadDllJmpBack = (PFNRT)(uintptr_t)(pbLdrLoadDll + offJmpBack);2723 *(PFNRT *)&g_pfnLdrLoadDllReal = pfnCallReal;2724 2725 # else2726 2736 /* Just use the disassembler to skip 6 bytes or more. */ 2727 2737 DISSTATE Dis; … … 2749 2759 offExecPage = RT_ALIGN_32(offJmpBack + 4, 16); 2750 2760 2751 # endif 2752 2753 /* Patch LdrLoadDLl. */ 2754 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE)); 2761 /* Assemble the LdrLoadDll patch. */ 2762 memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch)); 2755 2763 Assert(offJmpBack >= 5); 2756 pbLdrLoadDll[0] = 0xe9; 2757 *(uint32_t *)&pbLdrLoadDll[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4]; 2758 2759 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READ)); 2764 g_abLdrLoadDllPatch[0] = 0xe9; 2765 *(uint32_t *)&g_abLdrLoadDllPatch[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4]; 2760 2766 #endif 2761 2767 … … 2764 2770 */ 2765 2771 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(g_abSupHardReadWriteExecPage, PAGE_SIZE, PAGE_EXECUTE_READ)); 2772 2773 /* 2774 * Install the patches. 2775 */ 2776 supR3HardenedWinReInstallHooks(true /*fFirstCall*/); 2766 2777 } 2767 2778 … … 4143 4154 /* 4144 4155 * Apply anti debugger notification trick to the thread. (Also done in 4145 * supR3HardenedWinIn stallHooks.)4156 * supR3HardenedWinInit.) 4146 4157 */ 4147 4158 rcNt = NtSetInformationThread(hThread, ThreadHideFromDebugger, NULL, 0); … … 4661 4672 4662 4673 /** 4663 * Initializes the windows verficiation bits. 4674 * Initializes the windows verficiation bits and other things we're better off 4675 * doing after main() has passed on it's data. 4676 * 4664 4677 * @param fFlags The main flags. 4665 4678 * @param fAvastKludge Whether to apply the avast kludge. … … 4667 4680 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge) 4668 4681 { 4682 #ifndef VBOX_WITHOUT_DEBUGGER_CHECKS 4683 /* 4684 * Install a anti debugging hack before we continue. This prevents most 4685 * notifications from ending up in the debugger. (Also applied to the 4686 * child process when respawning.) 4687 */ 4688 rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0); 4689 if (!NT_SUCCESS(rcNt)) 4690 supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, VERR_GENERAL_FAILURE, 4691 "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt); 4692 #endif 4693 4669 4694 /* 4670 4695 * Init the verifier. … … 5474 5499 5475 5500 /* 5501 * If we've done early init already, register the DLL load notification 5502 * callback and reinstall the NtDll patches. 5503 */ 5504 if (g_fSupEarlyProcessInit) 5505 { 5506 supR3HardenedWinRegisterDllNotificationCallback(); 5507 supR3HardenedWinReInstallHooks(false /*fFirstCall */); 5508 } 5509 5510 /* 5476 5511 * Call the C/C++ main function. 5477 5512 */ … … 5616 5651 5617 5652 /* 5653 * Reinstall the NtDll patches since there is a slight possibility that 5654 * someone undid them while we where busy opening the device. 5655 */ 5656 supR3HardenedWinReInstallHooks(false /*fFirstCall */); 5657 5658 /* 5618 5659 * Restore the LdrInitializeThunk code so we can initialize the process 5619 5660 * normally when we return. -
trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
r52949 r52953 56 56 SUPHARNT_IMPORT_SYSCALL(NtWriteVirtualMemory, 20) 57 57 SUPHARNT_IMPORT_SYSCALL(NtYieldExecution, 0) 58 59 SUPHARNT_IMPORT_STDCALL_EARLY(NtCreateSection, 28) 60 SUPHARNT_IMPORT_STDCALL_EARLY(NtQueryVolumeInformationFile, 20) 58 SUPHARNT_IMPORT_SYSCALL(NtCreateSection, 28) 59 SUPHARNT_IMPORT_SYSCALL(NtQueryVolumeInformationFile, 20) 61 60 62 61 SUPHARNT_IMPORT_STDCALL_EARLY(LdrInitializeThunk, 12) 62 SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(LdrRegisterDllNotification, 16) 63 63 64 64 SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16)
Note:
See TracChangeset
for help on using the changeset viewer.