Changeset 52375 in vbox for trunk/src/VBox/HostDrivers/Support/win
- Timestamp:
- Aug 14, 2014 1:25:12 AM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support/win
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r52373 r52375 43 43 DECLHIDDEN(int) supHardenedWinInitImageVerifier(PRTERRINFO pErrInfo); 44 44 DECLHIDDEN(void) supHardenedWinTermImageVerifier(void); 45 DECLHIDDEN(void) supR3HardenedWinVerifyCachePreload(PCRTUTF16 pwszName); 45 46 46 47 typedef enum SUPHARDNTVPKIND … … 58 59 PCRTUTF16 pwszRight, uint32_t cwcRight, bool fCheckSlash); 59 60 DECLHIDDEN(bool) supHardViIsAppPatchDir(PCRTUTF16 pwszPath, uint32_t cwcName); 61 60 62 61 63 /** -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
r52366 r52375 954 954 955 955 /** 956 * Checks if it's safe to call WinVerifyTrust or whether we might end up in an957 * infinite recursion.958 *959 * @returns true if ok, false if not.960 * @param hFile The file name.961 * @param pwszName The executable name.962 */963 static bool supR3HardNtViCanCallWinVerifyTrust(HANDLE hFile, PCRTUTF16 pwszName)964 {965 /*966 * Recursion preventions hacks:967 * - Don't try call WinVerifyTrust on Wintrust.dll when called from the968 * create section hook. CRYPT32.DLL tries to load WinTrust.DLL in some cases.969 */970 size_t cwcName = RTUtf16Len(pwszName);971 if ( hFile != NULL972 && cwcName > g_System32NtPath.UniStr.Length / sizeof(WCHAR)973 && !memcmp(pwszName, g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length)974 && supHardViUtf16PathIsEqual(&pwszName[g_System32NtPath.UniStr.Length / sizeof(WCHAR)], "\\wintrust.dll"))975 return false;976 977 return true;978 }979 980 981 /**982 956 * Verifies the given loader image. 983 957 * … … 1079 1053 static uint32_t volatile s_idActiveThread = UINT32_MAX; 1080 1054 uint32_t const idCurrentThread = GetCurrentThreadId(); 1081 if ( s_idActiveThread != idCurrentThread 1082 && supR3HardNtViCanCallWinVerifyTrust(pNtViRdr->hFile, pwszName) ) 1055 if (s_idActiveThread != idCurrentThread) 1083 1056 { 1084 1057 ASMAtomicCmpXchgU32(&s_idActiveThread, idCurrentThread, UINT32_MAX); … … 1104 1077 } 1105 1078 else if (RT_SUCCESS(rc)) 1079 { 1080 /** @todo having trouble with a 32-bit windows box when letting these calls thru */ 1106 1081 rc = supR3HardNtViCallWinVerifyTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, pErrInfo, 1107 1082 g_pfnWinVerifyTrust); 1083 } 1108 1084 else 1109 1085 { … … 1174 1150 supHardNtViRdrDestroy(&pNtViRdr->Core); 1175 1151 } 1176 SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d (%ls)\n", rc, pwszName));1152 SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d %s(%ls)\n", rc, pfCacheable && *pfCacheable ? "cacheable ": "", pwszName)); 1177 1153 return rc; 1178 1154 } … … 1769 1745 } 1770 1746 1747 1748 /** 1749 * Loads a module in the system32 directory. 1750 * 1751 * @returns Module handle on success. Won't return on faliure. 1752 * @param pszName The name of the DLL to load. 1753 */ 1754 DECLHIDDEN(HMODULE) supR3HardenedWinLoadSystem32Dll(const char *pszName) 1755 { 1756 WCHAR wszName[200+60]; 1757 UINT cwcDir = GetSystemWindowsDirectoryW(wszName, RT_ELEMENTS(wszName) - 60); 1758 memcpy(&wszName[cwcDir], RT_STR_TUPLE(L"\\System32\\")); 1759 RTUtf16CopyAscii(&wszName[cwcDir + sizeof("\\System32\\") - 1], RT_ELEMENTS(wszName) - cwcDir, pszName); 1760 1761 DWORD fFlags = 0; 1762 if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) 1763 fFlags = LOAD_LIBRARY_SEARCH_SYSTEM32; 1764 HMODULE hMod = LoadLibraryExW(wszName, NULL, fFlags); 1765 if ( hMod == NULL 1766 && fFlags 1767 && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 2) 1768 && GetLastError() == ERROR_INVALID_PARAMETER) 1769 { 1770 fFlags = 0; 1771 hMod = LoadLibraryExW(wszName, NULL, fFlags); 1772 } 1773 if (hMod == NULL) 1774 supR3HardenedFatal("Error loading '%s': %u [%ls]", pszName, GetLastError(), wszName); 1775 return hMod; 1776 } 1777 1778 1771 1779 /** 1772 1780 * Called by supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation to … … 1774 1782 * 1775 1783 * These certificates permits us to correctly validate third party DLLs. 1776 * 1777 * @param fLoadLibraryFlags The LoadLibraryExW flags that the caller 1778 * found to work. Avoids us having to retry on 1779 * ERROR_INVALID_PARAMETER. 1780 */ 1781 static void supR3HardenedWinRetrieveTrustedRootCAs(DWORD fLoadLibraryFlags) 1784 */ 1785 static void supR3HardenedWinRetrieveTrustedRootCAs(void) 1782 1786 { 1783 1787 uint32_t cAdded = 0; … … 1786 1790 * Load crypt32.dll and resolve the APIs we need. 1787 1791 */ 1788 HMODULE hCrypt32 = LoadLibraryExW(L"\\\\.\\GLOBALROOT\\SystemRoot\\System32\\crypt32.dll", NULL, fLoadLibraryFlags); 1789 if (!hCrypt32) 1790 supR3HardenedFatal("Error loading 'crypt32.dll': %u", GetLastError()); 1792 HMODULE hCrypt32 = supR3HardenedWinLoadSystem32Dll("crypt32.dll"); 1791 1793 1792 1794 #define RESOLVE_CRYPT32_API(a_Name, a_pfnType) \ … … 1885 1887 * Resolve it. 1886 1888 */ 1887 DWORD fFlags = 0; 1888 if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) 1889 fFlags = LOAD_LIBRARY_SEARCH_SYSTEM32; 1890 HMODULE hWintrust = LoadLibraryExW(L"\\\\.\\GLOBALROOT\\SystemRoot\\System32\\Wintrust.dll", NULL, fFlags); 1891 if ( hWintrust == NULL 1892 && fFlags 1893 && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 2) 1894 && GetLastError() == ERROR_INVALID_PARAMETER) 1895 { 1896 fFlags = 0; 1897 hWintrust = LoadLibraryExW(L"\\\\.\\GLOBALROOT\\SystemRoot\\System32\\Wintrust.dll", NULL, fFlags); 1898 } 1899 if (hWintrust == NULL) 1900 supR3HardenedFatal("Error loading 'Wintrust.dll': %u", GetLastError()); 1901 1889 HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll"); 1902 1890 #define RESOLVE_CRYPT_API(a_Name, a_pfnType, a_uMinWinVer) \ 1903 1891 do { \ … … 1943 1931 SUP_DPRINTF(("g_pfnWinVerifyTrust=%p\n", pfnWinVerifyTrust)); 1944 1932 1933 # ifdef IN_SUP_HARDENED_R3 1934 /* 1935 * Load some problematic DLLs into the verifier cache to prevent 1936 * recursion trouble. 1937 */ 1938 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\crypt32.dll"); 1939 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\Wintrust.dll"); 1940 # endif 1941 1945 1942 /* 1946 1943 * Now, get trusted root CAs so we can verify a broader scope of signatures. 1947 1944 */ 1948 supR3HardenedWinRetrieveTrustedRootCAs(fFlags); 1945 supR3HardenedWinRetrieveTrustedRootCAs(); 1946 1947 # ifdef IN_SUP_HARDENED_R3 1948 /* 1949 * Do some verify cache preloading. The MS Visual C++ CRT DLLs works 1950 * around recursion issues with WinVerifyTrust on 32-bit windows 7. 1951 */ 1952 SUP_DPRINTF(("preloading part 2...\n")); 1953 # if 0 /* Seeing if this helps with the later Win7/32 issue... apparently not :-/ */ 1954 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\cfgmgr32.dll"); 1955 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\devobj.dll"); 1956 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\setupapi.dll"); 1957 supR3HardenedWinLoadSystem32Dll("setupapi.dll"); 1958 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\rsaenh.dll"); 1959 supR3HardenedWinLoadSystem32Dll("rsaenh.dll"); 1960 # endif 1961 1962 WCHAR wszPath[260+16]; 1963 supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\apphelp.dll"); 1964 memcpy(wszPath, g_SupLibHardenedExeNtPath.UniStr.Buffer, g_SupLibHardenedExeNtPath.UniStr.Length); 1965 static char const *s_apszAppDlls[] = 1966 { 1967 NULL, 1968 "VBoxRT.dll", 1969 # if _MSC_VER < 1600 1970 "msvcr90.dll", "msvcp90.dll", 1971 # elif _MSC_VER < 1700 1972 "msvcr100.dll", "msvcp100.dll", 1973 # elif _MSC_VER < 1800 1974 "msvcr110.dll", "msvcp110.dll", 1975 # elif _MSC_VER < 1900 1976 "msvcr120.dll", "msvcp120.dll", 1977 # elif _MSC_VER < 1900 1978 "msvcr130.dll", "msvcp130.dll", 1979 # else 1980 # error "Unsupported compiler version." 1981 # endif 1982 }; 1983 s_apszAppDlls[0] = pszProgName; 1984 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszAppDlls); i++) 1985 { 1986 RTUtf16CopyAscii(&wszPath[g_offSupLibHardenedExeNtName], 300 - g_offSupLibHardenedExeNtName, s_apszAppDlls[i]); 1987 supR3HardenedWinVerifyCachePreload(wszPath); 1988 } 1989 SUP_DPRINTF(("preloading part 2 - done.\n")); 1990 # endif 1949 1991 } 1950 1992 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52373 r52375 381 381 * here instead of being handled by the caller to 382 382 * save code duplication. 383 */ 384 static void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc, bool fCacheable) 383 * @param fForceCacheable Overrides the main state and @a fCacheable. 384 */ 385 static void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc, bool fCacheable, 386 bool fForceCacheable) 385 387 { 386 388 /* 387 389 * Don't cache anything until we've got the WinVerifyTrust API up and running. 388 390 */ 389 if ( g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY 390 && fCacheable) 391 if ( ( g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY 392 && fCacheable) 393 || fForceCacheable) 391 394 { 392 395 /* … … 414 417 { 415 418 if (ASMAtomicCmpXchgPtr(ppEntry, pEntry, NULL)) 419 { 420 SUP_DPRINTF(("supR3HardenedWinVerifyCacheInsert: %ls\n", pUniStr->Buffer)); 416 421 return; 422 } 423 417 424 PVERIFIERCACHEENTRY pOther = *ppEntry; 418 425 if (!pOther) … … 618 625 619 626 627 static NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect, bool *pfCallRealApi, 628 bool fForceCacheable) 629 { 630 *pfCallRealApi = false; 631 632 /* 633 * Query the name of the file, making sure to zero terminator the 634 * string. (2nd half of buffer is used for error info, see below.) 635 */ 636 union 637 { 638 UNICODE_STRING UniStr; 639 uint8_t abBuffer[sizeof(UNICODE_STRING) + 2048 * sizeof(WCHAR)]; 640 } uBuf; 641 RT_ZERO(uBuf); 642 ULONG cbNameBuf; 643 NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR) - 128, &cbNameBuf); 644 if (!NT_SUCCESS(rcNt)) 645 { 646 supR3HardenedError(VINF_SUCCESS, false, "NtCreateSection: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n", 647 fImage, *pfProtect, *pfAccess); 648 return rcNt; 649 } 650 651 if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer)) 652 { 653 uBuf.UniStr.MaximumLength = sizeof(uBuf) - 128; 654 supR3HardenedWinFix8dot3Path(hFile, &uBuf.UniStr); 655 } 656 657 /* 658 * Check the cache. 659 */ 660 PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile); 661 if (pCacheHit) 662 { 663 SUP_DPRINTF(("NtCreateSection: cache hit (%Rrc) on %ls\n", pCacheHit->rc, pCacheHit->wszPath)); 664 if (RT_SUCCESS(pCacheHit->rc)) 665 { 666 *pfCallRealApi = true; 667 return STATUS_SUCCESS; 668 } 669 supR3HardenedError(VINF_SUCCESS, false, "NtCreateSection: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls\n", 670 pCacheHit->rc, fImage, *pfProtect, *pfAccess, uBuf.UniStr.Buffer); 671 return STATUS_TRUST_FAILURE; 672 } 673 674 /* 675 * On XP the loader might hand us handles with just FILE_EXECUTE and 676 * SYNCHRONIZE, the means reading will fail later on. Also, we need 677 * READ_CONTROL access to check the file ownership later on, and non 678 * of the OS versions seems be giving us that. So, in effect we 679 * more or less always reopen the file here. 680 */ 681 HANDLE hMyFile = NULL; 682 rcNt = NtDuplicateObject(NtCurrentProcess(), hFile, NtCurrentProcess(), 683 &hMyFile, 684 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE, 685 0 /* Handle attributes*/, 0 /* Options */); 686 if (!NT_SUCCESS(rcNt)) 687 { 688 if (rcNt == STATUS_ACCESS_DENIED) 689 { 690 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 691 OBJECT_ATTRIBUTES ObjAttr; 692 InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 693 694 rcNt = NtCreateFile(&hMyFile, 695 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE, 696 &ObjAttr, 697 &Ios, 698 NULL /* Allocation Size*/, 699 FILE_ATTRIBUTE_NORMAL, 700 FILE_SHARE_READ, 701 FILE_OPEN, 702 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 703 NULL /*EaBuffer*/, 704 0 /*EaLength*/); 705 if (NT_SUCCESS(rcNt)) 706 rcNt = Ios.Status; 707 if (!NT_SUCCESS(rcNt)) 708 { 709 supR3HardenedError(VINF_SUCCESS, false, 710 "NtCreateSection: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n", 711 rcNt, hFile, uBuf.UniStr.Buffer); 712 return rcNt; 713 } 714 715 /* Check that we've got the same file. */ 716 LARGE_INTEGER idMyFile, idInFile; 717 bool fMyValid = supR3HardenedWinVerifyCacheGetIndexNumber(hMyFile, &idMyFile); 718 bool fInValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &idInFile); 719 if ( fMyValid 720 && ( fMyValid != fInValid 721 || idMyFile.QuadPart != idInFile.QuadPart)) 722 { 723 supR3HardenedError(VINF_SUCCESS, false, 724 "NtCreateSection: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n", 725 rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer); 726 NtClose(hMyFile); 727 return STATUS_TRUST_FAILURE; 728 } 729 } 730 else 731 { 732 SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtDuplicateObject -> %#x\n", rcNt)); 733 #ifdef DEBUG 734 735 supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_NtCreateSection: NtDuplicateObject(,%#x,) failed: %#x\n", hFile, rcNt); 736 #endif 737 hMyFile = hFile; 738 } 739 } 740 741 /* 742 * Special Kludge for Windows XP and W2K3 and their stupid attempts 743 * at mapping a hidden XML file called c:\Windows\WindowsShell.Manifest 744 * with executable access. The image bit isn't set, fortunately. 745 */ 746 if ( !fImage 747 && uBuf.UniStr.Length > g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR) 748 && memcmp(uBuf.UniStr.Buffer, g_System32NtPath.UniStr.Buffer, 749 g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) == 0) 750 { 751 PRTUTF16 pwszName = &uBuf.UniStr.Buffer[(g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) / sizeof(WCHAR)]; 752 if (RTUtf16ICmpAscii(pwszName, "WindowsShell.Manifest") == 0) 753 { 754 /* 755 * Drop all executable access to the mapping and let it continue. 756 */ 757 SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: Applying the drop-exec-kludge for '%ls'\n", uBuf.UniStr.Buffer)); 758 if (*pfAccess & SECTION_MAP_EXECUTE) 759 *pfAccess = (*pfAccess & ~SECTION_MAP_EXECUTE) | SECTION_MAP_READ; 760 if (*pfProtect & PAGE_EXECUTE) 761 *pfProtect = (*pfProtect & ~PAGE_EXECUTE) | PAGE_READONLY; 762 *pfProtect = (*pfProtect & ~UINT32_C(0xf0)) | ((*pfProtect & UINT32_C(0xe0)) >> 4); 763 if (hMyFile != hFile) 764 NtClose(hMyFile); 765 *pfCallRealApi = true; 766 return STATUS_SUCCESS; 767 } 768 } 769 770 /* 771 * Check the path. We don't allow DLLs to be loaded from just anywhere: 772 * 1. System32 - normal code or cat signing, owner TrustedInstaller. 773 * 2. WinSxS - normal code or cat signing, owner TrustedInstaller. 774 * 3. VirtualBox - kernel code signing and integrity checks. 775 * 4. AppPatchDir - normal code or cat signing, owner TrustedInstaller. 776 * 5. Program Files - normal code or cat signing, owner TrustedInstaller. 777 * 6. Common Files - normal code or cat signing, owner TrustedInstaller. 778 * 7. x86 variations of 4 & 5 - ditto. 779 */ 780 bool fSystem32 = false; 781 Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\'); 782 uint32_t fFlags = 0; 783 if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_System32NtPath.UniStr, true /*fCheckSlash*/)) 784 { 785 fSystem32 = true; 786 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 787 } 788 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_WinSxSNtPath.UniStr, true /*fCheckSlash*/)) 789 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 790 else if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR), 791 g_SupLibHardenedExeNtPath.UniStr.Buffer, 792 g_offSupLibHardenedExeNtName, false /*fCheckSlash*/)) 793 fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT; 794 #ifdef VBOX_PERMIT_MORE 795 else if (supHardViIsAppPatchDir(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR))) 796 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 797 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesNtPath.UniStr, true /*fCheckSlash*/)) 798 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 799 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesNtPath.UniStr, true /*fCheckSlash*/)) 800 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 801 # ifdef RT_ARCH_AMD64 802 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesX86NtPath.UniStr, true /*fCheckSlash*/)) 803 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 804 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesX86NtPath.UniStr, true /*fCheckSlash*/)) 805 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER; 806 # endif 807 #endif 808 #ifdef VBOX_PERMIT_VISUAL_STUDIO_PROFILING 809 /* Hack to allow profiling our code with Visual Studio. */ 810 else if ( uBuf.UniStr.Length > sizeof(L"\\SamplingRuntime.dll") 811 && memcmp(uBuf.UniStr.Buffer + (uBuf.UniStr.Length - sizeof(L"\\SamplingRuntime.dll") + sizeof(WCHAR)) / sizeof(WCHAR), 812 L"\\SamplingRuntime.dll", sizeof(L"\\SamplingRuntime.dll") - sizeof(WCHAR)) == 0 ) 813 { 814 if (hMyFile != hFile) 815 NtClose(hMyFile); 816 *pfCallRealApi = true; 817 return STATUS_SUCCESS; 818 } 819 #endif 820 else 821 { 822 supR3HardenedError(VINF_SUCCESS, false, 823 "supR3HardenedMonitor_NtCreateSection: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)", 824 uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect); 825 if (hMyFile != hFile) 826 NtClose(hMyFile); 827 return STATUS_TRUST_FAILURE; 828 } 829 830 /* 831 * Do the verification. For better error message we borrow what's 832 * left of the path buffer for an RTERRINFO buffer. 833 */ 834 RTERRINFO ErrInfo; 835 RTErrInfoInit(&ErrInfo, (char *)&uBuf.abBuffer[cbNameBuf], sizeof(uBuf) - cbNameBuf); 836 837 bool fCacheable = true; 838 int rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, &fCacheable, &ErrInfo); 839 if (RT_FAILURE(rc)) 840 { 841 supR3HardenedError(VINF_SUCCESS, false, 842 "supR3HardenedMonitor_NtCreateSection: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n", 843 rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg); 844 if (hMyFile != hFile) 845 NtClose(hMyFile); 846 return STATUS_TRUST_FAILURE; 847 } 848 if (hMyFile != hFile) 849 supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fCacheable, fForceCacheable); 850 851 *pfCallRealApi = true; 852 return STATUS_SUCCESS; 853 } 854 855 856 /** 857 * Preloads a file into the verify cache if possible. 858 * 859 * This is used to avoid known cyclic LoadLibrary issues with WinVerifyTrust. 860 * 861 * @param pwszName The name of the DLL to verify. 862 */ 863 DECLHIDDEN(void) supR3HardenedWinVerifyCachePreload(PCRTUTF16 pwszName) 864 { 865 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; 866 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 867 868 UNICODE_STRING UniStr; 869 UniStr.Buffer = (PWCHAR)pwszName; 870 UniStr.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR)); 871 UniStr.MaximumLength = UniStr.Length + sizeof(WCHAR); 872 873 OBJECT_ATTRIBUTES ObjAttr; 874 InitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 875 876 NTSTATUS rcNt = NtCreateFile(&hFile, 877 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE, 878 &ObjAttr, 879 &Ios, 880 NULL /* Allocation Size*/, 881 FILE_ATTRIBUTE_NORMAL, 882 FILE_SHARE_READ, 883 FILE_OPEN, 884 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 885 NULL /*EaBuffer*/, 886 0 /*EaLength*/); 887 if (NT_SUCCESS(rcNt)) 888 rcNt = Ios.Status; 889 if (!NT_SUCCESS(rcNt)) 890 { 891 SUP_DPRINTF(("supR3HardenedWinPreScreenImage: Error %#x opening '%ls'.\n", rcNt, pwszName)); 892 return; 893 } 894 895 ULONG fAccess = 0; 896 ULONG fProtect = 0; 897 bool fCallRealApi; 898 //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: scanning %ls\n", pwszName)); 899 supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, true /* fForceCacheable */); 900 //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: done %ls\n", pwszName)); 901 902 NtClose(hFile); 903 } 904 905 906 620 907 /** 621 908 * Hook that monitors NtCreateSection calls. … … 643 930 if (fImage || fExecMap || fExecProt) 644 931 { 645 /* 646 * Query the name of the file, making sure to zero terminator the 647 * string. (2nd half of buffer is used for error info, see below.) 648 */ 649 union 650 { 651 UNICODE_STRING UniStr; 652 uint8_t abBuffer[sizeof(UNICODE_STRING) + 2048 * sizeof(WCHAR)]; 653 } uBuf; 654 RT_ZERO(uBuf); 655 ULONG cbNameBuf; 656 NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR) - 128, &cbNameBuf); 932 bool fCallRealApi; 933 //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 1\n")); 934 NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi, false /*fForceCacheable*/); 935 //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 2 rcNt=%#x fCallRealApi=%#x\n", rcNt, fCallRealApi)); 657 936 if (!NT_SUCCESS(rcNt)) 658 {659 supR3HardenedError(VINF_SUCCESS, false,660 "NtCreateSection: NtQueryObject -> %#x (fImage=%d fExecMap=%d fExecProt=%d)\n",661 fImage, fExecMap, fExecProt);662 937 return rcNt; 663 } 664 665 if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer)) 666 { 667 uBuf.UniStr.MaximumLength = sizeof(uBuf) - 128; 668 supR3HardenedWinFix8dot3Path(hFile, &uBuf.UniStr); 669 } 670 671 /* 672 * Check the cache. 673 */ 674 PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile); 675 if (pCacheHit) 676 { 677 SUP_DPRINTF(("NtCreateSection: cache hit (%Rrc) on %ls\n", pCacheHit->rc, pCacheHit->wszPath)); 678 if (RT_SUCCESS(pCacheHit->rc)) 679 return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile); 680 supR3HardenedError(VINF_SUCCESS, false, 681 "NtCreateSection: cached rc=%Rrc fImage=%d fExecMap=%d fExecProt=%d %ls\n", 682 pCacheHit->rc, fImage, fExecMap, fExecProt, uBuf.UniStr.Buffer); 938 Assert(fCallRealApi); 939 if (!fCallRealApi) 683 940 return STATUS_TRUST_FAILURE; 684 }685 686 /*687 * On XP the loader might hand us handles with just FILE_EXECUTE and688 * SYNCHRONIZE, the means reading will fail later on. Also, we need689 * READ_CONTROL access to check the file ownership later on, and non690 * of the OS versions seems be giving us that. So, in effect we691 * more or less always reopen the file here.692 */693 HANDLE hMyFile = NULL;694 rcNt = NtDuplicateObject(NtCurrentProcess(), hFile, NtCurrentProcess(),695 &hMyFile,696 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,697 0 /* Handle attributes*/, 0 /* Options */);698 if (!NT_SUCCESS(rcNt))699 {700 if (rcNt == STATUS_ACCESS_DENIED)701 {702 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;703 OBJECT_ATTRIBUTES ObjAttr;704 InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);705 706 rcNt = NtCreateFile(&hMyFile,707 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,708 &ObjAttr,709 &Ios,710 NULL /* Allocation Size*/,711 FILE_ATTRIBUTE_NORMAL,712 FILE_SHARE_READ,713 FILE_OPEN,714 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,715 NULL /*EaBuffer*/,716 0 /*EaLength*/);717 if (NT_SUCCESS(rcNt))718 rcNt = Ios.Status;719 if (!NT_SUCCESS(rcNt))720 {721 supR3HardenedError(VINF_SUCCESS, false,722 "NtCreateSection: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",723 rcNt, hFile, uBuf.UniStr.Buffer);724 return rcNt;725 }726 727 /* Check that we've got the same file. */728 LARGE_INTEGER idMyFile, idInFile;729 bool fMyValid = supR3HardenedWinVerifyCacheGetIndexNumber(hMyFile, &idMyFile);730 bool fInValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &idInFile);731 if ( fMyValid732 && ( fMyValid != fInValid733 || idMyFile.QuadPart != idInFile.QuadPart))734 {735 supR3HardenedError(VINF_SUCCESS, false,736 "NtCreateSection: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",737 rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);738 NtClose(hMyFile);739 return STATUS_TRUST_FAILURE;740 }741 }742 else743 {744 SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtDuplicateObject -> %#x\n", rcNt));745 #ifdef DEBUG746 747 supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_NtCreateSection: NtDuplicateObject(,%#x,) failed: %#x\n", hFile, rcNt);748 #endif749 hMyFile = hFile;750 }751 }752 753 /*754 * Special Kludge for Windows XP and W2K3 and their stupid attempts755 * at mapping a hidden XML file called c:\Windows\WindowsShell.Manifest756 * with executable access. The image bit isn't set, fortunately.757 */758 if ( !fImage759 && uBuf.UniStr.Length > g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)760 && memcmp(uBuf.UniStr.Buffer, g_System32NtPath.UniStr.Buffer,761 g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) == 0)762 {763 PRTUTF16 pwszName = &uBuf.UniStr.Buffer[(g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) / sizeof(WCHAR)];764 if (RTUtf16ICmpAscii(pwszName, "WindowsShell.Manifest") == 0)765 {766 /*767 * Drop all executable access to the mapping and let it continue.768 */769 SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: Applying the drop-exec-kludge for '%ls'\n", uBuf.UniStr.Buffer));770 if (fAccess & SECTION_MAP_EXECUTE)771 fAccess = (fAccess & ~SECTION_MAP_EXECUTE) | SECTION_MAP_READ;772 if (fProtect & PAGE_EXECUTE)773 fProtect = (fProtect & ~PAGE_EXECUTE) | PAGE_READONLY;774 fProtect = (fProtect & ~UINT32_C(0xf0)) | ((fProtect & UINT32_C(0xe0)) >> 4);775 if (hMyFile != hFile)776 NtClose(hMyFile);777 return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);778 }779 }780 781 /*782 * Check the path. We don't allow DLLs to be loaded from just anywhere:783 * 1. System32 - normal code or cat signing, owner TrustedInstaller.784 * 2. WinSxS - normal code or cat signing, owner TrustedInstaller.785 * 3. VirtualBox - kernel code signing and integrity checks.786 * 4. AppPatchDir - normal code or cat signing, owner TrustedInstaller.787 * 5. Program Files - normal code or cat signing, owner TrustedInstaller.788 * 6. Common Files - normal code or cat signing, owner TrustedInstaller.789 * 7. x86 variations of 4 & 5 - ditto.790 */791 bool fSystem32 = false;792 Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');793 uint32_t fFlags = 0;794 if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_System32NtPath.UniStr, true /*fCheckSlash*/))795 {796 fSystem32 = true;797 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;798 }799 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_WinSxSNtPath.UniStr, true /*fCheckSlash*/))800 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;801 else if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),802 g_SupLibHardenedExeNtPath.UniStr.Buffer,803 g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))804 fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;805 #ifdef VBOX_PERMIT_MORE806 else if (supHardViIsAppPatchDir(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR)))807 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;808 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesNtPath.UniStr, true /*fCheckSlash*/))809 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;810 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesNtPath.UniStr, true /*fCheckSlash*/))811 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;812 # ifdef RT_ARCH_AMD64813 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesX86NtPath.UniStr, true /*fCheckSlash*/))814 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;815 else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesX86NtPath.UniStr, true /*fCheckSlash*/))816 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;817 # endif818 #endif819 #ifdef VBOX_PERMIT_VISUAL_STUDIO_PROFILING820 /* Hack to allow profiling our code with Visual Studio. */821 else if ( uBuf.UniStr.Length > sizeof(L"\\SamplingRuntime.dll")822 && memcmp(uBuf.UniStr.Buffer + (uBuf.UniStr.Length - sizeof(L"\\SamplingRuntime.dll") + sizeof(WCHAR)) / sizeof(WCHAR),823 L"\\SamplingRuntime.dll", sizeof(L"\\SamplingRuntime.dll") - sizeof(WCHAR)) == 0 )824 {825 if (hMyFile != hFile)826 NtClose(hMyFile);827 return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);828 }829 #endif830 else831 {832 supR3HardenedError(VINF_SUCCESS, false,833 "supR3HardenedMonitor_NtCreateSection: Not a trusted location: '%ls' (fImage=%d fExecMap=%d fExecProt=%d)",834 uBuf.UniStr.Buffer, fImage, fExecMap, fExecProt);835 if (hMyFile != hFile)836 NtClose(hMyFile);837 return STATUS_TRUST_FAILURE;838 }839 840 /*841 * Do the verification. For better error message we borrow what's842 * left of the path buffer for an RTERRINFO buffer.843 */844 RTERRINFO ErrInfo;845 RTErrInfoInit(&ErrInfo, (char *)&uBuf.abBuffer[cbNameBuf], sizeof(uBuf) - cbNameBuf);846 847 bool fCacheable = true;848 int rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, &fCacheable, &ErrInfo);849 if (RT_FAILURE(rc))850 {851 supR3HardenedError(VINF_SUCCESS, false,852 "supR3HardenedMonitor_NtCreateSection: rc=%Rrc fImage=%d fExecMap=%d fExecProt=%d %ls: %s\n",853 rc, fImage, fExecMap, fExecProt, uBuf.UniStr.Buffer, ErrInfo.pszMsg);854 if (hMyFile != hFile)855 NtClose(hMyFile);856 return STATUS_TRUST_FAILURE;857 }858 if (hMyFile != hFile)859 supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fCacheable);860 941 } 861 942 } -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
r52374 r52375 597 597 "%ls: supHardNtLdrCacheOpen failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc); 598 598 } 599 600 #if 0 /* Win7/32 ntdll!LdrpDebugFlags. */ 601 *(uint8_t *)&g_aSupNtImpDlls[0].pbImageBase[0xdd770] = 0x3; 602 #endif 599 603 } 600 604
Note:
See TracChangeset
for help on using the changeset viewer.