Changeset 52947 in vbox for trunk/src/VBox/HostDrivers/Support/win
- Timestamp:
- Oct 5, 2014 4:48:25 PM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support/win
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r52943 r52947 138 138 /** Set if verified. */ 139 139 bool fVerified; 140 /** Whether we've got valid cacheable image bit.s */ 141 bool fValidBits; 142 /** The image base address. */ 143 uintptr_t uImageBase; 140 144 } SUPHNTLDRCACHEENTRY; 141 145 /** Pointer to a loader cache entry. */ … … 143 147 DECLHIDDEN(int) supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry); 144 148 DECLHIDDEN(int) supHardNtLdrCacheEntryVerify(PSUPHNTLDRCACHEENTRY pEntry, PCRTUTF16 pwszName, PRTERRINFO pErrInfo); 145 DECLHIDDEN(int) supHardNtLdrCacheEntryAllocBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, PRTERRINFO pErrInfo); 149 DECLHIDDEN(int) supHardNtLdrCacheEntryGetBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, RTLDRADDR uBaseAddress, 150 PFNRTLDRIMPORT pfnGetImport, void *pvUser, PRTERRINFO pErrInfo); 146 151 147 152 -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r52940 r52947 810 810 */ 811 811 uint8_t *pbBits; 812 rc = supHardNtLdrCacheEntryAllocBits(pImage->pCacheEntry, &pbBits, pThis->pErrInfo); 812 if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION) 813 rc = supHardNtLdrCacheEntryGetBits(pImage->pCacheEntry, &pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis, 814 pThis->pErrInfo); 815 else 816 rc = supHardNtLdrCacheEntryGetBits(pImage->pCacheEntry, &pbBits, pImage->uImageBase, supHardNtVpGetImport, pThis, 817 pThis->pErrInfo); 813 818 if (RT_FAILURE(rc)) 814 819 return rc; 815 if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION)816 rc = RTLdrGetBits(pImage->pCacheEntry->hLdrMod, pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis);817 else818 rc = RTLdrGetBits(pImage->pCacheEntry->hLdrMod, pbBits, pImage->uImageBase, supHardNtVpGetImport, pThis);819 if (RT_FAILURE(rc))820 return supHardNtVpSetInfo2(pThis, rc, "%s: RTLdrGetBits failed: %Rrc", pImage->pszName, rc);821 820 822 821 /* XP SP3 does not set ImageBase to load address. It fixes up the image on load time though. */ … … 862 861 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrInitializeThunk': %Rrc", pImage->pszName, rc); 863 862 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 864 aSkipAreas[cSkipAreas++].cb = 1 0;863 aSkipAreas[cSkipAreas++].cb = 14; 865 864 } 866 865 … … 1586 1585 1587 1586 /** 1588 * Allocates a image bits buffer for use with RTLdrGetBits.1587 * Allocates a image bits buffer and calls RTLdrGetBits on them. 1589 1588 * 1590 1589 * An assumption here is that there won't ever be concurrent use of the cache. … … 1595 1594 * @param pEntry The loader cache entry. 1596 1595 * @param ppbBits Where to return the pointer to the allocation. 1597 * @param pErRInfo Where to return extened error information. 1598 */ 1599 DECLHIDDEN(int) supHardNtLdrCacheEntryAllocBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, PRTERRINFO pErrInfo) 1600 { 1596 * @param uBaseAddress The image base address, see RTLdrGetBits. 1597 * @param pfnGetImport Import getter, see RTLdrGetBits. 1598 * @param pvUser The user argument for @a pfnGetImport. 1599 * @param pErrInfo Where to return extened error information. 1600 */ 1601 DECLHIDDEN(int) supHardNtLdrCacheEntryGetBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, 1602 RTLDRADDR uBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser, 1603 PRTERRINFO pErrInfo) 1604 { 1605 int rc; 1606 1607 /* 1608 * First time around we have to allocate memory before we can get the image bits. 1609 */ 1601 1610 if (!pEntry->pbBits) 1602 1611 { … … 1610 1619 return supHardNtVpSetInfo1(pErrInfo, VERR_SUP_VP_NO_MEMORY, "Failed to allocate %zu bytes for image %s.", 1611 1620 cbBits, pEntry->pszName); 1612 } 1613 1614 /** @todo Try cache RTLdrGetBits calls too. */ 1621 1622 pEntry->fValidBits = false; /* paranoia */ 1623 1624 rc = RTLdrGetBits(pEntry->hLdrMod, pEntry->pbBits, uBaseAddress, pfnGetImport, pvUser); 1625 if (RT_FAILURE(rc)) 1626 return supHardNtVpSetInfo1(pErrInfo, VERR_SUP_VP_NO_MEMORY, "RTLdrGetBits failed on image %s: %Rrc", 1627 pEntry->pszName, rc); 1628 pEntry->uImageBase = uBaseAddress; 1629 pEntry->fValidBits = pfnGetImport == NULL; 1630 1631 } 1632 /* 1633 * Cache hit? No? 1634 * 1635 * Note! We cannot currently cache image bits for images with imports as we 1636 * don't control the way they're resolved. Fortunately, NTDLL and 1637 * the VM process images all have no imports. 1638 */ 1639 else if ( !pEntry->fValidBits 1640 || pEntry->uImageBase != uBaseAddress 1641 || pfnGetImport) 1642 { 1643 pEntry->fValidBits = false; 1644 1645 rc = RTLdrGetBits(pEntry->hLdrMod, pEntry->pbBits, uBaseAddress, pfnGetImport, pvUser); 1646 if (RT_FAILURE(rc)) 1647 return supHardNtVpSetInfo1(pErrInfo, VERR_SUP_VP_NO_MEMORY, "RTLdrGetBits failed on image %s: %Rrc", 1648 pEntry->pszName, rc); 1649 pEntry->uImageBase = uBaseAddress; 1650 pEntry->fValidBits = pfnGetImport == NULL; 1651 } 1615 1652 1616 1653 *ppbBits = pEntry->pbBits; … … 1651 1688 } 1652 1689 1653 pEntry->pszName = NULL; 1654 pEntry->fVerified = false; 1690 pEntry->pszName = NULL; 1691 pEntry->fVerified = false; 1692 pEntry->fValidBits = false; 1693 pEntry->uImageBase = 0; 1655 1694 } 1656 1695 … … 1760 1799 * Fill in the cache entry. 1761 1800 */ 1762 pEntry->pszName = pszName; 1763 pEntry->hLdrMod = hLdrMod; 1764 pEntry->pNtViRdr = pNtViRdr; 1765 pEntry->hFile = hFile; 1766 pEntry->pbBits = NULL; 1767 pEntry->fVerified = false; 1801 pEntry->pszName = pszName; 1802 pEntry->hLdrMod = hLdrMod; 1803 pEntry->pNtViRdr = pNtViRdr; 1804 pEntry->hFile = hFile; 1805 pEntry->pbBits = NULL; 1806 pEntry->fVerified = false; 1807 pEntry->fValidBits = false; 1808 pEntry->uImageBase = ~(uintptr_t)0; 1768 1809 1769 1810 #ifdef IN_SUP_HARDENED_R3 … … 2042 2083 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_NTDLL_MAPPING, 2043 2084 "The process has no NTDLL.DLL."); 2044 if (iKernel32 == UINT32_MAX && pThis->enmKind != SUPHARDNTVPKIND_CHILD_PURIFICATION)2085 if (iKernel32 == UINT32_MAX && pThis->enmKind == SUPHARDNTVPKIND_SELF_PURIFICATION) 2045 2086 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_KERNEL32_MAPPING, 2046 2087 "The process has no KERNEL32.DLL."); -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52943 r52947 240 240 /** Queue of cached images which needs their imports checked. */ 241 241 static PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL; 242 243 /** The windows path to dir \\SystemRoot\\System32 directory (technically 244 * this whatever \KnownDlls\KnownDllPath points to). */ 245 SUPSYSROOTDIRBUF g_System32WinPath; 242 246 /** @ */ 247 243 248 244 249 /** Static error info structure used during init. */ … … 305 310 # undef SYSCALL 306 311 #endif 312 313 DECLASM(void) supR3HardenedVmProcessInitThunk(void); 307 314 308 315 … … 1807 1814 * a search on the API level, all VBox calls will have full paths. 1808 1815 */ 1809 cwc = GetSystemDirectoryW(wszPath, RT_ELEMENTS(wszPath) - 32); 1810 if (!cwc) 1811 { 1812 supR3HardenedError(VINF_SUCCESS, false, 1813 "supR3HardenedMonitor_LdrLoadDll: GetSystemDirectoryW failed: %u\n", RtlGetLastWin32Error()); 1814 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_UNEXPECTED_IO_ERROR)); 1815 RtlRestoreLastWin32Error(dwSavedLastError); 1816 return STATUS_UNEXPECTED_IO_ERROR; 1817 } 1816 AssertCompile(sizeof(g_System32WinPath.awcBuffer) <= sizeof(wszPath)); 1817 cwc = g_System32WinPath.UniStr.Length / sizeof(RTUTF16); Assert(cwc > 2); 1818 1818 if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath)) 1819 1819 { … … 1824 1824 return STATUS_NAME_TOO_LONG; 1825 1825 } 1826 memcpy(wszPath, g_System32WinPath.UniStr.Buffer, cwc * sizeof(RTUTF16)); 1826 1827 wszPath[cwc++] = '\\'; 1827 1828 memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR)); … … 1853 1854 * and the real API can come up with a fitting status code for it. 1854 1855 */ 1855 HANDLE hFile = CreateFileW(wszPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/, 1856 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/); 1857 if (hFile != INVALID_HANDLE_VALUE) 1856 HANDLE hRootDir; 1857 UNICODE_STRING NtPathUniStr; 1858 int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, wszPath, RTSTR_MAX); 1859 if (RT_FAILURE(rc)) 1860 { 1861 supR3HardenedError(rc, false, 1862 "supR3HardenedMonitor_LdrLoadDll: RTNtPathFromWinUtf16Ex failed on '%ls': %Rrc\n", wszPath, rc); 1863 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID)); 1864 RtlRestoreLastWin32Error(dwSavedLastError); 1865 return STATUS_OBJECT_NAME_INVALID; 1866 } 1867 1868 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; 1869 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 1870 OBJECT_ATTRIBUTES ObjAttr; 1871 InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/); 1872 1873 rcNt = NtCreateFile(&hFile, 1874 FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE, 1875 &ObjAttr, 1876 &Ios, 1877 NULL /* Allocation Size*/, 1878 FILE_ATTRIBUTE_NORMAL, 1879 FILE_SHARE_READ, 1880 FILE_OPEN, 1881 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 1882 NULL /*EaBuffer*/, 1883 0 /*EaLength*/); 1884 if (NT_SUCCESS(rcNt)) 1885 rcNt = Ios.Status; 1886 if (NT_SUCCESS(rcNt)) 1858 1887 { 1859 1888 ULONG fAccess = 0; … … 1881 1910 { 1882 1911 DWORD dwErr = RtlGetLastWin32Error(); 1883 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u\n", wszPath, dwErr)); 1912 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u (NtPath=%.*ls)\n", 1913 wszPath, dwErr, NtPathUniStr.Length / sizeof(RTUTF16), NtPathUniStr.Buffer)); 1884 1914 } 1915 RTNtPathFree(&NtPathUniStr, &hRootDir); 1885 1916 } 1886 1917 … … 3655 3686 3656 3687 3657 static int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo) 3658 { 3688 static int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, uintptr_t *puChildNtDllAddr, uintptr_t *puChildExeAddr, 3689 PRTERRINFO pErrInfo) 3690 { 3691 *puChildNtDllAddr = 0; 3692 *puChildExeAddr = 0; 3693 3659 3694 /* 3660 3695 * Initialize the purifier instance data. … … 3695 3730 supR3HardNtPuChFindNtdll(&This); 3696 3731 3732 *puChildNtDllAddr = This.uNtDllAddr; 3733 *puChildExeAddr = (uintptr_t)This.Peb.ImageBaseAddress; 3734 3697 3735 /* 3698 3736 * Do the work, the last bit we tag along with the process verfication code. … … 3711 3749 3712 3750 /** 3751 * Terminates the child process. 3752 * 3753 * @param hProcess The process handle. 3754 * @param pszWhere Who's having child rasing troubles. 3755 * @param rc The status code to report. 3756 * @param pszFormat The message format string. 3757 * @param ... Message format arguments. 3758 */ 3759 static void supR3HardenedWinKillChild(HANDLE hProcess, const char *pszWhere, int rc, const char *pszFormat, ...) 3760 { 3761 /* 3762 * Terminate the process ASAP and display error. 3763 */ 3764 NtTerminateProcess(hProcess, RTEXITCODE_FAILURE); 3765 3766 va_list va; 3767 va_start(va, pszFormat); 3768 supR3HardenedErrorV(rc, false /*fFatal*/, pszFormat, va); 3769 va_end(va); 3770 3771 /* 3772 * Wait for the process to really go away. 3773 */ 3774 PROCESS_BASIC_INFORMATION BasicInfo; 3775 NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 3776 bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING; 3777 if (!fExitOk) 3778 { 3779 NTSTATUS rcNtWait; 3780 DWORD dwStartTick = GetTickCount(); 3781 do 3782 { 3783 NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS); 3784 3785 LARGE_INTEGER Timeout; 3786 Timeout.QuadPart = -20000000; /* 2 second */ 3787 rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout); 3788 3789 rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 3790 fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING; 3791 } while ( !fExitOk 3792 && ( rcNtWait == STATUS_TIMEOUT 3793 || rcNtWait == STATUS_USER_APC 3794 || rcNtWait == STATUS_ALERTED) 3795 && GetTickCount() - dwStartTick < 60 * 1000); 3796 if (fExitOk) 3797 supR3HardenedError(rc, false /*fFatal*/, 3798 "NtDuplicateObject failed and we failed to kill child: rc=%u (%#x) rcNtWait=%#x hProcess=%p\n", 3799 rc, rc, rcNtWait, hProcess); 3800 } 3801 3802 /* 3803 * Final error message. 3804 */ 3805 va_start(va, pszFormat); 3806 supR3HardenedFatalMsgV(pszWhere, kSupInitOp_Misc, rc, pszFormat, va); 3807 va_end(va); 3808 } 3809 3810 3811 /** 3812 * Checks the child process for error when the parent event semaphore is 3813 * signaled. 3814 * 3815 * If there is an error pending, this function will not return. 3816 * 3817 * @param hProcWait The child process handle. 3818 * @param uChildExeAddr The address of the executable in the child process. 3819 * @param phEvtParent Pointer to the parent event semaphore handle. We 3820 * may close the event semaphore and set it to NULL. 3821 * @param phEvtChild Pointer to the child event semaphore handle. We may 3822 * close the event semaphore and set it to NULL. 3823 */ 3824 static void supR3HardenedWinCheckVmChild(HANDLE hProcWait, uintptr_t uChildExeAddr, HANDLE *phEvtParent, HANDLE *phEvtChild) 3825 { 3826 /* 3827 * Read the process parameters from the child. 3828 */ 3829 uintptr_t uChildAddr = uChildExeAddr + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress); 3830 SIZE_T cbIgnored; 3831 SUPR3WINPROCPARAMS ChildProcParams; 3832 RT_ZERO(ChildProcParams); 3833 NTSTATUS rcNt = NtReadVirtualMemory(hProcWait, (PVOID)uChildAddr, &ChildProcParams, sizeof(ChildProcParams), &cbIgnored); 3834 if (!NT_SUCCESS(rcNt)) 3835 supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt, 3836 "NtReadVirtualMemory(,%p,) failed reading child process status: %#x\n", uChildAddr, rcNt); 3837 3838 /* 3839 * Signal the child to get on with whatever it's doing. 3840 */ 3841 rcNt = NtSetEvent(*phEvtChild, NULL); 3842 if (!NT_SUCCESS(rcNt)) 3843 supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt, "NtSetEvent failed: %#x\n", rcNt); 3844 3845 /* 3846 * Close the event semaphore handles. 3847 */ 3848 rcNt = NtClose(*phEvtParent); 3849 if (NT_SUCCESS(rcNt)) 3850 rcNt = NtClose(*phEvtChild); 3851 if (!NT_SUCCESS(rcNt)) 3852 supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt, "NtClose failed on event sem: %#x\n", rcNt); 3853 *phEvtChild = NULL; 3854 *phEvtParent = NULL; 3855 3856 /* 3857 * Process the information we read. 3858 */ 3859 if (ChildProcParams.rc == VINF_SUCCESS) 3860 return; 3861 3862 /* An error occurred, report it. */ 3863 ChildProcParams.szErrorMsg[sizeof(ChildProcParams.szErrorMsg) - 1] = '\0'; 3864 supR3HardenedFatalMsg("supR3HardenedWinCheckVmChild", kSupInitOp_Misc, ChildProcParams.rc, "%s", ChildProcParams.szErrorMsg); 3865 } 3866 3867 3868 static void supR3HardenedWinInitVmChild(HANDLE hProcess, HANDLE hThread, uintptr_t uChildNtDllAddr, uintptr_t uChildExeAddr, 3869 HANDLE hEvtChild, HANDLE hEvtParent) 3870 { 3871 /* 3872 * Plant the process parameters. This ASSUMES the handle inheritance is 3873 * performed when creating the child process. 3874 */ 3875 SUPR3WINPROCPARAMS ChildProcParams; 3876 RT_ZERO(ChildProcParams); 3877 ChildProcParams.hEvtChild = hEvtChild; 3878 ChildProcParams.hEvtParent = hEvtParent; 3879 ChildProcParams.uNtDllAddr = uChildNtDllAddr; 3880 ChildProcParams.rc = VINF_SUCCESS; 3881 3882 uintptr_t uChildAddr = uChildExeAddr + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress); 3883 SIZE_T cbIgnored; 3884 NTSTATUS rcNt = NtWriteVirtualMemory(hProcess, (PVOID)uChildAddr, &ChildProcParams, sizeof(ChildProcParams), &cbIgnored); 3885 if (!NT_SUCCESS(rcNt)) 3886 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt, 3887 "NtWriteVirtualMemory(,%p,) failed writing child process parameters: %#x\n", uChildAddr, rcNt); 3888 3889 /* 3890 * Locate the LdrInitializeThunk address in the child as well as pristine 3891 * code bits for it. 3892 */ 3893 PSUPHNTLDRCACHEENTRY pLdrEntry; 3894 int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry); 3895 if (RT_FAILURE(rc)) 3896 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc, 3897 "supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc); 3898 3899 uint8_t *pbChildNtDllBits; 3900 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbChildNtDllBits, uChildNtDllAddr, NULL, NULL, NULL /*pErrInfo*/); 3901 if (RT_FAILURE(rc)) 3902 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc, 3903 "supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc); 3904 3905 RTLDRADDR uLdrInitThunk; 3906 rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbChildNtDllBits, uChildNtDllAddr, UINT32_MAX, 3907 "LdrInitializeThunk", &uLdrInitThunk); 3908 if (RT_FAILURE(rc)) 3909 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc, 3910 "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc); 3911 PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk; 3912 SUP_DPRINTF(("supR3HardenedWinInitVmChild: uLdrInitThunk=%p\n", (uintptr_t)uLdrInitThunk)); 3913 3914 /* 3915 * Calculate the address of our code in the child process. 3916 */ 3917 uintptr_t uEarlyVmProcInitEP = uChildExeAddr + ( (uintptr_t)&supR3HardenedVmProcessInitThunk 3918 - (uintptr_t)NtCurrentPeb()->ImageBaseAddress); 3919 3920 /* 3921 * Compose the LdrInitializeThunk replacement bytes. 3922 */ 3923 uint8_t abNew[16]; 3924 memcpy(abNew, pbChildNtDllBits + ((uintptr_t)uLdrInitThunk - uChildNtDllAddr), sizeof(abNew)); 3925 #ifdef RT_ARCH_AMD64 3926 abNew[0] = 0xff; 3927 abNew[1] = 0x25; 3928 *(uint32_t *)&abNew[2] = 0; 3929 *(uint64_t *)&abNew[6] = uEarlyVmProcInitEP; 3930 #elif defined(RT_ARCH_X86) 3931 abNew[0] = 0xe9; 3932 *(uint32_t *)&abNew[1] = uEarlyVmProcInitEP - ((uint32_t)uLdrInitThunk + 5); 3933 #else 3934 # error "Unsupported arch." 3935 #endif 3936 3937 /* 3938 * Install the LdrInitializeThunk replacement code in the child process. 3939 */ 3940 PVOID pvProt = pvLdrInitThunk; 3941 SIZE_T cbProt = sizeof(abNew); 3942 ULONG fOldProt; 3943 rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt); 3944 if (!NT_SUCCESS(rcNt)) 3945 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt, 3946 "NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt); 3947 3948 rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, abNew, sizeof(abNew), &cbIgnored); 3949 if (!NT_SUCCESS(rcNt)) 3950 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt, 3951 "NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt); 3952 3953 pvProt = pvLdrInitThunk; 3954 cbProt = sizeof(abNew); 3955 rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt); 3956 if (!NT_SUCCESS(rcNt)) 3957 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt, 3958 "NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt); 3959 3960 /* Caller starts child execution. */ 3961 SUP_DPRINTF(("supR3HardenedWinInitVmChild: Start child.\n")); 3962 } 3963 3964 3965 /** 3713 3966 * Does the actually respawning. 3714 3967 * … … 3726 3979 3727 3980 SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1); 3981 3982 /* 3983 * Set up VM child communication event semaphores. 3984 */ 3985 HANDLE hEvtChild = NULL; 3986 HANDLE hEvtParent = NULL; 3987 if (iWhich >= 2) 3988 { 3989 OBJECT_ATTRIBUTES ObjAttrs; 3990 InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/); 3991 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtChild, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE)); 3992 InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/); 3993 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtParent, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE)); 3994 } 3728 3995 3729 3996 /* … … 3854 4121 * supR3HardenedWinInstallHooks.) 3855 4122 */ 3856 rcNt = NtSetInformationThread( NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);4123 rcNt = NtSetInformationThread(hThread, ThreadHideFromDebugger, NULL, 0); 3857 4124 if (!NT_SUCCESS(rcNt)) 3858 { 3859 NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS); 3860 supR3HardenedError(rcNt, true /*fFatal*/, "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt); 3861 } 4125 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", rcNt, 4126 "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt); 3862 4127 #endif 3863 4128 … … 3865 4130 * Clean up the process. 3866 4131 */ 3867 int rc = supR3HardenedWinPurifyChild(hProcess, hThread, RTErrInfoInitStatic(&g_ErrInfoStatic)); 4132 uintptr_t uChildNtDllAddr; 4133 uintptr_t uChildExeAddr; 4134 int rc = supR3HardenedWinPurifyChild(hProcess, hThread, &uChildNtDllAddr, &uChildExeAddr, 4135 RTErrInfoInitStatic(&g_ErrInfoStatic)); 3868 4136 if (RT_FAILURE(rc)) 3869 { 3870 NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS); 3871 supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg); 3872 } 4137 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", rc, "%s", g_ErrInfoStatic.szMsg); 3873 4138 3874 4139 /* 3875 4140 * Start the process execution. 3876 4141 */ 4142 if (iWhich >= 2) 4143 supR3HardenedWinInitVmChild(hProcess, hThread, uChildNtDllAddr, uChildExeAddr, hEvtChild, hEvtParent); 4144 3877 4145 ULONG cSuspendCount = 0; 3878 4146 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtResumeThread(hThread, &cSuspendCount)); … … 3887 4155 PROCESS_BASIC_INFORMATION BasicInfo; 3888 4156 HANDLE hProcWait; 3889 ULONG fRights = SYNCHRONIZE ;4157 ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE; 3890 4158 if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */ 3891 4159 fRights |= PROCESS_QUERY_LIMITED_INFORMATION; 3892 4160 else 3893 4161 fRights |= PROCESS_QUERY_INFORMATION; 4162 if (iWhich == 2) 4163 fRights |= PROCESS_VM_READ; 3894 4164 rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess, 3895 4165 NtCurrentProcess(), &hProcWait, … … 3900 4170 SYNCHRONIZE, 0 /*HandleAttributes*/, 0); 3901 4171 if (!NT_SUCCESS(rcNt)) 3902 { 3903 /* Failure is unacceptable, kill the process. */ 3904 NtTerminateProcess(hProcess, RTEXITCODE_FAILURE); 3905 supR3HardenedError(rcNt, false /*fFatal*/, "NtDuplicateObject failed on child process handle: %#x\n", rcNt); 3906 3907 NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 3908 bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING; 3909 if (!fExitOk) 3910 { 3911 NTSTATUS rcNtWait; 3912 DWORD dwStartTick = GetTickCount(); 3913 do 3914 { 3915 NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS); 3916 3917 LARGE_INTEGER Timeout; 3918 Timeout.QuadPart = -20000000; /* 2 second */ 3919 rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout); 3920 3921 rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 3922 fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING; 3923 } while ( !fExitOk 3924 && ( rcNtWait == STATUS_TIMEOUT 3925 || rcNtWait == STATUS_USER_APC 3926 || rcNtWait == STATUS_ALERTED) 3927 && GetTickCount() - dwStartTick < 60 * 1000); 3928 if (fExitOk) 3929 supR3HardenedError(rcNt, false /*fFatal*/, 3930 "NtDuplicateObject failed and we failed to kill child: rcNt=%u rcNtWait=%u hProcess=%p\n", 3931 rcNt, rcNtWait, hProcess); 3932 } 3933 supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME, 3934 "NtDuplicateObject failed on child process handle: %#x\n", rcNt); 3935 } 4172 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", VERR_INVALID_NAME, 4173 "NtDuplicateObject failed on child process handle: %#x\n", rcNt); 3936 4174 3937 4175 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess)); 3938 4176 hProcess = NULL; 4177 4178 /* 4179 * Signal the VM child that we've closed the unrestricted handles. 4180 */ 4181 if (iWhich >= 2) 4182 { 4183 rcNt = NtSetEvent(hEvtChild, NULL); 4184 if (!NT_SUCCESS(rcNt)) 4185 supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", VERR_INVALID_NAME, 4186 "NtSetEvent failed on child process handle: %#x\n", rcNt); 4187 } 3939 4188 3940 4189 /* … … 3972 4221 } 3973 4222 4223 for (;;) 4224 { 4225 HANDLE ahHandles[3]; 4226 ULONG cHandles = 1; 4227 ahHandles[0] = hProcWait; 4228 if (hEvtParent != NULL) 4229 ahHandles[cHandles++] = hEvtParent; 4230 if (hParent != NULL) 4231 ahHandles[cHandles++] = hParent; 4232 4233 rcNt = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*pTimeout*/); 4234 if (rcNt == STATUS_WAIT_0 + 1 && hEvtParent != NULL) 4235 supR3HardenedWinCheckVmChild(hProcWait, uChildExeAddr, &hEvtParent, &hEvtChild); 4236 else if ( (ULONG)rcNt - (ULONG)STATUS_WAIT_0 < cHandles 4237 || (ULONG)rcNt - (ULONG)STATUS_ABANDONED_WAIT_0 < cHandles) 4238 break; 4239 else if ( rcNt != STATUS_TIMEOUT 4240 && rcNt != STATUS_USER_APC 4241 && rcNt != STATUS_ALERTED) 4242 supR3HardenedFatal("NtWaitForMultipleObjects returned %#x\n", rcNt); 4243 } 4244 3974 4245 if (hParent != NULL) 3975 {3976 for (;;)3977 {3978 HANDLE ahHandles[2] = { hProcWait, hParent };3979 rcNt = NtWaitForMultipleObjects(2, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*pTimeout*/);3980 if ( rcNt == STATUS_WAIT_03981 || rcNt == STATUS_WAIT_0 + 13982 || rcNt == STATUS_ABANDONED_WAIT_03983 || rcNt == STATUS_ABANDONED_WAIT_0 + 1)3984 break;3985 if ( rcNt != STATUS_TIMEOUT3986 && rcNt != STATUS_USER_APC3987 && rcNt != STATUS_ALERTED)3988 supR3HardenedFatal("NtWaitForMultipleObjects returned %#x\n", rcNt);3989 }3990 4246 NtClose(hParent); 3991 }3992 else3993 {3994 /*3995 * Wait for the process to terminate.3996 */3997 for (;;)3998 {3999 rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);4000 if ( rcNt == STATUS_WAIT_04001 || rcNt == STATUS_ABANDONED_WAIT_0)4002 break;4003 if ( rcNt != STATUS_TIMEOUT4004 && rcNt != STATUS_USER_APC4005 && rcNt != STATUS_ALERTED)4006 supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);4007 }4008 }4009 4247 4010 4248 /* … … 4012 4250 */ 4013 4251 NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); 4014 if ( !NT_SUCCESS(rcNt2) 4015 || BasicInfo.ExitStatus == STATUS_PENDING) 4252 if (!NT_SUCCESS(rcNt2)) 4016 4253 BasicInfo.ExitStatus = RTEXITCODE_FAILURE; 4254 else if (BasicInfo.ExitStatus == STATUS_PENDING) 4255 { 4256 if (hEvtParent) 4257 NtTerminateProcess(hProcWait, RTEXITCODE_FAILURE); 4258 BasicInfo.ExitStatus = RTEXITCODE_FAILURE; 4259 } 4017 4260 4018 4261 NtClose(hProcWait); … … 4392 4635 DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge) 4393 4636 { 4637 /* 4638 * Init the verifier. 4639 */ 4394 4640 RTErrInfoInitStatic(&g_ErrInfoStatic); 4395 4641 int rc = supHardenedWinInitImageVerifier(&g_ErrInfoStatic.Core); … … 4397 4643 supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rc, 4398 4644 "supHardenedWinInitImageVerifier failed: %s", g_ErrInfoStatic.szMsg); 4645 4646 /* 4647 * Get the windows system directory from the KnownDlls dir. 4648 */ 4649 HANDLE hSymlink = INVALID_HANDLE_VALUE; 4650 UNICODE_STRING UniStr = RTNT_CONSTANT_UNISTR(L"\\KnownDlls\\KnownDllPath"); 4651 OBJECT_ATTRIBUTES ObjAttrs; 4652 InitializeObjectAttributes(&ObjAttrs, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 4653 NTSTATUS rcNt = NtOpenSymbolicLinkObject(&hSymlink, SYMBOLIC_LINK_QUERY, &ObjAttrs); 4654 if (!NT_SUCCESS(rcNt)) 4655 supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error opening '%ls': %#x", UniStr.Buffer, rcNt); 4656 4657 g_System32WinPath.UniStr.Buffer = g_System32WinPath.awcBuffer; 4658 g_System32WinPath.UniStr.Length = 0; 4659 g_System32WinPath.UniStr.MaximumLength = sizeof(g_System32WinPath.awcBuffer) - sizeof(RTUTF16); 4660 rcNt = NtQuerySymbolicLinkObject(hSymlink, &g_System32WinPath.UniStr, NULL); 4661 if (!NT_SUCCESS(rcNt)) 4662 supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error querying '%ls': %#x", UniStr.Buffer, rcNt); 4663 g_System32WinPath.UniStr.Buffer[g_System32WinPath.UniStr.Length / sizeof(RTUTF16)] = '\0'; 4664 4665 SUP_DPRINTF(("KnownDllPath: %ls\n", g_System32WinPath.UniStr.Buffer)); 4666 NtClose(hSymlink); 4399 4667 4400 4668 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)) … … 4445 4713 /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */ 4446 4714 ULONG cPatchCount = 0; 4447 NTSTATUSrcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,4448 4715 rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount, 4716 &cPatchCount, sizeof(cPatchCount), NULL); 4449 4717 if (NT_SUCCESS(rcNt)) 4450 4718 SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n", … … 5250 5518 5251 5519 /* 5252 * Wait on the parent process to dispose of the full access process handle. 5520 * Wait on the parent process to dispose of the full access process and 5521 * thread handles. 5253 5522 */ 5254 5523 LARGE_INTEGER Timeout; … … 5299 5568 * Open the driver. 5300 5569 */ 5570 SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n")); 5301 5571 supR3HardenedMainOpenDevice(); 5302 5572 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED; … … 5306 5576 * normally when we return. 5307 5577 */ 5578 SUP_DPRINTF(("supR3HardenedVmProcessInit: Restoring LdrIntiailizeThunk...\n")); 5308 5579 PSUPHNTLDRCACHEENTRY pLdrEntry; 5309 5580 int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry); … … 5311 5582 supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc); 5312 5583 5584 uint8_t *pbBits; 5585 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, g_ProcParams.uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/); 5586 if (RT_FAILURE(rc)) 5587 supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc); 5588 5313 5589 RTLDRADDR uValue; 5314 rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, p LdrEntry->pbBits, 0, UINT32_MAX, "LdrInitializeThunk", &uValue);5590 rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, g_ProcParams.uNtDllAddr, UINT32_MAX, "LdrInitializeThunk", &uValue); 5315 5591 if (RT_FAILURE(rc)) 5316 5592 supR3HardenedFatal("supR3HardenedVmProcessInit: Failed to find LdrInitializeThunk (%Rrc).\n", rc); 5317 5593 5318 PVOID pvLdrInitThunk = ( uint8_t *)g_ProcParams.uNtDllAddr + (uint32_t)uValue;5594 PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uValue; 5319 5595 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READWRITE)); 5320 memcpy(pvLdrInitThunk, p LdrEntry->pbBits + (uint32_t)uValue, 16);5596 memcpy(pvLdrInitThunk, pbBits + ((uintptr_t)uValue - g_ProcParams.uNtDllAddr), 16); 5321 5597 SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READ)); 5322 5598 5599 SUP_DPRINTF(("supR3HardenedVmProcessInit: Returning to LdrIntiailizeThunk...\n")); 5323 5600 return (uintptr_t)pvLdrInitThunk; 5324 5601 } -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
r52943 r52947 641 641 { 642 642 uint8_t *pbBits; 643 rc = supHardNtLdrCacheEntryAllocBits(pLdrEntry, &pbBits, NULL); 643 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL, 644 NULL /*pErrInfo*/); 644 645 if (RT_SUCCESS(rc)) 645 646 { 646 rc = RTLdrGetBits(pLdrEntry->hLdrMod, pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL); 647 if (RT_SUCCESS(rc)) 648 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 649 supR3HardenedDirectSyscall(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i], 650 &g_aSupNtImpDlls[iDll].paSyscalls[i], pLdrEntry, pbBits); 651 else 652 SUPHNTIMP_ERROR(19, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, 653 "%ls: RTLdrGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc); 647 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 648 supR3HardenedDirectSyscall(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i], 649 &g_aSupNtImpDlls[iDll].paSyscalls[i], pLdrEntry, pbBits); 654 650 } 655 651 else 656 652 SUPHNTIMP_ERROR(20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, 657 "%ls: supHardNtLdrCacheEntry AllocBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);653 "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc); 658 654 } 659 655 else … … 674 670 { 675 671 uint8_t *pbBits; 676 rc = supHardNtLdrCacheEntryAllocBits(pLdrEntry, &pbBits, NULL); 672 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL, 673 NULL /*pErrInfo*/); 677 674 if (RT_SUCCESS(rc)) 678 675 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) … … 712 709 if (RTStrICmp(g_aSupNtImpDlls[iDll].pszName, pszDll) == 0) 713 710 { 711 714 712 PSUPHNTLDRCACHEENTRY pLdrEntry; 715 713 int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry); … … 717 715 { 718 716 uint8_t *pbBits; 719 rc = supHardNtLdrCacheEntryAllocBits(pLdrEntry, &pbBits, NULL); 717 rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, (uintptr_t)g_aSupNtImpDlls[iDll].pbImageBase, NULL, NULL, 718 NULL /*pErrInfo*/); 720 719 if (RT_SUCCESS(rc)) 721 720 { … … 736 735 737 736 /* Complications, just call GetProcAddress. */ 738 return (PFNRT)GetProcAddress(GetModuleHandleW(g_aSupNtImpDlls[iDll].pwszName), pszProcedure); 737 if (g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 738 return (PFNRT)GetProcAddress(GetModuleHandleW(g_aSupNtImpDlls[iDll].pwszName), pszProcedure); 739 return NULL; 739 740 } 740 741 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp
r52941 r52947 39 39 #include <iprt/assert.h> 40 40 #include <iprt/ctype.h> 41 #include <iprt/heap.h> 41 42 #include <iprt/string.h> 42 43 #include <iprt/initterm.h> 43 44 #include <iprt/param.h> 45 #include <iprt/path.h> 44 46 #include <iprt/mem.h> 45 47 … … 97 99 */ 98 100 99 /** The heap we're using. */ 100 static HANDLE g_hSupR3HardenedHeap = NULL; 101 /** The handle of the heap we're using. */ 102 static HANDLE g_hSupR3HardenedHeap = NULL; 103 /** Number of heaps used during early process init. */ 104 static uint32_t g_cSupR3HardenedEarlyHeaps = 0; 105 /** Early process init heaps. */ 106 static struct 107 { 108 /** The heap handle. */ 109 RTHEAPSIMPLE hHeap; 110 /** The heap block pointer. */ 111 void *pvBlock; 112 /** The size of the heap block. */ 113 size_t cbBlock; 114 /** Number of active allocations on this heap. */ 115 size_t cAllocations; 116 } g_aSupR3HardenedEarlyHeaps[8]; 117 118 119 static uint32_t supR3HardenedEarlyFind(void *pv) 120 { 121 uint32_t iHeap = g_cSupR3HardenedEarlyHeaps; 122 while (iHeap-- > 0) 123 if ((uintptr_t)pv - (uintptr_t)g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock < g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock) 124 return iHeap; 125 return UINT32_MAX; 126 } 127 128 129 static void supR3HardenedEarlyCompact(void) 130 { 131 uint32_t iHeap = g_cSupR3HardenedEarlyHeaps; 132 while (iHeap-- > 0) 133 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations == 0) 134 { 135 PVOID pvMem = g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock; 136 SIZE_T cbMem = g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock; 137 if (iHeap + 1 < g_cSupR3HardenedEarlyHeaps) 138 g_aSupR3HardenedEarlyHeaps[iHeap] = g_aSupR3HardenedEarlyHeaps[g_cSupR3HardenedEarlyHeaps - 1]; 139 g_cSupR3HardenedEarlyHeaps--; 140 141 NTSTATUS rcNt = NtFreeVirtualMemory(NtCurrentProcess(), &pvMem, &cbMem, MEM_RELEASE); 142 Assert(NT_SUCCESS(rcNt)); 143 SUP_DPRINTF(("supR3HardenedEarlyCompact: Removed heap %#u (%#p LB %#zx)\n", iHeap, pvMem, cbMem)); 144 } 145 } 146 147 148 static void *supR3HardenedEarlyAlloc(size_t cb, bool fZero) 149 { 150 /* 151 * Try allocate on existing heaps. 152 */ 153 void *pv; 154 uint32_t iHeap = 0; 155 while (iHeap < g_cSupR3HardenedEarlyHeaps) 156 { 157 if (fZero) 158 pv = RTHeapSimpleAllocZ(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0); 159 else 160 pv = RTHeapSimpleAlloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, cb, 0); 161 if (pv) 162 { 163 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations++; 164 #ifdef SUPR3HARDENED_EARLY_HEAP_TRACE 165 SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb)); 166 #endif 167 return pv; 168 } 169 iHeap++; 170 } 171 172 /* 173 * Add another heap. 174 */ 175 if (iHeap == RT_ELEMENTS(g_aSupR3HardenedEarlyHeaps)) 176 supR3HardenedFatal("Early heap table is full (cb=%#zx).\n", cb); 177 SIZE_T cbBlock = iHeap == 0 ? _1M : g_aSupR3HardenedEarlyHeaps[iHeap - 1].cbBlock * 2; 178 while (cbBlock <= cb * 2) 179 cbBlock *= 2; 180 181 PVOID pvBlock = NULL; 182 NTSTATUS rcNt = NtAllocateVirtualMemory(NtCurrentProcess(), &pvBlock, 0 /*ZeroBits*/, &cbBlock, MEM_COMMIT, PAGE_READWRITE); 183 if (!NT_SUCCESS(rcNt)) 184 supR3HardenedFatal("NtAllocateVirtualMemory(,,,%#zx,,) failed: rcNt=%#x\n", cbBlock, rcNt); 185 SUP_DPRINTF(("New simple heap: #%u %p LB %#zx (for %zu allocation)\n", iHeap, pvBlock, cbBlock, cb)); 186 187 RTHEAPSIMPLE hHeap; 188 int rc = RTHeapSimpleInit(&hHeap, pvBlock, cbBlock); 189 if (RT_FAILURE(rc)) 190 supR3HardenedFatal("RTHeapSimpleInit(,%p,%#zx) failed: rc=%#x\n", pvBlock, cbBlock, rc); 191 192 if (fZero) 193 pv = RTHeapSimpleAllocZ(hHeap, cb, 0); 194 else 195 pv = RTHeapSimpleAlloc(hHeap, cb, 0); 196 if (!pv) 197 supR3HardenedFatal("RTHeapSimpleAlloc[Z] failed allocating %#zx bytes on a %#zu heap.\n", cb, cbBlock); 198 199 g_aSupR3HardenedEarlyHeaps[iHeap].pvBlock = pvBlock; 200 g_aSupR3HardenedEarlyHeaps[iHeap].cbBlock = cbBlock; 201 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations = 1; 202 g_aSupR3HardenedEarlyHeaps[iHeap].hHeap = hHeap; 203 204 Assert(g_cSupR3HardenedEarlyHeaps == iHeap); 205 g_cSupR3HardenedEarlyHeaps = iHeap + 1; 206 207 #ifdef SUPR3HARDENED_EARLY_HEAP_TRACE 208 SUP_DPRINTF(("Early heap: %p LB %#zx - alloc\n", pv, cb)); 209 #endif 210 return pv; 211 } 101 212 102 213 … … 108 219 static HANDLE supR3HardenedHeapInit(void) 109 220 { 221 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED); 110 222 HANDLE hHeap = RtlCreateHeap(HEAP_GROWABLE | HEAP_CLASS_PRIVATE, NULL /*HeapBase*/, 111 223 0 /*ReserveSize*/, 0 /*CommitSize*/, NULL /*Lock*/, NULL /*Parameters*/); … … 129 241 RtlCompactHeap(g_hSupR3HardenedHeap, 0 /*dwFlags*/); 130 242 RtlCompactHeap(GetProcessHeap(), 0 /*dwFlags*/); 243 supR3HardenedEarlyCompact(); 131 244 } 132 245 … … 155 268 HANDLE hHeap = g_hSupR3HardenedHeap; 156 269 if (!hHeap) 270 { 271 if ( g_fSupEarlyVmProcessInit 272 && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED) 273 return supR3HardenedEarlyAlloc(cb, false /*fZero*/); 157 274 hHeap = supR3HardenedHeapInit(); 275 } 276 158 277 void *pv = RtlAllocateHeap(hHeap, 0 /*fFlags*/, cb); 159 278 if (!pv) … … 167 286 HANDLE hHeap = g_hSupR3HardenedHeap; 168 287 if (!hHeap) 288 { 289 if ( g_fSupEarlyVmProcessInit 290 && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED) 291 return supR3HardenedEarlyAlloc(cb, true /*fZero*/); 169 292 hHeap = supR3HardenedHeapInit(); 293 } 294 170 295 void *pv = RtlAllocateHeap(hHeap, HEAP_ZERO_MEMORY, cb); 171 296 if (!pv) … … 202 327 return RTMemAllocZTag(cbNew, pszTag); 203 328 329 void *pv; 330 if (g_fSupEarlyVmProcessInit) 331 { 332 uint32_t iHeap = supR3HardenedEarlyFind(pvOld); 333 if (iHeap != UINT32_MAX) 334 { 335 #if 0 /* RTHeapSimpleRealloc is not implemented */ 336 /* If this is before we can use a regular heap, we try resize 337 within the simple heap. (There are a lot of array growing in 338 the ASN.1 code.) */ 339 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 340 { 341 pv = RTHeapSimpleRealloc(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld, cbNew, 0); 342 if (pv) 343 { 344 # ifdef SUPR3HARDENED_EARLY_HEAP_TRACE 345 SUP_DPRINTF(("Early heap: %p LB %#zx, was %p - realloc\n", pvNew, cbNew, pvOld)); 346 # endif 347 return pv; 348 } 349 } 350 #endif 351 352 /* Either we can't reallocate it on the same simple heap, or we're 353 past hardened main and wish to migrate everything over on the 354 real heap. */ 355 size_t cbOld = RTHeapSimpleSize(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld); 356 pv = RTMemAllocTag(cbNew, pszTag); 357 if (pv) 358 { 359 memcpy(pv, pvOld, RT_MIN(cbOld, cbNew)); 360 RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pvOld); 361 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations) 362 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--; 363 if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations 364 && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 365 supR3HardenedEarlyCompact(); 366 } 367 # ifdef SUPR3HARDENED_EARLY_HEAP_TRACE 368 SUP_DPRINTF(("Early heap: %p LB %#zx, was %p %LB %#zx - realloc\n", pv, cbNew, pvOld, cbOld)); 369 # endif 370 return pv; 371 } 372 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED); 373 } 374 375 /* Allocate from the regular heap. */ 204 376 HANDLE hHeap = g_hSupR3HardenedHeap; 205 377 Assert(hHeap != NULL); 206 void *pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew);378 pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew); 207 379 if (!pv) 208 380 supR3HardenedFatal("RtlReAllocateHeap failed to allocate %zu bytes.\n", cbNew); … … 215 387 if (pv) 216 388 { 389 if (g_fSupEarlyVmProcessInit) 390 { 391 uint32_t iHeap = supR3HardenedEarlyFind(pv); 392 if (iHeap != UINT32_MAX) 393 { 394 #ifdef SUPR3HARDENED_EARLY_HEAP_TRACE 395 SUP_DPRINTF(("Early heap: %p - free\n", pv)); 396 #endif 397 RTHeapSimpleFree(g_aSupR3HardenedEarlyHeaps[iHeap].hHeap, pv); 398 if (g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations) 399 g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations--; 400 if ( !g_aSupR3HardenedEarlyHeaps[iHeap].cAllocations 401 && g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 402 supR3HardenedEarlyCompact(); 403 return; 404 } 405 Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED); 406 } 407 217 408 HANDLE hHeap = g_hSupR3HardenedHeap; 218 409 Assert(hHeap != NULL); … … 251 442 } 252 443 444 445 446 /* 447 * path-win.cpp 448 */ 449 450 RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cbPath) 451 { 452 int rc; 453 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED) 454 /** @todo Rainy day: improve this by checking the process parameter block 455 * (needs to be normalized). */ 456 rc = RTStrCopy(pszPath, cbPath, "C:\\"); 457 else 458 { 459 /* 460 * GetCurrentDirectory may in some cases omit the drive letter, according 461 * to MSDN, thus the GetFullPathName call. 462 */ 463 RTUTF16 wszCurPath[RTPATH_MAX]; 464 if (GetCurrentDirectoryW(RTPATH_MAX, wszCurPath)) 465 { 466 RTUTF16 wszFullPath[RTPATH_MAX]; 467 if (GetFullPathNameW(wszCurPath, RTPATH_MAX, wszFullPath, NULL)) 468 rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cbPath, NULL); 469 else 470 rc = RTErrConvertFromWin32(RtlGetLastWin32Error()); 471 } 472 else 473 rc = RTErrConvertFromWin32(RtlGetLastWin32Error()); 474 } 475 return rc; 476 } 477 -
trunk/src/VBox/HostDrivers/Support/win/import-template-kernel32.h
r52941 r52947 3 3 SUPHARNT_IMPORT_STDCALL(ExitProcess, 4) 4 4 SUPHARNT_IMPORT_STDCALL(GetFullPathNameA, 16) 5 SUPHARNT_IMPORT_STDCALL(GetFullPathNameW, 16) 6 SUPHARNT_IMPORT_STDCALL(GetCurrentDirectoryW, 8) 5 7 SUPHARNT_IMPORT_STDCALL(GetModuleFileNameW, 12) 6 8 SUPHARNT_IMPORT_STDCALL(GetModuleHandleA, 4) -
trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
r52943 r52947 4 4 SUPHARNT_IMPORT_SYSCALL(NtCreateEvent, 20) 5 5 SUPHARNT_IMPORT_SYSCALL(NtCreateFile, 44) 6 SUPHARNT_IMPORT_SYSCALL(NtCreateSymbolicLinkObject, 16) 6 7 SUPHARNT_IMPORT_SYSCALL(NtDelayExecution, 8) 7 8 SUPHARNT_IMPORT_SYSCALL(NtDeviceIoControlFile, 40) … … 15 16 SUPHARNT_IMPORT_SYSCALL(NtOpenProcess, 16) 16 17 SUPHARNT_IMPORT_SYSCALL(NtOpenProcessToken, 12) 18 SUPHARNT_IMPORT_SYSCALL(NtOpenSymbolicLinkObject, 12) 17 19 SUPHARNT_IMPORT_SYSCALL(NtOpenThread, 16) 18 20 SUPHARNT_IMPORT_SYSCALL(NtOpenThreadToken, 16) … … 27 29 SUPHARNT_IMPORT_SYSCALL(NtQueryObject, 20) 28 30 SUPHARNT_IMPORT_SYSCALL(NtQuerySecurityObject, 20) 31 SUPHARNT_IMPORT_SYSCALL(NtQuerySymbolicLinkObject, 12) 29 32 SUPHARNT_IMPORT_SYSCALL(NtQuerySystemInformation, 16) 30 33 SUPHARNT_IMPORT_SYSCALL(NtQueryTimerResolution, 12)
Note:
See TracChangeset
for help on using the changeset viewer.