Changeset 52139 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Jul 22, 2014 8:19:29 PM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r52083 r52139 417 417 DECLHIDDEN(void) supR3HardenedWinVerifyProcess(void); 418 418 DECLHIDDEN(void) supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(void); 419 DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int cArgs, char **papszArgs);420 DECLHIDDEN(int) supR3HardenedWinReSpawn( void);419 DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs); 420 DECLHIDDEN(int) supR3HardenedWinReSpawn(int iWhich); 421 421 DECLHIDDEN(void *) supR3HardenedWinLoadLibrary(const char *pszName, bool fSystem32Only); 422 422 extern RTUTF16 g_wszSupLibHardenedExePath[1024]; -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r52089 r52139 1542 1542 "Effective UID is not root (euid=%d egid=%d uid=%d gid=%d)", 1543 1543 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 */ 1552 1571 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 */ 1556 1577 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 */ 1557 1583 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 } 1559 1598 1560 1599 #ifdef RT_OS_WINDOWS 1561 1600 /* 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 */ 1576 1603 supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(); 1577 1604 g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY; 1578 1605 #endif 1579 1580 /*1581 * Open the root service connection.1582 */1583 //if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_SVC))1584 //supR3HardenedMainOpenService(&g_SupPreInitData, true /* fFatal */);1585 1606 1586 1607 #ifdef SUP_HARDENED_SUID -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r52030 r52139 100 100 /** Combined NT version number for XP. */ 101 101 #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) 102 104 /** Combined NT version number for Vista. */ 103 105 #define SUP_NT_VER_VISTA SUP_MAKE_NT_VER_SIMPLE(6,0) -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52092 r52139 45 45 #include <iprt/initterm.h> 46 46 #include <iprt/param.h> 47 #include <iprt/zero.h> 47 48 48 49 #include "SUPLibInternal.h" … … 54 55 * Defined Constants And Macros * 55 56 *******************************************************************************/ 56 /** The first argument of a respawed stub argument.57 /** The first argument of a respawed stub when respawned for the first time. 57 58 * This just needs to be unique enough to avoid most confusion with real 58 59 * 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" 60 66 61 67 /** Unconditional assertion. */ … … 1362 1368 * 1363 1369 * @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 */ 1375 static PRTUTF16 supR3HardenedWinConstructCmdLine(PUNICODE_STRING pString, int iWhich) 1376 { 1377 SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2); 1378 1367 1379 /* 1368 1380 * Get the command line and skip the executable name. … … 1404 1416 * Allocate a new buffer. 1405 1417 */ 1418 AssertCompile(sizeof(SUPR3_RESPAWN_1_ARG0) == sizeof(SUPR3_RESPAWN_2_ARG0)); 1406 1419 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. */ 1408 1421 + !!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 1409 1426 PRTUTF16 pwszCmdLine = (PRTUTF16)HeapAlloc(GetProcessHeap(), 0 /* dwFlags*/, (cwcCmdLine + 1) * sizeof(RTUTF16)); 1410 1427 SUPR3HARDENED_ASSERT(pwszCmdLine != NULL); … … 1414 1431 */ 1415 1432 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++) 1417 1434 *pwszDst++ = *pszSrc; 1418 1435 … … 1427 1444 SUPR3HARDENED_ASSERT(pwszDst - pwszCmdLine == cwcCmdLine); 1428 1445 1446 if (pString) 1447 { 1448 pString->Buffer = pwszCmdLine; 1449 pString->Length = (USHORT)(cwcCmdLine * sizeof(WCHAR)); 1450 pString->MaximumLength = pString->Length + sizeof(WCHAR); 1451 } 1429 1452 return pwszCmdLine; 1430 1453 } 1431 1454 1432 1455 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 1469 typedef 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; 1484 typedef SUPR3HARDNTPUCH *PSUPR3HARDNTPUCH; 1485 1486 1487 static 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 */ 1527 static 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 1628 static 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 1643 static 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 1696 DECLINLINE(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 1721 static 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 1733 static 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 1755 static 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 1861 static 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 1974 static 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 1433 2025 /** 1434 2026 * Does the actually respawning. … … 1436 2028 * @returns Exit code (if we get that far). 1437 2029 */ 1438 static int supR3HardenedWinDoReSpawn( void)2030 static int supR3HardenedWinDoReSpawn(int iWhich) 1439 2031 { 1440 2032 SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1); 1441 2033 1442 2034 /* 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 /* 1443 2047 * Configure the startup info and creation flags. 1444 2048 */ 1445 DWORD dwCreationFlags = 0;2049 DWORD dwCreationFlags = CREATE_SUSPENDED; 1446 2050 1447 2051 STARTUPINFOEXW SiEx; … … 1462 2066 1463 2067 /* 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 /*1475 2068 * Construct the command line and launch the process. 1476 2069 */ 1477 PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine( );1478 1479 PROCESS_INFORMATION ProcessInfo ;2070 PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine(NULL, iWhich); 2071 2072 PROCESS_INFORMATION ProcessInfoW32; 1480 2073 if (!CreateProcessW(g_wszSupLibHardenedExePath, 1481 2074 pwszCmdLine, … … 1487 2080 NULL /*pwszCurDir*/, 1488 2081 &SiEx.StartupInfo, 1489 &ProcessInfo ))2082 &ProcessInfoW32)) 1490 2083 supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME, 1491 2084 "Error relaunching VirtualBox VM process: %u\n" … … 1493 2086 GetLastError(), pwszCmdLine); 1494 2087 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 1495 2165 /* 1496 2166 * Close the unrestricted access handles. Since we need to wait on the … … 1498 2168 * away with the process handle returned by CreateProcess. 1499 2169 */ 1500 SUPR3HARDENED_ASSERT(CloseHandle(ProcessInfo.hThread)); 1501 ProcessInfo.hThread = NULL; 2170 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hThread)); 1502 2171 1503 2172 HANDLE hProcWait; … … 1508 2177 dwRights |= PROCESS_QUERY_INFORMATION; 1509 2178 if (!DuplicateHandle(GetCurrentProcess(), 1510 ProcessInfo.hProcess,2179 hProcess, 1511 2180 GetCurrentProcess(), 1512 2181 &hProcWait, … … 1517 2186 /* This is unacceptable, kill the process. */ 1518 2187 DWORD dwErr = GetLastError(); 1519 TerminateProcess( ProcessInfo.hProcess, RTEXITCODE_FAILURE);2188 TerminateProcess(hProcess, RTEXITCODE_FAILURE); 1520 2189 supR3HardenedError(dwErr, false /*fFatal*/, "DuplicateHandle failed on child process handle: %u\n", dwErr); 1521 2190 1522 2191 DWORD dwExit; 1523 BOOL fExitOk = GetExitCodeProcess( ProcessInfo.hProcess, &dwExit)2192 BOOL fExitOk = GetExitCodeProcess(hProcess, &dwExit) 1524 2193 && dwExit != STILL_ACTIVE; 1525 2194 if (!fExitOk) … … 1529 2198 do 1530 2199 { 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) 1534 2203 && dwExit != STILL_ACTIVE; 1535 2204 } while ( !fExitOk … … 1539 2208 supR3HardenedError(dwErr, false /*fFatal*/, 1540 2209 "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); 1542 2211 } 1543 2212 supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME, … … 1545 2214 } 1546 2215 1547 SUPR3HARDENED_ASSERT (CloseHandle(ProcessInfo.hProcess));1548 ProcessInfo.hProcess = NULL;2216 SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess)); 2217 hProcess = NULL; 1549 2218 1550 2219 /* … … 1568 2237 dwExit = RTEXITCODE_FAILURE; 1569 2238 1570 CloseHandle(hProcWait);2239 NtClose(hProcWait); 1571 2240 suplibHardenedExit((RTEXITCODE)dwExit); 1572 2241 } 1573 2242 1574 2243 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 */ 1575 2254 static bool supR3HardenedWinDriverExists(const char *pszDriver) 1576 2255 { … … 1641 2320 1642 2321 /** 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 */ 2324 static void supR3HardenedWinOpenStubDevice(void) 2325 { 2326 /* 2327 * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv). 1652 2328 */ 1653 2329 static const WCHAR s_wszName[] = L"\\Device\\VBoxDrvStub"; … … 1728 2404 "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt); 1729 2405 } 2406 } 2407 2408 2409 /** 2410 * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true. 2411 * 2412 * @returns Program exit code. 2413 */ 2414 DECLHIDDEN(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(); 1730 2422 1731 2423 /* 1732 2424 * Respawn the process with kernel protection for the new process. 1733 2425 */ 1734 return supR3HardenedWinDoReSpawn( );2426 return supR3HardenedWinDoReSpawn(iWhich); 1735 2427 } 1736 2428 … … 1741 2433 * @returns true if required, false if not. In the latter case, the first 1742 2434 * 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. 1743 2437 * @param cArgs The number of arguments. 1744 2438 * @param papszArgs Pointer to the argument vector. 1745 2439 */ 1746 DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int cArgs, char **papszArgs)2440 DECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs) 1747 2441 { 1748 2442 SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1); 2443 SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2); 1749 2444 1750 2445 if (cArgs < 1) 1751 2446 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 1753 2459 return true; 1754 2460 … … 1926 2632 supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromNtStatus(rcNt), 1927 2633 "NtQueryObject -> %#x (on %ls)\n", rcNt, g_wszSupLibHardenedExePath); 1928 CloseHandle(hFile);2634 NtClose(hFile); 1929 2635 1930 2636 /* The NT executable name offset / dir path length. */
Note:
See TracChangeset
for help on using the changeset viewer.