VirtualBox

Ignore:
Timestamp:
Oct 5, 2014 4:48:25 PM (10 years ago)
Author:
vboxsync
Message:

SUP: Implemented early VM process vboxdrv initialization.

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  
    138138    /** Set if verified. */
    139139    bool                fVerified;
     140    /** Whether we've got valid cacheable image bit.s */
     141    bool                fValidBits;
     142    /** The image base address. */
     143    uintptr_t           uImageBase;
    140144} SUPHNTLDRCACHEENTRY;
    141145/** Pointer to a loader cache entry. */
     
    143147DECLHIDDEN(int)  supHardNtLdrCacheOpen(const char *pszName, PSUPHNTLDRCACHEENTRY *ppEntry);
    144148DECLHIDDEN(int)  supHardNtLdrCacheEntryVerify(PSUPHNTLDRCACHEENTRY pEntry, PCRTUTF16 pwszName, PRTERRINFO pErrInfo);
    145 DECLHIDDEN(int)  supHardNtLdrCacheEntryAllocBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, PRTERRINFO pErrInfo);
     149DECLHIDDEN(int)  supHardNtLdrCacheEntryGetBits(PSUPHNTLDRCACHEENTRY pEntry, uint8_t **ppbBits, RTLDRADDR uBaseAddress,
     150                                               PFNRTLDRIMPORT pfnGetImport, void *pvUser, PRTERRINFO pErrInfo);
    146151
    147152
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp

    r52940 r52947  
    810810     */
    811811    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);
    813818    if (RT_FAILURE(rc))
    814819        return rc;
    815     if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION)
    816         rc = RTLdrGetBits(pImage->pCacheEntry->hLdrMod, pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis);
    817     else
    818         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);
    821820
    822821    /* XP SP3 does not set ImageBase to load address. It fixes up the image on load time though. */
     
    862861                return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrInitializeThunk': %Rrc", pImage->pszName, rc);
    863862            aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue;
    864             aSkipAreas[cSkipAreas++].cb = 10;
     863            aSkipAreas[cSkipAreas++].cb = 14;
    865864        }
    866865
     
    15861585
    15871586/**
    1588  * Allocates a image bits buffer for use with RTLdrGetBits.
     1587 * Allocates a image bits buffer and calls RTLdrGetBits on them.
    15891588 *
    15901589 * An assumption here is that there won't ever be concurrent use of the cache.
     
    15951594 * @param   pEntry              The loader cache entry.
    15961595 * @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 */
     1601DECLHIDDEN(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     */
    16011610    if (!pEntry->pbBits)
    16021611    {
     
    16101619            return supHardNtVpSetInfo1(pErrInfo, VERR_SUP_VP_NO_MEMORY, "Failed to allocate %zu bytes for image %s.",
    16111620                                       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    }
    16151652
    16161653    *ppbBits = pEntry->pbBits;
     
    16511688    }
    16521689
    1653     pEntry->pszName   = NULL;
    1654     pEntry->fVerified = false;
     1690    pEntry->pszName    = NULL;
     1691    pEntry->fVerified  = false;
     1692    pEntry->fValidBits = false;
     1693    pEntry->uImageBase = 0;
    16551694}
    16561695
     
    17601799     * Fill in the cache entry.
    17611800     */
    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;
    17681809
    17691810#ifdef IN_SUP_HARDENED_R3
     
    20422083        return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_NTDLL_MAPPING,
    20432084                                   "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)
    20452086        return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_KERNEL32_MAPPING,
    20462087                                   "The process has no KERNEL32.DLL.");
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp

    r52943 r52947  
    240240/** Queue of cached images which needs their imports checked. */
    241241static PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL;
     242
     243/** The windows path to dir \\SystemRoot\\System32 directory (technically
     244 *  this whatever \KnownDlls\KnownDllPath points to). */
     245SUPSYSROOTDIRBUF            g_System32WinPath;
    242246/** @ */
     247
    243248
    244249/** Static error info structure used during init. */
     
    305310# undef SYSCALL
    306311#endif
     312
     313DECLASM(void) supR3HardenedVmProcessInitThunk(void);
    307314
    308315
     
    18071814             * a search on the API level, all VBox calls will have full paths.
    18081815             */
    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);
    18181818            if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
    18191819            {
     
    18241824                return STATUS_NAME_TOO_LONG;
    18251825            }
     1826            memcpy(wszPath, g_System32WinPath.UniStr.Buffer, cwc * sizeof(RTUTF16));
    18261827            wszPath[cwc++] = '\\';
    18271828            memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
     
    18531854         * and the real API can come up with a fitting status code for it.
    18541855         */
    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))
    18581887        {
    18591888            ULONG fAccess = 0;
     
    18811910        {
    18821911            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));
    18841914        }
     1915        RTNtPathFree(&NtPathUniStr, &hRootDir);
    18851916    }
    18861917
     
    36553686
    36563687
    3657 static int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo)
    3658 {
     3688static int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, uintptr_t *puChildNtDllAddr, uintptr_t *puChildExeAddr,
     3689                                       PRTERRINFO pErrInfo)
     3690{
     3691    *puChildNtDllAddr = 0;
     3692    *puChildExeAddr = 0;
     3693
    36593694    /*
    36603695     * Initialize the purifier instance data.
     
    36953730    supR3HardNtPuChFindNtdll(&This);
    36963731
     3732    *puChildNtDllAddr = This.uNtDllAddr;
     3733    *puChildExeAddr   = (uintptr_t)This.Peb.ImageBaseAddress;
     3734
    36973735    /*
    36983736     * Do the work, the last bit we tag along with the process verfication code.
     
    37113749
    37123750/**
     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 */
     3759static 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 */
     3824static 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
     3868static 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/**
    37133966 * Does the actually respawning.
    37143967 *
     
    37263979
    37273980    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    }
    37283995
    37293996    /*
     
    38544121     * supR3HardenedWinInstallHooks.)
    38554122     */
    3856     rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
     4123    rcNt = NtSetInformationThread(hThread, ThreadHideFromDebugger, NULL, 0);
    38574124    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);
    38624127#endif
    38634128
     
    38654130     * Clean up the process.
    38664131     */
    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));
    38684136    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);
    38734138
    38744139    /*
    38754140     * Start the process execution.
    38764141     */
     4142    if (iWhich >= 2)
     4143        supR3HardenedWinInitVmChild(hProcess, hThread, uChildNtDllAddr, uChildExeAddr, hEvtChild, hEvtParent);
     4144
    38774145    ULONG cSuspendCount = 0;
    38784146    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtResumeThread(hThread, &cSuspendCount));
     
    38874155    PROCESS_BASIC_INFORMATION BasicInfo;
    38884156    HANDLE hProcWait;
    3889     ULONG fRights = SYNCHRONIZE;
     4157    ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE;
    38904158    if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
    38914159        fRights |= PROCESS_QUERY_LIMITED_INFORMATION;
    38924160    else
    38934161        fRights |= PROCESS_QUERY_INFORMATION;
     4162    if (iWhich == 2)
     4163        fRights |= PROCESS_VM_READ;
    38944164    rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
    38954165                             NtCurrentProcess(), &hProcWait,
     
    39004170                                 SYNCHRONIZE, 0 /*HandleAttributes*/, 0);
    39014171    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);
    39364174
    39374175    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess));
    39384176    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    }
    39394188
    39404189    /*
     
    39724221    }
    39734222
     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
    39744245    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_0
    3981                 || rcNt == STATUS_WAIT_0 + 1
    3982                 || rcNt == STATUS_ABANDONED_WAIT_0
    3983                 || rcNt == STATUS_ABANDONED_WAIT_0 + 1)
    3984                 break;
    3985             if (   rcNt != STATUS_TIMEOUT
    3986                 && rcNt != STATUS_USER_APC
    3987                 && rcNt != STATUS_ALERTED)
    3988                 supR3HardenedFatal("NtWaitForMultipleObjects returned %#x\n", rcNt);
    3989         }
    39904246        NtClose(hParent);
    3991     }
    3992     else
    3993     {
    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_0
    4001                 || rcNt == STATUS_ABANDONED_WAIT_0)
    4002                 break;
    4003             if (   rcNt != STATUS_TIMEOUT
    4004                 && rcNt != STATUS_USER_APC
    4005                 && rcNt != STATUS_ALERTED)
    4006                 supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
    4007         }
    4008     }
    40094247
    40104248    /*
     
    40124250     */
    40134251    NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
    4014     if (   !NT_SUCCESS(rcNt2)
    4015         || BasicInfo.ExitStatus == STATUS_PENDING)
     4252    if (!NT_SUCCESS(rcNt2))
    40164253        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    }
    40174260
    40184261    NtClose(hProcWait);
     
    43924635DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge)
    43934636{
     4637    /*
     4638     * Init the verifier.
     4639     */
    43944640    RTErrInfoInitStatic(&g_ErrInfoStatic);
    43954641    int rc = supHardenedWinInitImageVerifier(&g_ErrInfoStatic.Core);
     
    43974643        supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rc,
    43984644                              "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);
    43994667
    44004668    if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
     
    44454713                /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */
    44464714                ULONG cPatchCount = 0;
    4447                 NTSTATUS rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
    4448                                                          &cPatchCount, sizeof(cPatchCount), NULL);
     4715                rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
     4716                                                &cPatchCount, sizeof(cPatchCount), NULL);
    44494717                if (NT_SUCCESS(rcNt))
    44504718                    SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n",
     
    52505518
    52515519    /*
    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.
    52535522     */
    52545523    LARGE_INTEGER Timeout;
     
    52995568     * Open the driver.
    53005569     */
     5570    SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n"));
    53015571    supR3HardenedMainOpenDevice();
    53025572    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED;
     
    53065576     * normally when we return.
    53075577     */
     5578    SUP_DPRINTF(("supR3HardenedVmProcessInit: Restoring LdrIntiailizeThunk...\n"));
    53085579    PSUPHNTLDRCACHEENTRY pLdrEntry;
    53095580    int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
     
    53115582        supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
    53125583
     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
    53135589    RTLDRADDR uValue;
    5314     rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, 0, UINT32_MAX, "LdrInitializeThunk", &uValue);
     5590    rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, g_ProcParams.uNtDllAddr, UINT32_MAX, "LdrInitializeThunk", &uValue);
    53155591    if (RT_FAILURE(rc))
    53165592        supR3HardenedFatal("supR3HardenedVmProcessInit: Failed to find LdrInitializeThunk (%Rrc).\n", rc);
    53175593
    5318     PVOID pvLdrInitThunk = (uint8_t *)g_ProcParams.uNtDllAddr + (uint32_t)uValue;
     5594    PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uValue;
    53195595    SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READWRITE));
    5320     memcpy(pvLdrInitThunk, pLdrEntry->pbBits + (uint32_t)uValue, 16);
     5596    memcpy(pvLdrInitThunk, pbBits + ((uintptr_t)uValue - g_ProcParams.uNtDllAddr), 16);
    53215597    SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READ));
    53225598
     5599    SUP_DPRINTF(("supR3HardenedVmProcessInit: Returning to LdrIntiailizeThunk...\n"));
    53235600    return (uintptr_t)pvLdrInitThunk;
    53245601}
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp

    r52943 r52947  
    641641            {
    642642                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*/);
    644645                if (RT_SUCCESS(rc))
    645646                {
    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);
    654650                }
    655651                else
    656652                    SUPHNTIMP_ERROR(20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
    657                                     "%ls: supHardNtLdrCacheEntryAllocBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
     653                                    "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
    658654            }
    659655            else
     
    674670            {
    675671                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*/);
    677674                if (RT_SUCCESS(rc))
    678675                    for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++)
     
    712709        if (RTStrICmp(g_aSupNtImpDlls[iDll].pszName, pszDll) == 0)
    713710        {
     711
    714712            PSUPHNTLDRCACHEENTRY pLdrEntry;
    715713            int rc = supHardNtLdrCacheOpen(g_aSupNtImpDlls[iDll].pszName, &pLdrEntry);
     
    717715            {
    718716                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*/);
    720719                if (RT_SUCCESS(rc))
    721720                {
     
    736735
    737736            /* 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;
    739740        }
    740741
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp

    r52941 r52947  
    3939#include <iprt/assert.h>
    4040#include <iprt/ctype.h>
     41#include <iprt/heap.h>
    4142#include <iprt/string.h>
    4243#include <iprt/initterm.h>
    4344#include <iprt/param.h>
     45#include <iprt/path.h>
    4446#include <iprt/mem.h>
    4547
     
    9799 */
    98100
    99 /** The heap we're using. */
    100 static HANDLE g_hSupR3HardenedHeap = NULL;
     101/** The handle of the heap we're using. */
     102static HANDLE       g_hSupR3HardenedHeap = NULL;
     103/** Number of heaps used during early process init. */
     104static uint32_t     g_cSupR3HardenedEarlyHeaps = 0;
     105/** Early process init heaps. */
     106static 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
     119static 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
     129static 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
     148static 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}
    101212
    102213
     
    108219static HANDLE supR3HardenedHeapInit(void)
    109220{
     221    Assert(g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED);
    110222    HANDLE hHeap = RtlCreateHeap(HEAP_GROWABLE | HEAP_CLASS_PRIVATE, NULL /*HeapBase*/,
    111223                                 0 /*ReserveSize*/, 0 /*CommitSize*/,  NULL /*Lock*/, NULL /*Parameters*/);
     
    129241        RtlCompactHeap(g_hSupR3HardenedHeap, 0 /*dwFlags*/);
    130242    RtlCompactHeap(GetProcessHeap(), 0 /*dwFlags*/);
     243    supR3HardenedEarlyCompact();
    131244}
    132245
     
    155268    HANDLE hHeap = g_hSupR3HardenedHeap;
    156269    if (!hHeap)
     270    {
     271        if (   g_fSupEarlyVmProcessInit
     272            && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
     273            return supR3HardenedEarlyAlloc(cb, false /*fZero*/);
    157274        hHeap = supR3HardenedHeapInit();
     275    }
     276
    158277    void *pv = RtlAllocateHeap(hHeap, 0 /*fFlags*/, cb);
    159278    if (!pv)
     
    167286    HANDLE hHeap = g_hSupR3HardenedHeap;
    168287    if (!hHeap)
     288    {
     289        if (   g_fSupEarlyVmProcessInit
     290            && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
     291            return supR3HardenedEarlyAlloc(cb, true /*fZero*/);
    169292        hHeap = supR3HardenedHeapInit();
     293    }
     294
    170295    void *pv = RtlAllocateHeap(hHeap, HEAP_ZERO_MEMORY, cb);
    171296    if (!pv)
     
    202327        return RTMemAllocZTag(cbNew, pszTag);
    203328
     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. */
    204376    HANDLE hHeap = g_hSupR3HardenedHeap;
    205377    Assert(hHeap != NULL);
    206     void *pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew);
     378    pv = RtlReAllocateHeap(hHeap, 0 /*dwFlags*/, pvOld, cbNew);
    207379    if (!pv)
    208380        supR3HardenedFatal("RtlReAllocateHeap failed to allocate %zu bytes.\n", cbNew);
     
    215387    if (pv)
    216388    {
     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
    217408        HANDLE hHeap = g_hSupR3HardenedHeap;
    218409        Assert(hHeap != NULL);
     
    251442}
    252443
     444
     445
     446/*
     447 * path-win.cpp
     448 */
     449
     450RTDECL(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  
    33SUPHARNT_IMPORT_STDCALL(ExitProcess, 4)
    44SUPHARNT_IMPORT_STDCALL(GetFullPathNameA, 16)
     5SUPHARNT_IMPORT_STDCALL(GetFullPathNameW, 16)
     6SUPHARNT_IMPORT_STDCALL(GetCurrentDirectoryW, 8)
    57SUPHARNT_IMPORT_STDCALL(GetModuleFileNameW, 12)
    68SUPHARNT_IMPORT_STDCALL(GetModuleHandleA, 4)
  • trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h

    r52943 r52947  
    44SUPHARNT_IMPORT_SYSCALL(NtCreateEvent, 20)
    55SUPHARNT_IMPORT_SYSCALL(NtCreateFile, 44)
     6SUPHARNT_IMPORT_SYSCALL(NtCreateSymbolicLinkObject, 16)
    67SUPHARNT_IMPORT_SYSCALL(NtDelayExecution, 8)
    78SUPHARNT_IMPORT_SYSCALL(NtDeviceIoControlFile, 40)
     
    1516SUPHARNT_IMPORT_SYSCALL(NtOpenProcess, 16)
    1617SUPHARNT_IMPORT_SYSCALL(NtOpenProcessToken, 12)
     18SUPHARNT_IMPORT_SYSCALL(NtOpenSymbolicLinkObject, 12)
    1719SUPHARNT_IMPORT_SYSCALL(NtOpenThread, 16)
    1820SUPHARNT_IMPORT_SYSCALL(NtOpenThreadToken, 16)
     
    2729SUPHARNT_IMPORT_SYSCALL(NtQueryObject, 20)
    2830SUPHARNT_IMPORT_SYSCALL(NtQuerySecurityObject, 20)
     31SUPHARNT_IMPORT_SYSCALL(NtQuerySymbolicLinkObject, 12)
    2932SUPHARNT_IMPORT_SYSCALL(NtQuerySystemInformation, 16)
    3033SUPHARNT_IMPORT_SYSCALL(NtQueryTimerResolution, 12)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette