VirtualBox

Changeset 52139 in vbox for trunk/src/VBox/HostDrivers


Ignore:
Timestamp:
Jul 22, 2014 8:19:29 PM (10 years ago)
Author:
vboxsync
Message:

SUP: child-process purification to avoid sysfer.dll.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h

    r52083 r52139  
    417417DECLHIDDEN(void)    supR3HardenedWinVerifyProcess(void);
    418418DECLHIDDEN(void)    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(void);
    419 DECLHIDDEN(bool)    supR3HardenedWinIsReSpawnNeeded(int cArgs, char **papszArgs);
    420 DECLHIDDEN(int)     supR3HardenedWinReSpawn(void);
     419DECLHIDDEN(bool)    supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs);
     420DECLHIDDEN(int)     supR3HardenedWinReSpawn(int iWhich);
    421421DECLHIDDEN(void *)  supR3HardenedWinLoadLibrary(const char *pszName, bool fSystem32Only);
    422422extern RTUTF16      g_wszSupLibHardenedExePath[1024];
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp

    r52089 r52139  
    15421542                              "Effective UID is not root (euid=%d egid=%d uid=%d gid=%d)",
    15431543                              geteuid(), getegid(), g_uid, g_gid);
    1544 #endif
    1545 
    1546     /*
    1547      * Validate the installation.  On Windows we leave the files open so they
    1548      * cannot be tampered with after they've been verified.  We also check
    1549      * install loader hooks and check the process integrity.
    1550      */
    1551 #ifndef RT_OS_WINDOWS
     1544#endif /* SUP_HARDENED_SUID */
     1545
     1546#ifdef RT_OS_WINDOWS
     1547    /*
     1548     * Windows: First respawn. On Windows we will respawn the process twice to establish
     1549     * something we can put some kind of reliable trust in.  The first respawning aims
     1550     * at dropping compatibility layers and process "security" solutions.
     1551     */
     1552    if (   !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
     1553        && supR3HardenedWinIsReSpawnNeeded(1 /*iWhich*/, argc, argv))
     1554    {
     1555        supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV);
     1556        supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
     1557        return supR3HardenedWinReSpawn(1 /*iWhich*/);
     1558    }
     1559
     1560    /*
     1561     * Windows: Initialize the image verification global data so we can verify the
     1562     * signature of the process image and hook the core of the DLL loader API so we
     1563     * can check the signature of all DLLs mapped into the process.
     1564     */
     1565    supR3HardenedWinInit(fFlags);
     1566#endif /* RT_OS_WINDOWS */
     1567
     1568    /*
     1569     * Validate the installation.
     1570     */
    15521571    supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
    1553 #else
    1554     supR3HardenedWinInit(fFlags);
    1555     supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
     1572
     1573    /*
     1574     * The next steps are only taken if we actually need to access the support
     1575     * driver.
     1576     */
    15561577    if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
     1578    {
     1579#ifdef RT_OS_WINDOWS
     1580        /*
     1581         * Windows: Verify the process (repeated by the kernel later.
     1582         */
    15571583        supR3HardenedWinVerifyProcess();
    1558 #endif
     1584
     1585        /*
     1586         * Windows: The second respawn.  This time we make a special arrangement
     1587         * with vboxdrv to monitor access to the new process from its inception.
     1588         */
     1589        if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv))
     1590            return supR3HardenedWinReSpawn(2 /* iWhich*/);
     1591#endif /* RT_OS_WINDOWS */
     1592
     1593        /*
     1594         * Open the vboxdrv device.
     1595         */
     1596        supR3HardenedMainOpenDevice();
     1597    }
    15591598
    15601599#ifdef RT_OS_WINDOWS
    15611600    /*
    1562      * On Windows we'll respawn the process with a special vboxdrv arrangement
    1563      * in place to monitor access to the process for its inception.
    1564      */
    1565     if (   !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
    1566         && supR3HardenedWinIsReSpawnNeeded(argc, argv))
    1567         return supR3HardenedWinReSpawn();
    1568 #endif
    1569 
    1570     /*
    1571      * Open the vboxdrv device.
    1572      */
    1573     if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
    1574         supR3HardenedMainOpenDevice();
    1575 #ifdef RT_OS_WINDOWS
     1601     * Windows: Enable the use of windows APIs to verify images at load time.
     1602     */
    15761603    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation();
    15771604    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY;
    15781605#endif
    1579 
    1580     /*
    1581      * Open the root service connection.
    1582      */
    1583     //if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_SVC))
    1584         //supR3HardenedMainOpenService(&g_SupPreInitData, true /* fFatal */);
    15851606
    15861607#ifdef SUP_HARDENED_SUID
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h

    r52030 r52139  
    100100/** Combined NT version number for XP. */
    101101#define SUP_NT_VER_XP       SUP_MAKE_NT_VER_SIMPLE(5,1)
     102/** Combined NT version number for Windows server 2003 & XP64. */
     103#define SUP_NT_VER_W2K3     SUP_MAKE_NT_VER_SIMPLE(5,2)
    102104/** Combined NT version number for Vista. */
    103105#define SUP_NT_VER_VISTA    SUP_MAKE_NT_VER_SIMPLE(6,0)
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp

    r52092 r52139  
    4545#include <iprt/initterm.h>
    4646#include <iprt/param.h>
     47#include <iprt/zero.h>
    4748
    4849#include "SUPLibInternal.h"
     
    5455*   Defined Constants And Macros                                               *
    5556*******************************************************************************/
    56 /** The first argument of a respawed stub argument.
     57/** The first argument of a respawed stub when respawned for the first time.
    5758 * This just needs to be unique enough to avoid most confusion with real
    5859 * executable names,  there are other checks in place to make sure we've respanwed. */
    59 #define SUPR3_RESPAWN_ARG0  "81954AF5-4D2F-31EB-A142-B7AF187A1C41-suplib-2ndchild"
     60#define SUPR3_RESPAWN_1_ARG0  "81954AF5-4D2F-31EB-A142-B7AF187A1C41-suplib-2ndchild"
     61
     62/** The first argument of a respawed stub when respawned for the second time.
     63 * This just needs to be unique enough to avoid most confusion with real
     64 * executable names,  there are other checks in place to make sure we've respanwed. */
     65#define SUPR3_RESPAWN_2_ARG0  "81954AF5-4D2F-31EB-A142-B7AF187A1C41-suplib-3rdchild"
    6066
    6167/** Unconditional assertion. */
     
    13621368 *
    13631369 * @returns Pointer to a command line string (heap).
    1364  */
    1365 static PRTUTF16 supR3HardenedWinConstructCmdLine(void)
    1366 {
     1370 * @param   pUniStr         Unicode string structure to initialize to the
     1371 *                          command line. Optional.
     1372 * @param   iWhich          Which respawn we're to check for, 1 being the first
     1373 *                          one, and 2 the second and final.
     1374 */
     1375static PRTUTF16 supR3HardenedWinConstructCmdLine(PUNICODE_STRING pString, int iWhich)
     1376{
     1377    SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2);
     1378
    13671379    /*
    13681380     * Get the command line and skip the executable name.
     
    14041416     * Allocate a new buffer.
    14051417     */
     1418    AssertCompile(sizeof(SUPR3_RESPAWN_1_ARG0) == sizeof(SUPR3_RESPAWN_2_ARG0));
    14061419    size_t cwcArgs    = suplibHardenedWStrLen(pwszArgs);
    1407     size_t cwcCmdLine = (sizeof(SUPR3_RESPAWN_ARG0) - 1) / sizeof(SUPR3_RESPAWN_ARG0[0]) /* Respawn exe name. */
     1420    size_t cwcCmdLine = (sizeof(SUPR3_RESPAWN_1_ARG0) - 1) / sizeof(SUPR3_RESPAWN_1_ARG0[0]) /* Respawn exe name. */
    14081421                      + !!cwcArgs + cwcArgs; /* if arguments present, add space + arguments. */
     1422    if (cwcCmdLine * sizeof(WCHAR) >= 0xfff0)
     1423        supR3HardenedFatalMsg("supR3HardenedWinConstructCmdLine", kSupInitOp_Misc, VERR_OUT_OF_RANGE,
     1424                              "Command line is too long (%u chars)!", cwcCmdLine);
     1425
    14091426    PRTUTF16 pwszCmdLine = (PRTUTF16)HeapAlloc(GetProcessHeap(), 0 /* dwFlags*/, (cwcCmdLine + 1) * sizeof(RTUTF16));
    14101427    SUPR3HARDENED_ASSERT(pwszCmdLine != NULL);
     
    14141431     */
    14151432    PRTUTF16 pwszDst = pwszCmdLine;
    1416     for (const char *pszSrc = SUPR3_RESPAWN_ARG0; *pszSrc; pszSrc++)
     1433    for (const char *pszSrc = iWhich == 1 ? SUPR3_RESPAWN_1_ARG0 : SUPR3_RESPAWN_2_ARG0; *pszSrc; pszSrc++)
    14171434        *pwszDst++ = *pszSrc;
    14181435
     
    14271444    SUPR3HARDENED_ASSERT(pwszDst - pwszCmdLine == cwcCmdLine);
    14281445
     1446    if (pString)
     1447    {
     1448        pString->Buffer = pwszCmdLine;
     1449        pString->Length = (USHORT)(cwcCmdLine * sizeof(WCHAR));
     1450        pString->MaximumLength = pString->Length + sizeof(WCHAR);
     1451    }
    14291452    return pwszCmdLine;
    14301453}
    14311454
    14321455
     1456
     1457/*
     1458 * Child-Process Purification - release it from dubious influences.
     1459 * 
     1460 * AV software and other things injecting themselves into the embryonic
     1461 * and budding process to intercept API calls and what not.  Unfortunately
     1462 * this is also the behavior of viruses, malware and other unfriendly
     1463 * software, so we won't stand for it.  AV software can scan our image
     1464 * as they are loaded via kernel hooks, that's sufficient.  No need for
     1465 * matching half of NTDLL or messing with the import table of the
     1466 * process executable.
     1467 */
     1468
     1469typedef struct SUPR3HARDNTPUCH
     1470{
     1471    /** Process handle. */
     1472    HANDLE                      hProcess;
     1473    /** Primary thread handle. */
     1474    HANDLE                      hThread;
     1475    /** Error buffer. */
     1476    PRTERRINFO                  pErrInfo;
     1477    /** The basic process info. */
     1478    PROCESS_BASIC_INFORMATION   BasicInfo;
     1479    /** The probable size of the PEB. */
     1480    size_t                      cbPeb;
     1481    /** The pristine process environment block. */
     1482    PEB                         Peb;
     1483} SUPR3HARDNTPUCH;
     1484typedef SUPR3HARDNTPUCH *PSUPR3HARDNTPUCH;
     1485
     1486
     1487static int supR3HardNtPuChScrewUpPebForInitialImageEvents(PSUPR3HARDNTPUCH pThis)
     1488{
     1489    /*
     1490     * Not sure if any of the cracker software uses the PEB at this point, but
     1491     * just in case they do make some of the PEB fields a little less useful.
     1492     */
     1493    PEB Peb = pThis->Peb;
     1494
     1495    /* Make ImageBaseAddress useless. */
     1496    Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress ^ UINT32_C(0x5f139000));
     1497#ifdef RT_ARCH_AMD64
     1498    Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress | UINT64_C(0x0313000000000000));
     1499#endif
     1500
     1501    /*
     1502     * Write the PEB.
     1503     */
     1504    SIZE_T cbActualMem = pThis->cbPeb;
     1505    NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
     1506    if (!NT_SUCCESS(rcNt))
     1507        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
     1508    return VINF_SUCCESS;
     1509}
     1510
     1511
     1512/**
     1513 * Trigger the initial image events without actually initializing the process.
     1514 *
     1515 * This is a trick to force sysplant.sys to call its hand by tripping the image
     1516 * loaded event for the main executable and ntdll images.  This will happen when
     1517 * the first thread in a process starts executing in PspUserThreadStartup.  We
     1518 * create a second thread that quits immediately by means of temporarily
     1519 * replacing ntdll!LdrInitializeThunk by a NtTerminateThread call.
     1520 * (LdrInitializeThunk is called by way of an APC queued the thread is created,
     1521 * thus NtSetContextThread is of no use.)
     1522 *
     1523 * @returns VBox status code.
     1524 * @param   pThis               The child cleanup
     1525 * @param   pErrInfo            For extended error information.
     1526 */
     1527static int supR3HardNtPuChTriggerInitialImageEvents(PSUPR3HARDNTPUCH pThis)
     1528{
     1529    /** @todo stop assuming NTDLL doesn't move.  */
     1530    PVOID pvLdrInitThunk      = (PVOID)(uintptr_t)LdrInitializeThunk;
     1531    PVOID pvNtTerminateThread = (PVOID)(uintptr_t)NtTerminateThread;
     1532
     1533    /*
     1534     * Back up the thunk code.
     1535     */
     1536    uint8_t abBackup[16];
     1537    SIZE_T  cbIgnored;
     1538    NTSTATUS rcNt = NtReadVirtualMemory(pThis->hProcess, pvLdrInitThunk, abBackup, sizeof(abBackup), &cbIgnored);
     1539    if (!NT_SUCCESS(rcNt))
     1540        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1541                             "NtReadVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
     1542
     1543    /*
     1544     * Cook up replacement code that calls NtTerminateThread.
     1545     */
     1546    uint8_t abReplacement[sizeof(abBackup)] ;
     1547    memcpy(abReplacement, abBackup, sizeof(abReplacement));
     1548
     1549#ifdef RT_ARCH_AMD64
     1550    abReplacement[0] = 0x31;    /* xor ecx, ecx */
     1551    abReplacement[1] = 0xc9;
     1552    abReplacement[2] = 0x31;    /* xor edx, edx */
     1553    abReplacement[3] = 0xd2;
     1554    abReplacement[4] = 0xe8;    /* call near NtTerminateThread */
     1555    *(int32_t *)&abReplacement[5] = (int32_t)((intptr_t)pvNtTerminateThread - ((intptr_t)pvLdrInitThunk + 9));
     1556    abReplacement[9] = 0xcc;    /* int3 */
     1557#elif defined(RT_ARCH_X86)
     1558    abReplacement[0] = 0x6a;    /* push 0 */
     1559    abReplacement[1] = 0x00;
     1560    abReplacement[2] = 0x6a;    /* push 0 */
     1561    abReplacement[3] = 0x00;
     1562    abReplacement[4] = 0xe8;    /* call near NtTerminateThread */
     1563    *(int32_t *)&abReplacement[5] = (int32_t)((intptr_t)pvNtTerminateThread - ((intptr_t)pvLdrInitThunk + 9));
     1564    abReplacement[9] = 0xcc;    /* int3 */
     1565#else
     1566# error "Unsupported arch."
     1567#endif
     1568
     1569    /*
     1570     * Install the replacment code.
     1571     */
     1572    PVOID  pvProt   = pvLdrInitThunk;
     1573    SIZE_T cbProt   = 16;
     1574    ULONG  fOldProt = 0;
     1575    rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
     1576    if (!NT_SUCCESS(rcNt))
     1577        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1578                             "NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
     1579
     1580    rcNt = NtWriteVirtualMemory(pThis->hProcess, pvLdrInitThunk, abReplacement, sizeof(abReplacement), &cbIgnored);
     1581    if (!NT_SUCCESS(rcNt))
     1582        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1583                             "NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
     1584
     1585    /*
     1586     * Create the thread, waiting 10 seconds for it to complete.
     1587     */
     1588    CLIENT_ID Thread2Id;
     1589    HANDLE hThread2;
     1590    rcNt = RtlCreateUserThread(pThis->hProcess,
     1591                               NULL /* SecurityAttribs */,
     1592                               FALSE /* CreateSuspended */,
     1593                               0 /* ZeroBits */,
     1594                               0 /* MaximumStackSize */,
     1595                               0 /* CommittedStackSize */,
     1596                               (PFNRT)2 /* StartAddress */,
     1597                               NULL /*Parameter*/ ,
     1598                               &hThread2,
     1599                               &Thread2Id);
     1600    if (NT_SUCCESS(rcNt))
     1601    {
     1602        LARGE_INTEGER Timeout;
     1603        Timeout.QuadPart = -10 * 10000000; /* 10 seconds */
     1604        NtWaitForSingleObject(hThread2, FALSE /* Alertable */, &Timeout);
     1605        NtTerminateThread(hThread2, DBG_TERMINATE_THREAD);
     1606        NtClose(hThread2);
     1607    }
     1608
     1609    /*
     1610     * Restore the original thunk code and protection.
     1611     */
     1612    rcNt = NtWriteVirtualMemory(pThis->hProcess, pvLdrInitThunk, abBackup, sizeof(abBackup), &cbIgnored);
     1613    if (!NT_SUCCESS(rcNt))
     1614        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1615                             "NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt);
     1616
     1617    pvProt   = pvLdrInitThunk;
     1618    cbProt   = 16;
     1619    rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
     1620    if (!NT_SUCCESS(rcNt))
     1621        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1622                             "NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt);
     1623
     1624    return VINF_SUCCESS;
     1625}
     1626
     1627#if 0
     1628static int supR3HardenedWinScratchChildMemory(HANDLE hProcess, void *pv, size_t cb, const char *pszWhat, PRTERRINFO pErrInfo)
     1629{
     1630    SUP_DPRINTF(("supR3HardenedWinScratchChildMemory: %p %#x\n", pv, cb));
     1631
     1632    PVOID  pvCopy = pv;
     1633    SIZE_T cbCopy = cb;
     1634    NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);
     1635    if (!NT_SUCCESS(rcNt))
     1636        return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtProtectVirtualMemory/%s (%p LB %#zx) failed: %#x",
     1637                             pszWhat, pv, cb, rcNt);
     1638    return VINF_SUCCESS;
     1639}
     1640#endif
     1641
     1642
     1643static int supR3HardNtPuChSanitizePeb(PSUPR3HARDNTPUCH pThis)
     1644{
     1645    /*
     1646     * Make a copy of the pre-execution PEB.
     1647     */
     1648    PEB Peb = pThis->Peb;
     1649
     1650#if 0
     1651    /*
     1652     * There should not be any activation context, so if there is, we scratch the memory associated with it.
     1653     */
     1654    int rc = 0;
     1655    if (RT_SUCCESS(rc) && Peb.pShimData && !((uintptr_t)Peb.pShimData & PAGE_OFFSET_MASK))
     1656        rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.pShimData, PAGE_SIZE, "pShimData", pErrInfo);
     1657    if (RT_SUCCESS(rc) && Peb.ActivationContextData && !((uintptr_t)Peb.ActivationContextData & PAGE_OFFSET_MASK))
     1658        rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ActivationContextData, PAGE_SIZE, "ActivationContextData", pErrInfo);
     1659    if (RT_SUCCESS(rc) && Peb.ProcessAssemblyStorageMap && !((uintptr_t)Peb.ProcessAssemblyStorageMap & PAGE_OFFSET_MASK))
     1660        rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "ProcessAssemblyStorageMap", pErrInfo);
     1661    if (RT_SUCCESS(rc) && Peb.SystemDefaultActivationContextData && !((uintptr_t)Peb.SystemDefaultActivationContextData & PAGE_OFFSET_MASK))
     1662        rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "SystemDefaultActivationContextData", pErrInfo);
     1663    if (RT_SUCCESS(rc) && Peb.SystemAssemblyStorageMap && !((uintptr_t)Peb.SystemAssemblyStorageMap & PAGE_OFFSET_MASK))
     1664        rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.SystemAssemblyStorageMap, PAGE_SIZE, "SystemAssemblyStorageMap", pErrInfo);
     1665    if (RT_FAILURE(rc))
     1666        return rc;
     1667#endif
     1668
     1669    /*
     1670     * Clear compatibility and activation related fields.
     1671     */
     1672    Peb.AppCompatFlags.QuadPart             = 0;
     1673    Peb.AppCompatFlagsUser.QuadPart         = 0;
     1674    Peb.pShimData                           = NULL;
     1675    Peb.AppCompatInfo                       = NULL;
     1676#if 0
     1677    Peb.ActivationContextData               = NULL;
     1678    Peb.ProcessAssemblyStorageMap           = NULL;
     1679    Peb.SystemDefaultActivationContextData  = NULL;
     1680    Peb.SystemAssemblyStorageMap            = NULL;
     1681    /*Peb.Diff0.W6.IsProtectedProcess = 1;*/
     1682#endif
     1683
     1684    /*
     1685     * Write back the PEB.
     1686     */
     1687    SIZE_T cbActualMem = pThis->cbPeb;
     1688    NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
     1689    if (!NT_SUCCESS(rcNt))
     1690        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
     1691
     1692    return VINF_SUCCESS;
     1693}
     1694
     1695
     1696DECLINLINE(PIMAGE_NT_HEADERS) supR3HardNtPuChFindNtHeaders(uint8_t *pbBuf, size_t cbBuf)
     1697{
     1698    PIMAGE_DOS_HEADER pMzHdr = (PIMAGE_DOS_HEADER)pbBuf;
     1699    if (cbBuf >= sizeof(*pMzHdr))
     1700    {
     1701        if (pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)
     1702        {
     1703            if (pMzHdr->e_lfanew >= cbBuf)
     1704                return NULL;
     1705            cbBuf -= pMzHdr->e_lfanew;
     1706            pbBuf += pMzHdr->e_lfanew;
     1707        }
     1708    }
     1709
     1710    PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)pbBuf;
     1711    if (cbBuf >= sizeof(IMAGE_NT_HEADERS))
     1712    {
     1713        if (pNtHdrs->Signature == IMAGE_NT_SIGNATURE)
     1714            return pNtHdrs;
     1715    }
     1716    return NULL;
     1717}
     1718
     1719
     1720#ifdef DEBUG
     1721static uint32_t supR3HardNtPuChFindFirstDiff(void const *pvBuf1, void const *pvBuf2, size_t cbBuf)
     1722{
     1723    uint8_t const *pabBuf1 = (uint8_t const *)pvBuf1;
     1724    uint8_t const *pabBuf2 = (uint8_t const *)pvBuf2;
     1725    uint32_t off = 0;
     1726    while (off < cbBuf && pabBuf1[off] == pabBuf2[off])
     1727        off++;
     1728    return off;
     1729}
     1730#endif
     1731
     1732
     1733static NTSTATUS supR3HardNtPuChRestoreImageBits(PSUPR3HARDNTPUCH pThis, PVOID pvChildAddr,
     1734                                                void const *pvFileBits, size_t cbToRestore, uint32_t fCorrectProtection)
     1735{
     1736    PVOID  pvProt   = pvChildAddr;
     1737    SIZE_T cbProt   = cbToRestore;
     1738    ULONG  fOldProt = 0;
     1739    NTSTATUS rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_READWRITE, &fOldProt);
     1740    if (NT_SUCCESS(rcNt))
     1741    {
     1742        SIZE_T cbIgnored;
     1743        rcNt = NtWriteVirtualMemory(pThis->hProcess, pvChildAddr, pvFileBits, cbToRestore, &cbIgnored);
     1744
     1745        pvProt = pvChildAddr;
     1746        cbProt = cbToRestore;
     1747        NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fCorrectProtection, &fOldProt);
     1748        if (NT_SUCCESS(rcNt))
     1749            rcNt = rcNt2;
     1750    }
     1751    return rcNt;
     1752}
     1753
     1754
     1755static int supR3HardNtPuChSanitizeImage(PSUPR3HARDNTPUCH pThis, PMEMORY_BASIC_INFORMATION pMemInfo)
     1756{
     1757    /*
     1758     * Get the image name.
     1759     */
     1760    union
     1761    {
     1762        UNICODE_STRING UniStr;
     1763        uint8_t abPadding[4096];
     1764    } uBuf;
     1765    SIZE_T cbActual;
     1766    NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
     1767                                         pMemInfo->BaseAddress,
     1768                                         MemorySectionName,
     1769                                         &uBuf,
     1770                                         sizeof(uBuf) - sizeof(WCHAR),
     1771                                         &cbActual);
     1772    if (!NT_SUCCESS(rcNt))
     1773        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1774                             "NtQueryVirtualMemory/MemorySectionName failed for %p: %#x", pMemInfo->BaseAddress, rcNt);
     1775    uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
     1776
     1777    /*
     1778     * Open the file.
     1779     */
     1780    HANDLE              hFile = RTNT_INVALID_HANDLE_VALUE;
     1781    IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     1782
     1783    OBJECT_ATTRIBUTES ObjAttr;
     1784    InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
     1785
     1786    rcNt = NtCreateFile(&hFile,
     1787                        FILE_READ_DATA | SYNCHRONIZE,
     1788                        &ObjAttr,
     1789                        &Ios,
     1790                        NULL /* Allocation Size*/,
     1791                        FILE_ATTRIBUTE_NORMAL,
     1792                        FILE_SHARE_READ,
     1793                        FILE_OPEN,
     1794                        FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
     1795                        NULL /*EaBuffer*/,
     1796                        0 /*EaLength*/);
     1797    if (NT_SUCCESS(rcNt))
     1798        rcNt = Ios.Status;
     1799    if (!NT_SUCCESS(rcNt))
     1800        return RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),
     1801                             "NtCreateFile returned %#x opening '%ls'.", rcNt, uBuf.UniStr.Buffer);
     1802
     1803    /*
     1804     * Read the headers, ASSUMES the stub isn't pushing the optional header out
     1805     * of a 4KB buffer.  Also ASSUMEs that the file is more than 4KB in size.
     1806     */
     1807    int             rc;
     1808    uint8_t         abFile[_4K];
     1809    LARGE_INTEGER   off;
     1810    off.QuadPart = 0;
     1811    rcNt = NtReadFile(hFile, NULL, NULL, NULL, &Ios, abFile, sizeof(abFile), &off, NULL);
     1812    if (NT_SUCCESS(rcNt))
     1813        rcNt = Ios.Status;
     1814    if (NT_SUCCESS(rcNt))
     1815    {
     1816        PIMAGE_NT_HEADERS pNtFile = supR3HardNtPuChFindNtHeaders(abFile, sizeof(abFile));
     1817        if (pNtFile)
     1818        {
     1819            /*
     1820             * Read the first 4KB of the process memory.
     1821             */
     1822            uint8_t abProc[_4K];
     1823            SIZE_T cbActualMem;
     1824            rcNt = NtReadVirtualMemory(pThis->hProcess, pMemInfo->BaseAddress, abProc, sizeof(abProc), &cbActualMem);
     1825            if (NT_SUCCESS(rcNt))
     1826            {
     1827                PIMAGE_NT_HEADERS pNtProc = (PIMAGE_NT_HEADERS)&abProc[(uint8_t *)pNtFile - &abFile[0]];
     1828                pNtFile->OptionalHeader.ImageBase = pNtProc->OptionalHeader.ImageBase;
     1829
     1830                size_t cbCompare = RT_MIN(pNtFile->OptionalHeader.SizeOfHeaders, sizeof(abProc));
     1831                if (cbCompare < sizeof(abFile))
     1832                    RT_BZERO(&abFile[cbCompare], sizeof(abFile) - cbCompare);
     1833                if (!memcmp(abFile, abProc, cbCompare))
     1834                    rc = VINF_SUCCESS;
     1835                else
     1836                {
     1837                    SUP_DPRINTF(("supR3HardNtPuChSanitizeImage: Header diff @%#x in ('%ls')\n",
     1838                                 supR3HardNtPuChFindFirstDiff(abFile, abProc, sizeof(abProc)), uBuf.UniStr.Buffer));
     1839                    rc = supR3HardNtPuChRestoreImageBits(pThis, pMemInfo->BaseAddress, abFile, cbCompare, PAGE_READONLY);
     1840                }
     1841            }
     1842            else
     1843                rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),
     1844                                   "NtReadVirtualMemory returned %#x read 4KB at %p ('%ls').", rcNt,
     1845                                   pMemInfo->BaseAddress, uBuf.UniStr.Buffer);
     1846        }
     1847        else
     1848            rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),
     1849                               "No PE header in the first 4KB of '%ls'.", rcNt, uBuf.UniStr.Buffer);
     1850    }
     1851    else
     1852        rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),
     1853                           "NtReadFile returned %#x reading the header of '%ls'.", rcNt, uBuf.UniStr.Buffer);
     1854
     1855    NtClose(hFile);
     1856
     1857    return rc;
     1858}
     1859
     1860
     1861static int supR3HardNtPuChSanitizeMemory(PSUPR3HARDNTPUCH pThis)
     1862{
     1863    /*
     1864     * Find and remove/disable any unwanted executable memory.
     1865     */
     1866    uint32_t    cXpExceptions = 0;
     1867    uintptr_t   cbAdvance = 0;
     1868    uintptr_t   uPtrWhere = 0;
     1869    for (uint32_t i = 0; i < 1024; i++)
     1870    {
     1871        SIZE_T                      cbActual = 0;
     1872        MEMORY_BASIC_INFORMATION    MemInfo  = { 0, 0, 0, 0, 0, 0, 0 };
     1873        NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
     1874                                             (void const *)uPtrWhere,
     1875                                             MemoryBasicInformation,
     1876                                             &MemInfo,
     1877                                             sizeof(MemInfo),
     1878                                             &cbActual);
     1879        if (!NT_SUCCESS(rcNt))
     1880            break;
     1881        //SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: %p (%p LB %#zx): type=%#010x prot=%#06x state=%#07x aprot=%#06x abase=%p\n",
     1882        //             uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize,MemInfo.Type,
     1883        //             MemInfo.Protect, MemInfo.State, MemInfo.AllocationBase, MemInfo.AllocationProtect));
     1884
     1885        if (   MemInfo.Type == SEC_IMAGE
     1886            || MemInfo.Type == SEC_PROTECTED_IMAGE
     1887            || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))
     1888        {
     1889            /*
     1890             * Restore modified parts of the image from file.
     1891             */
     1892            if (MemInfo.BaseAddress == MemInfo.AllocationBase)
     1893            {
     1894                int rc = supR3HardNtPuChSanitizeImage(pThis, &MemInfo);
     1895                if (RT_FAILURE(rc))
     1896                    return rc;
     1897            }
     1898        }
     1899        /*
     1900         * Executable memory outside an image is evil by definition.
     1901         */
     1902        else if (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))
     1903        {
     1904            /*
     1905             * XP, W2K3 exception: Ignore the CSRSS read-only region as best we can.
     1906             */
     1907            if (   (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))
     1908                   == PAGE_EXECUTE_READ
     1909                && cXpExceptions == 0
     1910                && (uintptr_t)MemInfo.BaseAddress >= UINT32_C(0x78000000)
     1911                /* && MemInfo.BaseAddress == pPeb->ReadOnlySharedMemoryBase */
     1912                && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 0) )
     1913                cXpExceptions++;
     1914#ifndef VBOX_PERMIT_VISUAL_STUDIO_PROFILING
     1915            else
     1916            {
     1917                /*
     1918                 * Free any private executable memory (sysplant.sys allocates executable memory).
     1919                 */
     1920                if (MemInfo.Type == MEM_PRIVATE)
     1921                {
     1922                    SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: Freeing exec mem at %p (%p LB %#zx)\n",
     1923                                 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize));
     1924                    PVOID   pvFree = MemInfo.BaseAddress;
     1925                    SIZE_T  cbFree = MemInfo.RegionSize;
     1926                    rcNt = NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE);
     1927                    if (!NT_SUCCESS(rcNt))
     1928                        return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1929                                             "NtFreeVirtualMemory (%p LB %#zx) failed: %#x",
     1930                                             MemInfo.BaseAddress, MemInfo.RegionSize, rcNt);
     1931                }
     1932                /*
     1933                 * Unmap mapped memory, failing that, drop exec privileges.
     1934                 */
     1935                else if (MemInfo.Type == MEM_MAPPED)
     1936                {
     1937                    SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: Unmapping exec mem at %p (%p/%p LB %#zx)\n",
     1938                                 uPtrWhere, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize));
     1939                    rcNt = NtUnmapViewOfSection(pThis->hProcess, MemInfo.AllocationBase);
     1940                    if (!NT_SUCCESS(rcNt))
     1941                    {
     1942                        PVOID  pvCopy = MemInfo.BaseAddress;
     1943                        SIZE_T cbCopy = MemInfo.RegionSize;
     1944                        NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);
     1945                        if (!NT_SUCCESS(rcNt2))
     1946                            rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL);
     1947                        if (!NT_SUCCESS(rcNt2))
     1948                            return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1949                                                 "NtUnmapViewOfSection (%p/%p LB %#zx) failed: %#x (%#x)",
     1950                                                 MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize, rcNt, rcNt2);
     1951                    }
     1952                }
     1953                else
     1954                    return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,
     1955                                         "Unknown executable memory type %#x at %p/%p LB %#zx",
     1956                                         MemInfo.Type, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize);
     1957            }
     1958#endif
     1959        }
     1960
     1961        /*
     1962         * Advance.
     1963         */
     1964        cbAdvance = MemInfo.RegionSize;
     1965        if (uPtrWhere + cbAdvance <= uPtrWhere)
     1966            break;
     1967        uPtrWhere += MemInfo.RegionSize;
     1968    }
     1969
     1970    return VINF_SUCCESS;
     1971}
     1972
     1973
     1974static int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo)
     1975{
     1976    /*
     1977     * Initialize the purifier instance data.
     1978     */
     1979    SUPR3HARDNTPUCH This;
     1980    This.hProcess = hProcess;
     1981    This.hThread  = hThread;
     1982    This.pErrInfo = pErrInfo;
     1983
     1984    ULONG cbActual = 0;
     1985    NTSTATUS rcNt = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
     1986                                              &This.BasicInfo, sizeof(This.BasicInfo), &cbActual);
     1987    if (!NT_SUCCESS(rcNt))
     1988        return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
     1989                             "NtQueryInformationProcess/ProcessBasicInformation failed: %#x", rcNt);
     1990
     1991    if (g_uNtVerCombined < SUP_NT_VER_W2K3)
     1992        This.cbPeb = PEB_SIZE_W51;
     1993    else if (g_uNtVerCombined < SUP_NT_VER_VISTA)
     1994        This.cbPeb = PEB_SIZE_W52;
     1995    else if (g_uNtVerCombined < SUP_NT_VER_W70)
     1996        This.cbPeb = PEB_SIZE_W6;
     1997    else if (g_uNtVerCombined < SUP_NT_VER_W80)
     1998        This.cbPeb = PEB_SIZE_W7;
     1999    else if (g_uNtVerCombined < SUP_NT_VER_W81)
     2000        This.cbPeb = PEB_SIZE_W80;
     2001    else
     2002        This.cbPeb = PEB_SIZE_W81;
     2003
     2004    SIZE_T cbActualMem;
     2005    RT_ZERO(This.Peb);
     2006    rcNt = NtReadVirtualMemory(hProcess, This.BasicInfo.PebBaseAddress, &This.Peb, sizeof(This.Peb), &cbActualMem);
     2007    if (!NT_SUCCESS(rcNt))
     2008        return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtReadVirtualMemory/Peb failed: %#x", rcNt);
     2009
     2010    /*
     2011     * Do the work.
     2012     */
     2013    int rc = supR3HardNtPuChScrewUpPebForInitialImageEvents(&This);
     2014    if (RT_SUCCESS(rc))
     2015        rc = supR3HardNtPuChTriggerInitialImageEvents(&This);
     2016    if (RT_SUCCESS(rc))
     2017        rc = supR3HardNtPuChSanitizePeb(&This);
     2018    if (RT_SUCCESS(rc))
     2019        rc = supR3HardNtPuChSanitizeMemory(&This);
     2020
     2021    return rc;
     2022}
     2023
     2024
    14332025/**
    14342026 * Does the actually respawning.
     
    14362028 * @returns Exit code (if we get that far).
    14372029 */
    1438 static int supR3HardenedWinDoReSpawn(void)
     2030static int supR3HardenedWinDoReSpawn(int iWhich)
    14392031{
    14402032    SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
    14412033
    14422034    /*
     2035     * Set up security descriptors.
     2036     */
     2037    SECURITY_ATTRIBUTES ProcessSecAttrs;
     2038    MYSECURITYCLEANUP   ProcessSecAttrsCleanup;
     2039    supR3HardenedInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
     2040
     2041    SECURITY_ATTRIBUTES ThreadSecAttrs;
     2042    MYSECURITYCLEANUP   ThreadSecAttrsCleanup;
     2043    supR3HardenedInitSecAttrs(&ThreadSecAttrs, &ThreadSecAttrsCleanup, false /*fProcess*/);
     2044
     2045#if 1
     2046    /*
    14432047     * Configure the startup info and creation flags.
    14442048     */
    1445     DWORD dwCreationFlags = 0;
     2049    DWORD dwCreationFlags = CREATE_SUSPENDED;
    14462050
    14472051    STARTUPINFOEXW SiEx;
     
    14622066
    14632067    /*
    1464      * Set up security descriptors.
    1465      */
    1466     SECURITY_ATTRIBUTES ProcessSecAttrs;
    1467     MYSECURITYCLEANUP   ProcessSecAttrsCleanup;
    1468     supR3HardenedInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
    1469 
    1470     SECURITY_ATTRIBUTES ThreadSecAttrs;
    1471     MYSECURITYCLEANUP   ThreadSecAttrsCleanup;
    1472     supR3HardenedInitSecAttrs(&ThreadSecAttrs, &ThreadSecAttrsCleanup, false /*fProcess*/);
    1473 
    1474     /*
    14752068     * Construct the command line and launch the process.
    14762069     */
    1477     PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine();
    1478 
    1479     PROCESS_INFORMATION ProcessInfo;
     2070    PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine(NULL, iWhich);
     2071
     2072    PROCESS_INFORMATION ProcessInfoW32;
    14802073    if (!CreateProcessW(g_wszSupLibHardenedExePath,
    14812074                        pwszCmdLine,
     
    14872080                        NULL /*pwszCurDir*/,
    14882081                        &SiEx.StartupInfo,
    1489                         &ProcessInfo))
     2082                        &ProcessInfoW32))
    14902083        supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
    14912084                              "Error relaunching VirtualBox VM process: %u\n"
     
    14932086                              GetLastError(), pwszCmdLine);
    14942087
     2088    HANDLE hProcess = ProcessInfoW32.hProcess;
     2089    HANDLE hThread  = ProcessInfoW32.hThread;
     2090
     2091#else
     2092
     2093    /*
     2094     * Construct the process parameters.
     2095     */
     2096    UNICODE_STRING W32ImageName;
     2097    W32ImageName.Buffer = g_wszSupLibHardenedExePath; /* Yes the windows name for the process parameters. */
     2098    W32ImageName.Length = (USHORT)RTUtf16Len(g_wszSupLibHardenedExePath) * sizeof(WCHAR);
     2099    W32ImageName.MaximumLength = W32ImageName.Length + sizeof(WCHAR);
     2100
     2101    UNICODE_STRING CmdLine;
     2102    supR3HardenedWinConstructCmdLine(&CmdLine, iWhich);
     2103
     2104    PRTL_USER_PROCESS_PARAMETERS pProcParams = NULL;
     2105    SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateProcessParameters(&pProcParams,
     2106                                                               &W32ImageName,
     2107                                                               NULL /* DllPath - inherit from this process */,
     2108                                                               NULL /* CurrentDirectory - inherit from this process */,
     2109                                                               &CmdLine,
     2110                                                               NULL /* Environment - inherit from this process */,
     2111                                                               NULL /* WindowsTitle - none */,
     2112                                                               NULL /* DesktopTitle - none. */,
     2113                                                               NULL /* ShellInfo - none. */,
     2114                                                               NULL /* RuntimeInfo - none (byte array for MSVCRT file info) */)
     2115                                    );
     2116
     2117    /** @todo this doesn't work. :-( */
     2118    PPEB                            pPeb              = NtCurrentPeb();
     2119    PRTL_USER_PROCESS_PARAMETERS    pParentProcParams = pPeb->ProcessParameters;
     2120    pProcParams->ConsoleHandle  = pParentProcParams->ConsoleHandle;
     2121    pProcParams->ConsoleFlags   = pParentProcParams->ConsoleFlags;
     2122    pProcParams->StandardInput  = pParentProcParams->StandardInput;
     2123    pProcParams->StandardOutput = pParentProcParams->StandardOutput;
     2124    pProcParams->StandardError  = pParentProcParams->StandardError;
     2125
     2126    RTL_USER_PROCESS_INFORMATION ProcessInfoNt = { sizeof(ProcessInfoNt) };
     2127    NTSTATUS rcNt = RtlCreateUserProcess(&g_SupLibHardenedExeNtPath.UniStr,
     2128                                         OBJ_INHERIT | OBJ_CASE_INSENSITIVE /*Attributes*/,
     2129                                         pProcParams,
     2130                                         NULL, //&ProcessSecAttrs,
     2131                                         NULL, //&ThreadSecAttrs,
     2132                                         NtCurrentProcess() /* ParentProcess */,
     2133                                         FALSE /*fInheritHandles*/,
     2134                                         NULL /* DebugPort */,
     2135                                         NULL /* ExceptionPort */,
     2136                                         &ProcessInfoNt);
     2137    if (!NT_SUCCESS(rcNt))
     2138        supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
     2139                              "Error relaunching VirtualBox VM process: %#x\n"
     2140                              "Command line: '%ls'",
     2141                              rcNt, CmdLine.Buffer);
     2142
     2143    RtlDestroyProcessParameters(pProcParams);
     2144
     2145    HANDLE hProcess = ProcessInfoNt.ProcessHandle;
     2146    HANDLE hThread  = ProcessInfoNt.ThreadHandle;
     2147#endif
     2148
     2149    /*
     2150     * Clean up the process.
     2151     */
     2152    int rc = supR3HardenedWinPurifyChild(hProcess, hThread, RTErrInfoInitStatic(&g_ErrInfoStatic));
     2153    if (RT_FAILURE(rc))
     2154    {
     2155        NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
     2156        supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
     2157    }
     2158
     2159    /*
     2160     * Start the process execution.
     2161     */
     2162    ULONG cSuspendCount = 0;
     2163    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtResumeThread(hThread, &cSuspendCount));
     2164
    14952165    /*
    14962166     * Close the unrestricted access handles.  Since we need to wait on the
     
    14982168     * away with the process handle returned by CreateProcess.
    14992169     */
    1500     SUPR3HARDENED_ASSERT(CloseHandle(ProcessInfo.hThread));
    1501     ProcessInfo.hThread = NULL;
     2170    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hThread));
    15022171
    15032172    HANDLE hProcWait;
     
    15082177        dwRights |= PROCESS_QUERY_INFORMATION;
    15092178    if (!DuplicateHandle(GetCurrentProcess(),
    1510                          ProcessInfo.hProcess,
     2179                         hProcess,
    15112180                         GetCurrentProcess(),
    15122181                         &hProcWait,
     
    15172186        /* This is unacceptable, kill the process. */
    15182187        DWORD dwErr = GetLastError();
    1519         TerminateProcess(ProcessInfo.hProcess, RTEXITCODE_FAILURE);
     2188        TerminateProcess(hProcess, RTEXITCODE_FAILURE);
    15202189        supR3HardenedError(dwErr, false /*fFatal*/, "DuplicateHandle failed on child process handle: %u\n", dwErr);
    15212190
    15222191        DWORD dwExit;
    1523         BOOL fExitOk = GetExitCodeProcess(ProcessInfo.hProcess, &dwExit)
     2192        BOOL fExitOk = GetExitCodeProcess(hProcess, &dwExit)
    15242193                    && dwExit != STILL_ACTIVE;
    15252194        if (!fExitOk)
     
    15292198            do
    15302199            {
    1531                 TerminateProcess(ProcessInfo.hProcess, RTEXITCODE_FAILURE);
    1532                 dwWait  = WaitForSingleObject(ProcessInfo.hProcess, 1000);
    1533                 fExitOk = GetExitCodeProcess(ProcessInfo.hProcess, &dwExit)
     2200                NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
     2201                dwWait  = WaitForSingleObject(hProcess, 1000);
     2202                fExitOk = GetExitCodeProcess(hProcess, &dwExit)
    15342203                       && dwExit != STILL_ACTIVE;
    15352204            } while (   !fExitOk
     
    15392208                supR3HardenedError(dwErr, false /*fFatal*/,
    15402209                                   "DuplicateHandle failed and we failed to kill child: dwErr=%u dwWait=%u err=%u hProcess=%p\n",
    1541                                    dwErr, dwWait, GetLastError(), ProcessInfo.hProcess);
     2210                                   dwErr, dwWait, GetLastError(), hProcess);
    15422211        }
    15432212        supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
     
    15452214    }
    15462215
    1547     SUPR3HARDENED_ASSERT(CloseHandle(ProcessInfo.hProcess));
    1548     ProcessInfo.hProcess = NULL;
     2216    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess));
     2217    hProcess = NULL;
    15492218
    15502219    /*
     
    15682237        dwExit = RTEXITCODE_FAILURE;
    15692238
    1570     CloseHandle(hProcWait);
     2239    NtClose(hProcWait);
    15712240    suplibHardenedExit((RTEXITCODE)dwExit);
    15722241}
    15732242
    15742243
     2244/**
     2245 * Checks if the driver exists.
     2246 *
     2247 * This checks whether the driver is present in the /Driver object directory.
     2248 * Drivers being initialized or terminated will have an object there
     2249 * before/after their devices nodes are created/deleted.
     2250 *
     2251 * @returns true if it exists, false if not.
     2252 * @param   pszDriver           The driver name.
     2253 */
    15752254static bool supR3HardenedWinDriverExists(const char *pszDriver)
    15762255{
     
    16412320
    16422321/**
    1643  * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true.
    1644  *
    1645  * @returns Program exit code.
    1646  */
    1647 DECLHIDDEN(int) supR3HardenedWinReSpawn(void)
    1648 {
    1649     /*
    1650      * Open the stub device.  Retry if we think driver might still be
    1651      * initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
     2322 * Open the stub device before the 2nd respawn.
     2323 */
     2324static void supR3HardenedWinOpenStubDevice(void)
     2325{
     2326    /*
     2327     * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
    16522328     */
    16532329    static const WCHAR  s_wszName[] = L"\\Device\\VBoxDrvStub";
     
    17282404                              "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt);
    17292405    }
     2406}
     2407
     2408
     2409/**
     2410 * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true.
     2411 *
     2412 * @returns Program exit code.
     2413 */
     2414DECLHIDDEN(int) supR3HardenedWinReSpawn(int iWhich)
     2415{
     2416    /*
     2417     * Before the 2nd respawn we set up a child protection deal with the
     2418     * support driver via /Devices/VBoxDrvStub.
     2419     */
     2420    if (iWhich == 2)
     2421        supR3HardenedWinOpenStubDevice();
    17302422
    17312423    /*
    17322424     * Respawn the process with kernel protection for the new process.
    17332425     */
    1734     return supR3HardenedWinDoReSpawn();
     2426    return supR3HardenedWinDoReSpawn(iWhich);
    17352427}
    17362428
     
    17412433 * @returns true if required, false if not. In the latter case, the first
    17422434 *          argument in the vector is replaced.
     2435 * @param   iWhich              Which respawn we're to check for, 1 being the
     2436 *                              first one, and 2 the second and final.
    17432437 * @param   cArgs               The number of arguments.
    17442438 * @param   papszArgs           Pointer to the argument vector.
    17452439 */
    1746 DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int cArgs, char **papszArgs)
     2440DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs)
    17472441{
    17482442    SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
     2443    SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2);
    17492444
    17502445    if (cArgs < 1)
    17512446        return true;
    1752     if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_ARG0))
     2447
     2448    if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
     2449    {
     2450        if (iWhich > 1)
     2451            return true;
     2452    }
     2453    else if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
     2454    {
     2455        if (iWhich < 2)
     2456            return false;
     2457    }
     2458    else
    17532459        return true;
    17542460
     
    19262632        supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromNtStatus(rcNt),
    19272633                              "NtQueryObject -> %#x (on %ls)\n", rcNt, g_wszSupLibHardenedExePath);
    1928     CloseHandle(hFile);
     2634    NtClose(hFile);
    19292635
    19302636    /* The NT executable name offset / dir path length. */
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