Changeset 54997 in vbox for trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
- Timestamp:
- Mar 28, 2015 12:19:24 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
r53820 r54997 98 98 typedef BOOL (WINAPI *PFNCERTCLOSESTORE)(HCERTSTORE hCertStore, DWORD dwFlags); 99 99 typedef PCCERT_CONTEXT (WINAPI *PFNCERTENUMCERTIFICATESINSTORE)(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext); 100 101 typedef NTSTATUS (WINAPI *PFNBCRYPTOPENALGORTIHMPROVIDER)(BCRYPT_ALG_HANDLE *phAlgo, PCWSTR pwszAlgoId, 102 PCWSTR pwszImpl, DWORD dwFlags); 100 103 #endif 101 104 … … 2051 2054 2052 2055 /* 2053 * Resolve it.2056 * Resolve the imports we need. 2054 2057 */ 2055 2058 HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll"); … … 2075 2078 RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle2, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2, SUP_NT_VER_W80); 2076 2079 2077 /*2078 * Call it on ourselves and ntdll to make sure it loads all the providers2079 * now, we would otherwise geting into recursive trouble in the2080 * NtCreateSection hook.2081 */2082 2080 # ifdef IN_SUP_HARDENED_R3 2081 /* 2082 * Load bcrypt.dll and instantiate a few hashing and signing providers to 2083 * make sure the providers are cached for later us. Avoid recursion issues. 2084 */ 2085 HMODULE hBCrypt = supR3HardenedWinLoadSystem32Dll("bcrypt.dll"); 2086 if (hBCrypt) 2087 { 2088 PFNBCRYPTOPENALGORTIHMPROVIDER pfnOpenAlgoProvider; 2089 pfnOpenAlgoProvider = (PFNBCRYPTOPENALGORTIHMPROVIDER)GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider"); 2090 if (pfnOpenAlgoProvider) 2091 { 2092 SUP_DPRINTF(("bcrypt.dll loaded at %p, BCryptOpenAlgorithmProvider at %p, preloading providers:\n", 2093 hBCrypt, pfnOpenAlgoProvider)); 2094 # define PRELOAD_ALGO_PROVIDER(a_Name) \ 2095 do { \ 2096 BCRYPT_ALG_HANDLE hAlgo = NULL; \ 2097 NTSTATUS rcNt = pfnOpenAlgoProvider(&hAlgo, a_Name, NULL, 0); \ 2098 SUP_DPRINTF(("%sBCryptOpenAlgorithmProvider(,'%ls',0,0) -> %#x (hAlgo=%p)\n", \ 2099 NT_SUCCESS(rcNt) ? " " : "warning: ", a_Name, rcNt, hAlgo)); \ 2100 } while (0) 2101 PRELOAD_ALGO_PROVIDER(BCRYPT_MD2_ALGORITHM); 2102 PRELOAD_ALGO_PROVIDER(BCRYPT_MD4_ALGORITHM); 2103 PRELOAD_ALGO_PROVIDER(BCRYPT_MD5_ALGORITHM); 2104 PRELOAD_ALGO_PROVIDER(BCRYPT_SHA1_ALGORITHM); 2105 PRELOAD_ALGO_PROVIDER(BCRYPT_SHA256_ALGORITHM); 2106 PRELOAD_ALGO_PROVIDER(BCRYPT_SHA512_ALGORITHM); 2107 PRELOAD_ALGO_PROVIDER(BCRYPT_RSA_ALGORITHM); 2108 PRELOAD_ALGO_PROVIDER(BCRYPT_DSA_ALGORITHM); 2109 # undef PRELOAD_ALGO_PROVIDER 2110 } 2111 else 2112 SUP_DPRINTF(("Warning! Failed to find BCryptOpenAlgorithmProvider in bcrypt.dll\n")); 2113 } 2114 else 2115 SUP_DPRINTF(("Warning! Failed to load bcrypt.dll\n")); 2116 2117 /* 2118 * Call the verification API on ourselves and ntdll to make sure it works 2119 * and loads more stuff it needs, preventing any recursive fun we'd run 2120 * into after we set g_pfnWinVerifyTrust. 2121 */ 2083 2122 RTERRINFOSTATIC ErrInfoStatic; 2084 2123 RTErrInfoInitStatic(&ErrInfoStatic); … … 2582 2621 if (g_pfnWinVerifyTrust != NULL) 2583 2622 { 2584 /* Check for recursion. */ 2585 bool fNoRecursion; 2586 if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX) 2623 uint32_t const idCurrentThread = RTNtCurrentThreadId(); 2624 2625 /* Check if loader lock owner. */ 2626 struct _RTL_CRITICAL_SECTION volatile *pLoaderLock = NtCurrentPeb()->LoaderLock; 2627 bool fOwnsLoaderLock = pLoaderLock 2628 && pLoaderLock->OwningThread == (HANDLE)(uintptr_t)idCurrentThread 2629 && pLoaderLock->LockCount >= 0; 2630 if (!fOwnsLoaderLock) 2587 2631 { 2588 fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0; 2589 if (fNoRecursion) 2590 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1); 2591 } 2592 else 2593 { 2594 uint32_t const idCurrentThread = RTNtCurrentThreadId(); 2595 fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX); 2596 } 2597 if (fNoRecursion) 2598 { 2599 /* We can call WinVerifyTrust. */ 2600 if (pfWinVerifyTrust) 2601 *pfWinVerifyTrust = true; 2602 2603 if (rc != VERR_LDRVI_NOT_SIGNED) 2632 /* Check for recursion. */ 2633 bool fNoRecursion; 2634 if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX) 2604 2635 { 2605 if (rc == VINF_LDRVI_NOT_SIGNED) 2636 fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0; 2637 if (fNoRecursion) 2638 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1); 2639 } 2640 else 2641 fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX); 2642 2643 if (fNoRecursion && !fOwnsLoaderLock) 2644 { 2645 /* We can call WinVerifyTrust. */ 2646 if (pfWinVerifyTrust) 2647 *pfWinVerifyTrust = true; 2648 2649 if (rc != VERR_LDRVI_NOT_SIGNED) 2606 2650 { 2607 if ( fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)2651 if (rc == VINF_LDRVI_NOT_SIGNED) 2608 2652 { 2609 int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust); 2610 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc)); 2611 rc = rc2; 2653 if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION) 2654 { 2655 int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, 2656 g_pfnWinVerifyTrust); 2657 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc)); 2658 rc = rc2; 2659 } 2660 else 2661 { 2662 AssertFailed(); 2663 rc = VERR_LDRVI_NOT_SIGNED; 2664 } 2665 } 2666 else if (RT_SUCCESS(rc)) 2667 { 2668 HRESULT hrcWinVerifyTrust; 2669 rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, 2670 &hrcWinVerifyTrust); 2671 2672 /* DLLs signed with special roots, like "Microsoft Digital Media Authority 2005", 2673 may fail here because the root cert is not in the normal certificate stores 2674 (if any). Our verification code has the basics of these certificates included 2675 and can verify them, which is why we end up here instead of in the 2676 VINF_LDRVI_NOT_SIGNED case above. Current workaround is to do as above. 2677 (Intel graphics driver DLLs, like igdusc64.dll. */ 2678 if ( RT_FAILURE(rc) 2679 && hrcWinVerifyTrust == CERT_E_CHAINING 2680 && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)) 2681 { 2682 rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust); 2683 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc)); 2684 } 2612 2685 } 2613 2686 else 2614 2687 { 2615 AssertFailed(); 2616 rc = VERR_LDRVI_NOT_SIGNED; 2688 int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL); 2689 AssertMsg(RT_FAILURE_NP(rc2), 2690 ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>")); 2617 2691 } 2618 2692 } 2619 else if (RT_SUCCESS(rc)) 2620 { 2621 HRESULT hrcWinVerifyTrust; 2622 rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, 2623 &hrcWinVerifyTrust); 2624 2625 /* DLLs signed with special roots, like "Microsoft Digital Media Authority 2005", 2626 may fail here because the root cert is not in the normal certificate stores 2627 (if any). Our verification code has the basics of these certificates included 2628 and can verify them, which is why we end up here instead of in the 2629 VINF_LDRVI_NOT_SIGNED case above. Current workaround is to do as above. 2630 (Intel graphics driver DLLs, like igdusc64.dll. */ 2631 if ( RT_FAILURE(rc) 2632 && hrcWinVerifyTrust == CERT_E_CHAINING 2633 && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)) 2634 { 2635 rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust); 2636 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc)); 2637 } 2638 } 2693 2694 /* Unwind recursion. */ 2695 if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX) 2696 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0); 2639 2697 else 2640 { 2641 int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL); 2642 AssertMsg(RT_FAILURE_NP(rc2), 2643 ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>")); 2644 } 2698 ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX); 2645 2699 } 2646 2647 /* Unwind recursion. */ 2648 if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX) 2649 TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0); 2700 /* 2701 * No can do. 2702 */ 2650 2703 else 2651 ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX);2704 SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName)); 2652 2705 } 2653 2706 else 2654 SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));2707 SUP_DPRINTF(("Detected loader lock ownership: rc=%Rrc '%ls'.\n", rc, pwszName)); 2655 2708 } 2656 2709 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.