SUPR3HardenedMain-win.cpp revision 09af8164395ce22610792b5097e2b6ba3a63ac78
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox Support Library - Hardened main(), windows bits.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The contents of this file may alternatively be used under the terms
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of the Common Development and Distribution License Version 1.0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * CDDL are applicable instead of those of the GPL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * You may elect to license modified versions of this file under the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Defined Constants And Macros *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
edde275acba04aca58db4172a163741e3abadfbcvboxsync/** The first argument of a respawed stub when respawned for the first time.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This just needs to be unique enough to avoid most confusion with real
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * executable names, there are other checks in place to make sure we've respanwed. */
a1d9d394b49969e730c5a8e037ea2d672a48dbf6vboxsync#define SUPR3_RESPAWN_1_ARG0 "60eaff78-4bdd-042d-2e72-669728efd737-suplib-2ndchild"
edde275acba04aca58db4172a163741e3abadfbcvboxsync/** The first argument of a respawed stub when respawned for the second time.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * This just needs to be unique enough to avoid most confusion with real
edde275acba04aca58db4172a163741e3abadfbcvboxsync * executable names, there are other checks in place to make sure we've respanwed. */
a1d9d394b49969e730c5a8e037ea2d672a48dbf6vboxsync#define SUPR3_RESPAWN_2_ARG0 "60eaff78-4bdd-042d-2e72-669728efd737-suplib-3rdchild"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion. */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("%s: %s\n", __FUNCTION__, #a_Expr); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion of NT_SUCCESS. */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("%s: %s -> %#x\n", __FUNCTION__, #a_Expr, rcNtAssert); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion of a WIN32 API returning non-FALSE. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define SUPR3HARDENED_ASSERT_WIN32_SUCCESS(a_Expr) \
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("%s: %s -> %#x\n", __FUNCTION__, #a_Expr, RtlGetLastWin32Error()); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Structures and Typedefs *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Security descriptor cleanup structure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to security cleanup structure. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Image verifier cache entry.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Pointer to the next entry with the same hash value. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Next entry in the WinVerifyTrust todo list. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The file handle. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** If fIndexNumber is set, this is an file system internal file identifier. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The path hash value. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The verification result. */
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync /** Used for shutting up errors after a while. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /** The validation flags (for WinVerifyTrust retry). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Whether IndexNumber is valid */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Whether verified by WinVerifyTrust. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool volatile fWinVerifyTrust;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** cwcPath * sizeof(RTUTF16). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The full path of this entry (variable size). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to an image verifier path entry. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Name of an import DLL that we need to check out.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Pointer to the next DLL in the list. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** The length of pwszAltSearchDir if available. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** This points the directory containing the DLL needing it, this will be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * NULL for a System32 DLL. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** The name of the import DLL (variable length). */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Pointer to a import DLL that needs checking out. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child requests.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Perform child purification and close full access handles (must be zero). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Close the events, we're good on our own from here on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Reporting error. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** End of valid requests. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child process parameters.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The event semaphore the child will be waiting on. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The event semaphore the parent will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of the NTDLL. This is only valid during the very early
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * initialization as we abuse for thread creation protection. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The requested operation (set by the child). */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The last status. */
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync /** The init operation the error relates to if message, kSupInitOp_Invalid if
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * not message. */
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync /** Where if message. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** Error message / path name string space. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child process data structure for use during child process init setup and
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * purification.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Process handle. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Primary thread handle. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Handle to the parent process, if we're the middle (stub) process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The event semaphore the child will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The event semaphore the parent will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of NTDLL in the child. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of NTDLL in this process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Which respawn number this is (1 = stub, 2 = VM). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The basic process info. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The probable size of the PEB. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The pristine process environment block. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The child process parameters. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Pointer to a child process data structure. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Process parameters. Specified by parent if VM process, see
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * supR3HardenedVmProcessInit. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic SUPR3WINPROCPARAMS g_ProcParams = { NULL, NULL, 0, (SUPR3WINCHILDREQ)0, 0 };
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** Set if supR3HardenedEarlyProcessInit was invoked. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** Set if the stub device has been opened (stub process only). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @name Global variables initialized by suplibHardenedWindowsMain.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Combined windows NT version number. See SUP_MAKE_NT_VER_COMBINED. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Count calls to the special main function for linking santity checks. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t volatile g_cSuplibHardenedWindowsMainCalls;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The UTF-16 windows path to the executable. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The NT path of the executable. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The offset into g_SupLibHardenedExeNtPath of the executable name (WCHAR,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * not byte). This also gives the length of the exectuable directory path,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * including a trailing slash. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @name Hook related variables.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to the bit of assembly code that will perform the original
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * NtCreateSection operation. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic NTSTATUS (NTAPI * g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Pointer to the NtCreateSection function in NtDll (for patching purposes). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The patched NtCreateSection bytes (for restoring). */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Pointer to the bit of assembly code that will perform the original
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * LdrLoadDll operation. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS (NTAPI * g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Pointer to the LdrLoadDll function in NtDll (for patching purposes). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The patched LdrLoadDll bytes (for restoring). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The hash table of verifier cache . */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_apVerifierCache[128];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs WinVerifyTrust to check them. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_pVerifierCacheTodoWvt = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs their imports checked. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync/** The windows path to dir \\SystemRoot\\System32 directory (technically
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * this whatever \KnownDlls\KnownDllPath points to). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Positive if the DLL notification callback has been registered, counts
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * registration attempts as negative. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The registration cookie of the DLL notification callback. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Static error info structure used during init. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** In the assembly file. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncextern "C" uint8_t g_abSupHardReadWriteExecPage[PAGE_SIZE];
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/** Whether we've patched our own LdrInitializeThunk or not. We do this to
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * disable thread creation. */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/** The backup of our own LdrInitializeThunk code, for enabling and disabling
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * thread creation in this process. */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Mask of adversaries that we've detected (SUPHARDNT_ADVERSARY_XXX). */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** @name SUPHARDNT_ADVERSARY_XXX - Adversaries
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Symantec endpoint protection or similar including SysPlant.sys. */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT RT_BIT_32(0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Symantec Norton 360. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_N360 RT_BIT_32(1)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Avast! */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** TrendMicro OfficeScan and probably others. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** McAfee. */
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync/** Kaspersky or OEMs of it. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Malwarebytes Anti-Malware (MBAM). */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** AVG Internet Security. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Panda Security. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Microsoft Security Essentials. */
a6c871653045073d6ef74d0589de345ae62b607dvboxsync/** Comodo. */
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync/** Check Point's Zone Alarm (may include Kaspersky). */
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync#define SUPHARDNT_ADVERSARY_ZONE_ALARM RT_BIT_32(11)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Unknown adversary detected while waiting on child. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncstatic void supR3HardenedWinRegisterDllNotificationCallback(void);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncstatic void supR3HardenedWinReInstallHooks(bool fFirst);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncDECLASM(void) supR3HardenedEarlyProcessInitThunk(void);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple wide char search routine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the first location of @a wcNeedle in @a pwszHaystack.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * NULL if not found.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszHaystack Pointer to the string that should be searched.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param wcNeedle The character to search for.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic PRTUTF16 suplibHardenedWStrChr(PCRTUTF16 pwszHaystack, RTUTF16 wcNeedle)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple wide char string length routine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns The number of characters in the given string. (Excludes the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terminator.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The string.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Our version of GetTickCount.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * @returns Millisecond timestamp.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync PKUSER_SHARED_DATA pUserSharedData = (PKUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync /* use interrupt time */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync Time.HighPart = pUserSharedData->InterruptTime.High1Time;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync Time.LowPart = pUserSharedData->InterruptTime.LowPart;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Wrapper around LoadLibraryEx that deals with the UTF-8 to UTF-16 conversion
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and supplies the right flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Module handle on success, NULL on failure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszName The full path to the DLL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fSystem32Only Whether to only look for imports in the system32
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directory. If set to false, the application
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directory is also searched.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void *) supR3HardenedWinLoadLibrary(const char *pszName, bool fSystem32Only)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTStrToUtf16Ex(pszName, RTSTR_MAX, &pwszPath, RT_ELEMENTS(wszPath), NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync void *pvRet = (void *)LoadLibraryExW(wszPath, NULL /*hFile*/, fFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Vista, W7, W2K8R might not work without KB2533623, so retry with no flags. */
30f07af559efcbd967e801903746fc21f81ee533vboxsync && RtlGetLastWin32Error() == ERROR_INVALID_PARAMETER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvRet = (void *)LoadLibraryExW(wszPath, NULL /*hFile*/, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("RTStrToUtf16Ex failed on '%s': %Rrc", pszName, rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Gets the internal index number of the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns True if we got an index number, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file in question.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pIndexNumber where to return the index number.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedWinVerifyCacheGetIndexNumber(HANDLE hFile, PLARGE_INTEGER pIndexNumber)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryInformationFile(hFile, &Ios, pIndexNumber, sizeof(*pIndexNumber), FileInternalInformation);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NT_SUCCESS(rcNt) && pIndexNumber->QuadPart != 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Calculates the hash value for the given UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Hash value.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr String to hash.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t supR3HardenedWinVerifyCacheHashPath(PCUNICODE_STRING pUniStr)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cwcLeft = pUniStr->Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcLeft-- > 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Calculates the hash value for a directory + filename combo as if they were
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * one single string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns Hash value.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcDir The directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcDir The length of the directory name. RTSTR_MAX if
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * not available.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pszName The import name (UTF-8).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic uint32_t supR3HardenedWinVerifyCacheHashDirAndFile(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (cwcDir-- > 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Verify string cache compare function.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns true if the strings match, false if not.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcLeft The left hand string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcRight The right hand string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcToCompare The number of chars to compare.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic bool supR3HardenedWinVerifyCacheIsMatch(PCRTUTF16 pawcLeft, PCRTUTF16 pawcRight, uint32_t cwcToCompare)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Try a quick memory compare first. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (memcmp(pawcLeft, pawcRight, cwcToCompare * sizeof(RTUTF16)) == 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Slow char by char compare. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (cwcToCompare-- > 0)
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync wcLeft = wcLeft != '/' ? RT_C_TO_LOWER(wcLeft) : '\\';
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync wcRight = wcRight != '/' ? RT_C_TO_LOWER(wcRight) : '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Inserts the given verifier result into the cache.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr The full path of the image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file handle - must either be entered into
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the cache or closed.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param rc The verifier result.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param fWinVerifyTrust Whether verified by WinVerifyTrust or not.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param fFlags The image verification flags.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Allocate and initalize a new entry.
30f07af559efcbd967e801903746fc21f81ee533vboxsync PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)RTMemAllocZ(sizeof(VERIFIERCACHEENTRY) + pUniStr->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(pEntry->wszPath, pUniStr->Buffer, pUniStr->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->wszPath[pUniStr->Length / sizeof(WCHAR)] = '\0';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &pEntry->IndexNumber);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try insert it, careful with concurrent code as well as potential duplicates.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t iHashTab = pEntry->uHash % RT_ELEMENTS(g_apVerifierCache);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync VERIFIERCACHEENTRY * volatile *ppEntry = &g_apVerifierCache[iHashTab];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pEntry, pEntry->pNextTodoWvt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheInsert: %ls\n", pUniStr->Buffer));
e17f6f8a70a7709a9a6319d9a473596fb600b552vboxsync && supR3HardenedWinVerifyCacheIsMatch(pOther->wszPath, pEntry->wszPath, pEntry->cbPath / sizeof(RTUTF16)))
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Duplicate entry (may happen due to races). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Looks up an entry in the verifier hash table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @return Pointer to the entry on if found, NULL if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr The full path of the image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookup(PCUNICODE_STRING pUniStr, HANDLE hFile)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t iHashTab = uHash % RT_ELEMENTS(g_apVerifierCache);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PVERIFIERCACHEENTRY pCur = g_apVerifierCache[iHashTab];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pwszPath, cbPath / sizeof(RTUTF16)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &IndexNumber);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && IndexNumber.QuadPart == pCur->IndexNumber.QuadPart)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Looks up an import DLL in the verifier hash table.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @return Pointer to the entry on if found, NULL if not.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcDir The directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcDir The length of the directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pszName The import name (UTF-8).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookupImport(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t uHash = supR3HardenedWinVerifyCacheHashDirAndFile(pawcDir, cwcDir, pszName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t iHashTab = uHash % RT_ELEMENTS(g_apVerifierCache);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t const cbPath = (uint32_t)((cwcDir + 1 + strlen(pszName)) * sizeof(RTUTF16));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEENTRY pCur = g_apVerifierCache[iHashTab];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pawcDir, cwcDir))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pCur->wszPath[cwcDir] == '\\' || pCur->wszPath[cwcDir] == '/')
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (RTUtf16ICmpAscii(&pCur->wszPath[cwcDir + 1], pszName))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Schedules the import DLLs for verification and entry into the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hLdrMod The loader module which imports should be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * scheduled for verification.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszName The full NT path of the module.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyCacheScheduleImports(RTLDRMOD hLdrMod, PCRTUTF16 pwszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Any imports?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_COUNT, NULL /*pvBits*/, &cImports, sizeof(cImports), NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Figure out the DLL directory from pwszName.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ((wc == '\\' || wc == '/' || wc == ':') && cwcDir + 2 != i)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( g_System32NtPath.UniStr.Length / sizeof(WCHAR) == cwcDir
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pawcDir, g_System32NtPath.UniStr.Buffer, cwcDir))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Enumerate the imports.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync for (i = 0; i < cImports; i++)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_MODULE, NULL /*pvBits*/, &uBuf, sizeof(uBuf), NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Skip kernel32, ntdll and API set stuff.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || RTStrNCmp(uBuf.szName, RT_STR_TUPLE("api-ms-win-")) == 0 )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Skip to the next one if it's already in the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for system32\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for appdir\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pawcDir && supR3HardenedWinVerifyCacheLookupImport(pawcDir, cwcDir, uBuf.szName) != NULL)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for dll dir\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* We could skip already scheduled modules, but that'll require serialization and extra work... */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Add it to the todo list.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: Import todo: #%u '%s'.\n", i, uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cbName = (uint32_t)strlen(uBuf.szName) + 1;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cbNameAligned = RT_ALIGN_32(cbName, sizeof(RTUTF16));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cbNeeded = RT_OFFSETOF(VERIFIERCACHEIMPORT, szName[cbNameAligned])
30f07af559efcbd967e801903746fc21f81ee533vboxsync PVERIFIERCACHEIMPORT pImport = (PVERIFIERCACHEIMPORT)RTMemAllocZ(cbNeeded);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Init it. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->pwszAltSearchDir = (PRTUTF16)&pImport->szName[cbNameAligned];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(pImport->pwszAltSearchDir, pawcDir, cwcDir * sizeof(RTUTF16));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Insert it. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoImports, pImport, pImport->pNext));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("RTLDRPROP_IMPORT_MODULE failed with rc=%Rrc i=%#x on '%ls'\n", rc, i, pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("RTLDRPROP_IMPORT_COUNT failed with rc=%Rrc on '%ls'\n", rc, pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Processes the list of import todos.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic void supR3HardenedWinVerifyCacheProcessImportTodos(void)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Work until we've got nothing more todo.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEIMPORT pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoImports, NULL, PVERIFIERCACHEIMPORT);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Not in the cached already?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( !supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && !supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || !supR3HardenedWinVerifyCacheLookupImport(pCur->pwszAltSearchDir, pCur->cwcAltSearchDir, pCur->szName)) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try locate the imported DLL and open it.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Processing '%s'...\n", pCur->szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wszPath[260 + 260]; /* Assumes we've limited the import name length to 256. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync AssertCompile(sizeof(wszPath) > sizeof(g_System32NtPath));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Check for DLL isolation / redirection / mapping.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync int rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrName.Length = (USHORT)cwcName * sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync UniStrStatic.MaximumLength = (USHORT)(sizeof(wszPath) - cwcName * sizeof(WCHAR) - sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNtRedir = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync InitializeObjectAttributes(&ObjAttr, pUniStrResult,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync 0 /*EaLength*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync /* For accurate logging. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcCopy = RT_MIN(pUniStrResult->Length / sizeof(RTUTF16), RT_ELEMENTS(wszPath) - 1);
100b161379af7255c69e27587cc746e5f76ff050vboxsync memcpy(wszPath, pUniStrResult->Buffer, cwcCopy * sizeof(RTUTF16));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex #1 failed: %Rrc\n", rc));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * If not something that gets remapped, do the half normal searching we need.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync { g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length / sizeof(WCHAR) },
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync { g_SupLibHardenedExeNtPath.UniStr.Buffer, g_offSupLibHardenedExeNtName - 1 },
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync /* Search System32 first, unless it's a 'V*' or 'm*' name, the latter for msvcrt. */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (aDirs[i].pawcDir && aDirs[i].cwcDir && aDirs[i].cwcDir < RT_ELEMENTS(wszPath) / 3 * 2)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(wszPath, aDirs[i].pawcDir, aDirs[i].cwcDir * sizeof(RTUTF16));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NtName.Length = (USHORT)((cwc + cwcName) * sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync 0 /*EaLength*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex #2 failed: %Rrc\n", rc));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * If we successfully opened it, verify it and cache the result.
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' -> '%ls' [rcNtRedir=%#x]\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fCallRealApi = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "Imports", false /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Failed to locate '%s'\n", pCur->szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' is in the cache.\n", pCur->szName));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Processes the list of WinVerifyTrust todos.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic void supR3HardenedWinVerifyCacheProcessWvtTodos(void)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY volatile *ppReschedLastNext = NULL;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Work until we've got nothing more todo.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoWvt, NULL, PVERIFIERCACHEENTRY);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync int rc = supHardenedWinVerifyImageTrust(pCur->hFile, pCur->wszPath, pCur->fFlags, pCur->rc,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Retry it at a later time. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls' [rescheduled]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* else: already processed. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Anything to reschedule.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pReschedule, *ppReschedLastNext));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Checks whether the path could be containing alternative 8.3 names generated
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * by NTFS, FAT, or other similar file systems.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @returns Pointer to the first component that might be an 8.3 name, NULL if
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * not 8.3 path.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param pwszPath The path to check.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsyncstatic PRTUTF16 supR3HardenedWinIsPossible8dot3Path(PCRTUTF16 pwszPath)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* Could check more here before jumping to conclusions... */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync else if (wc == 0)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Fixes up a path possibly containing one or more alternative 8-dot-3 style
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * components.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * The path is fixed up in place. Errors are ignored.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param hFile The handle to the file which path we're fixing up.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param pUniStr The path to fix up. MaximumLength is the max buffer
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsyncstatic void supR3HardenedWinFix8dot3Path(HANDLE hFile, PUNICODE_STRING pUniStr)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * We could use FileNormalizedNameInformation here and slap the volume device
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * path in front of the result, but it's only supported since windows 8.0
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * according to some docs... So we expand all supicious names.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszFix = supR3HardenedWinIsPossible8dot3Path(pwszFix);
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '/')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync 0 /*EaLength*/);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (NT_SUCCESS(rcNt) && uBuf.Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint32_t offName = uBuf.Info.FileNameLength / sizeof(WCHAR);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync while (offName > 0 && uBuf.Info.FileName[offName - 1] != '\\' && uBuf.Info.FileName[offName - 1] != '/')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint32_t cwcNameNew = (uBuf.Info.FileNameLength / sizeof(WCHAR)) - offName;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* else: ignore overflow. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* else: ignore failure. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* Advance */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Query the name of the file, making sure to zero terminator the
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * string. (2nd half of buffer is used for error info, see below.)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync uint8_t abBuffer[sizeof(UNICODE_STRING) + 2048 * sizeof(WCHAR)];
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR) - 128, &cbNameBuf);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Check the cache.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* If we haven't done the WinVerifyTrust thing, do it if we can. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [redoing WinVerifyTrust]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync int rc = supHardenedWinVerifyImageTrust(pCacheHit->hFile, pCacheHit->wszPath, pCacheHit->fFlags, pCacheHit->rc,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, rc, pCacheHit->rc, fWinVerifyTrust, pCacheHit->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: WinVerifyTrust not available, rescheduling %ls\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [avoiding WinVerifyTrust]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls%s\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, pCacheHit->rc, pCacheHit->wszPath, pCacheHit->fWinVerifyTrust ? "" : " [lacks WinVerifyTrust]"));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Return the cached value. */
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync uint32_t cErrorHits = ASMAtomicIncU32(&pCacheHit->cErrorHits);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "supR3HardenedScreenImage/%s: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x cErrorHits=%u %ls\n",
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync pszCaller, pCacheHit->rc, fImage, *pfProtect, *pfAccess, cErrorHits, uBuf.UniStr.Buffer);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * On XP the loader might hand us handles with just FILE_EXECUTE and
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * SYNCHRONIZE, the means reading will fail later on. Also, we need
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * READ_CONTROL access to check the file ownership later on, and non
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * of the OS versions seems be giving us that. So, in effect we
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * more or less always reopen the file here.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hFile, NtCurrentProcess(),
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 0 /*EaLength*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /* Check that we've got the same file. */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fMyValid = supR3HardenedWinVerifyCacheGetIndexNumber(hMyFile, &idMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fInValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &idInFile);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: NtDuplicateObject -> %#x\n", pszCaller, rcNt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: NtDuplicateObject(,%#x,) failed: %#x\n", pszCaller, hFile, rcNt);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Special Kludge for Windows XP and W2K3 and their stupid attempts
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * at mapping a hidden XML file called c:\Windows\WindowsShell.Manifest
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * with executable access. The image bit isn't set, fortunately.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && uBuf.UniStr.Length > g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && memcmp(uBuf.UniStr.Buffer, g_System32NtPath.UniStr.Buffer,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) == 0)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync PRTUTF16 pwszName = &uBuf.UniStr.Buffer[(g_System32NtPath.UniStr.Length - sizeof(L"System32") + sizeof(WCHAR)) / sizeof(WCHAR)];
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (RTUtf16ICmpAscii(pwszName, "WindowsShell.Manifest") == 0)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Drop all executable access to the mapping and let it continue.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: Applying the drop-exec-kludge for '%ls'\n", pszCaller, uBuf.UniStr.Buffer));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfAccess = (*pfAccess & ~SECTION_MAP_EXECUTE) | SECTION_MAP_READ;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfProtect = (*pfProtect & ~PAGE_EXECUTE) | PAGE_READONLY;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfProtect = (*pfProtect & ~UINT32_C(0xf0)) | ((*pfProtect & UINT32_C(0xe0)) >> 4);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Check the path. We don't allow DLLs to be loaded from just anywhere:
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 1. System32 - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 2. WinSxS - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 3. VirtualBox - kernel code signing and integrity checks.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 4. AppPatchDir - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 5. Program Files - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 6. Common Files - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 7. x86 variations of 4 & 5 - ditto.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_System32NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_WinSxSNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViIsAppPatchDir(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR)))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesX86NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesX86NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /* Hack to allow profiling our code with Visual Studio. */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if ( uBuf.UniStr.Length > sizeof(L"\\SamplingRuntime.dll")
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && memcmp(uBuf.UniStr.Buffer + (uBuf.UniStr.Length - sizeof(L"\\SamplingRuntime.dll") + sizeof(WCHAR)) / sizeof(WCHAR),
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync L"\\SamplingRuntime.dll", sizeof(L"\\SamplingRuntime.dll") - sizeof(WCHAR)) == 0 )
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync "supR3HardenedScreenImage/%s: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect);
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#else /* VBOX_PERMIT_EVEN_MORE */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Require trusted installer + some kind of signature on everything, except
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * for the VBox bits where we require kernel code signing and special
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * integrity checks.
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#endif /* VBOX_PERMIT_EVEN_MORE */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Do the verification. For better error message we borrow what's
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * left of the path buffer for an RTERRINFO buffer.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync RTErrInfoInit(&ErrInfo, (char *)&uBuf.abBuffer[cbNameBuf], sizeof(uBuf) - cbNameBuf);
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, fAvoidWinVerifyTrust, &fWinVerifyTrust, &ErrInfo);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg);
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust, fFlags);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Insert into the cache.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust, fFlags);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Preloads a file into the verify cache if possible.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * This is used to avoid known cyclic LoadLibrary issues with WinVerifyTrust.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pwszName The name of the DLL to verify.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyCachePreload(PCRTUTF16 pwszName)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UniStr.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UniStr.MaximumLength = UniStr.Length + sizeof(WCHAR);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync InitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 0 /*EaLength*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: Error %#x opening '%ls'.\n", rcNt, pwszName));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: scanning %ls\n", pwszName));
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, "preload", false /*fAvoidWinVerifyTrust*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: done %ls\n", pwszName));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Hook that monitors NtCreateSection calls.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @returns NT status code.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param phSection Where to return the section handle.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fAccess The desired access.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pObjAttribs The object attributes (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pcbSection The section size (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fProtect The max section protection.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fAttribs The section attributes.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param hFile The file to create a section from (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncsupR3HardenedMonitor_NtCreateSection(PHANDLE phSection, ACCESS_MASK fAccess, POBJECT_ATTRIBUTES pObjAttribs,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync PLARGE_INTEGER pcbSection, ULONG fProtect, ULONG fAttribs, HANDLE hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool const fImage = RT_BOOL(fAttribs & (SEC_IMAGE | SEC_PROTECTED_IMAGE));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool const fExecMap = RT_BOOL(fAccess & SECTION_MAP_EXECUTE);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool const fExecProt = RT_BOOL(fProtect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_WRITECOPY
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 1\n"));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "NtCreateSection", true /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 2 rcNt=%#x fCallRealApi=%#x\n", rcNt, fCallRealApi));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Call checked out OK, call the original.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * Helper for supR3HardenedMonitor_LdrLoadDll.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @returns NT status code.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pwszPath The path destination buffer.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param cwcPath The size of the path buffer.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pUniStrResult The result string.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pOrgName The orignal name (for errors).
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pcwc Where to return the actual length.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsyncstatic NTSTATUS supR3HardenedCopyRedirectionResult(WCHAR *pwszPath, size_t cwcPath, PUNICODE_STRING pUniStrResult,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync *pcwc = cwc = pUniStrResult->Length / sizeof(WCHAR);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long: %.*ls -> %.*ls (RtlDosApplyFileIoslationRedirection_Ustr)\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pOrgName->Length / sizeof(WCHAR), pOrgName->Buffer,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pUniStrResult->Length / sizeof(WCHAR), pUniStrResult->Buffer);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync memcpy(&pwszPath[0], pUniStrResult->Buffer, pUniStrResult->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hooks that intercepts LdrLoadDll calls.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Two purposes:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * -# Enforce our own search path restrictions.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * -# Prevalidate DLLs about to be loaded so we don't upset the loader data
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * by doing it from within the NtCreateSection hook (WinVerifyTrust
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * seems to be doing harm there on W7/32).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszSearchPath The search path to use.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pfFlags Flags on input. DLL characteristics or something
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * on return?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pName The name of the module.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param phMod Where the handle of the loaded DLL is to be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * returned to the caller.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncsupR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_STRING pName, PHANDLE phMod)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Make sure the DLL notification callback is registered. If we could, we
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * would've done this during early process init, but due to lack of heap
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * and uninitialized loader lock, it's not possible that early on.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * The callback protects our NtDll hooks from getting unhooked by
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * "friendly" fire from the AV crowd.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Process WinVerifyTrust todo before and after.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject things we don't want to deal with.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: name is NULL or have a zero length.\n");
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x (pName=%p)\n", STATUS_INVALID_PARAMETER, pName));
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync /*SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject long paths that's close to the 260 limit without looking.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: too long name: %#x bytes\n", pName->Length);
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Absolute path?
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UNICODE_STRING UniStrStatic = { 0, (USHORT)sizeof(wszPath) - sizeof(WCHAR), wszPath };
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [redir]\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer, rcNt));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Not an absolute path. Check if it's one of those special API set DLLs
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * or something we're known to use but should be taken from WinSxS.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if (supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Not an absolute path or special API set. There are two alternatives
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * now, either there is no path at all or there is a relative path. We
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * will resolve it to an absolute path in either case, failing the call
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * if we can't.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool const fNeedDllSuffix = offLastDot == UINT32_MAX && offLastSlash == UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (offLastDot != UINT32_MAX && offLastDot == cwcName - 1)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject relative paths for now as they might be breakout attempts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedMonitor_LdrLoadDll: relative name not permitted: %.*ls\n",
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Perform dll redirection to WinSxS such. We using an undocumented
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * API here, which as always is a bit risky... ASSUMES that the API
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * returns a full DOS path.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Search for the DLL. Only System32 is allowed as the target of
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * a search on the API level, all VBox calls will have full paths.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync AssertCompile(sizeof(g_System32WinPath.awcBuffer) <= sizeof(wszPath));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync cwc = g_System32WinPath.UniStr.Length / sizeof(RTUTF16); Assert(cwc > 2);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcName, pawcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync memcpy(wszPath, g_System32WinPath.UniStr.Buffer, cwc * sizeof(RTUTF16));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [rcNt=%#x]\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer, rcNt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try open the file. If this fails, never mind, just pass it on to
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * the real API as we've replaced any searchable name with a full name
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and the real API can come up with a fitting status code for it.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, wszPath, RTSTR_MAX);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supR3HardenedMonitor_LdrLoadDll: RTNtPathFromWinUtf16Ex failed on '%ls': %Rrc\n", wszPath, rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync 0 /*EaLength*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fCallRealApi = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "LdrLoadDll", false /*fAvoidWinVerifyTrust*/, &fQuietFailure);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: rejecting '%ls': rcNt=%#x\n",
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u (NtPath=%.*ls)\n",
9f997e760f610c92e3a365be21ead6972bc46130vboxsync wszPath, dwErr, NtPathUniStr.Length / sizeof(RTUTF16), NtPathUniStr.Buffer));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Screened successfully enough. Call the real thing.
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls [calling]\n",
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = g_pfnLdrLoadDllReal(pwszSearchPath, pfFlags, pName, phMod);
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * Log the result and process pending WinVerifyTrust work if we can.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x hMod=%p '%ls'\n", rcNt, *phMod, wszPath));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * DLL load and unload notification callback.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This is a safety against our LdrLoadDll hook being replaced by protection
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * software. Though, we prefer the LdrLoadDll hook to this one as it allows us
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * to call WinVerifyTrust more freely.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param ulReason The reason we're called, see
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * LDR_DLL_NOTIFICATION_REASON_XXX.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pData Reason specific data. (Format is currently the same for
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * both load and unload.)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pvUser User parameter (ignored).
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks Vista and later.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks The loader lock is held when we're called, at least on Windows 7.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic VOID CALLBACK supR3HardenedDllNotificationCallback(ULONG ulReason, PCLDR_DLL_NOTIFICATION_DATA pData, PVOID pvUser)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Screen the image on load. We will normally get a verification cache
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * hit here because of the LdrLoadDll and NtCreateSection hooks, so it
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * should be relatively cheap to recheck. In case our NtDll patches
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This ASSUMES that we get informed after the fact as indicated by the
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * available documentation.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (ulReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: load %p LB %#010x %.*ls [fFlags=%#x]\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Convert the windows path to an NT path and open it. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: RTNtPathFromWinUtf16Ex failed on '%.*ls': %Rrc\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, rc);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 0 /*EaLength*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: NtCreateFile failed on '%.*ls' / '%.*ls': %#x\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Do the screening. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync bool fCallRealApi = false;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "LdrLoadDll", true /*fAvoidWinVerifyTrust*/, &fQuietFailure);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: supR3HardenedScreenImage failed on '%.*ls' / '%.*ls': %#x\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Log the unload call.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else if (ulReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: Unload %p LB %#010x %.*ls [flags=%#x]\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Unloaded.DllBase, pData->Unloaded.SizeOfImage,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Unloaded.FullDllName->Length / sizeof(WCHAR), pData->Unloaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Just log things we don't know and then return without caching anything.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: ulReason=%u pData=%p\n", ulReason, pData));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Use this opportunity to make sure our NtDll patches are still in place,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * since they may be replaced by indecent protection software solutions.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Registers the DLL notification callback if it hasn't already been registered.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinRegisterDllNotificationCallback(void)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * The notification API was added in Vista, so it's an optional (weak) import.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NTSTATUS rcNt = LdrRegisterDllNotification(0, supR3HardenedDllNotificationCallback, NULL, &g_pvDllNotificationCookie);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("Registered Dll notification callback with NTDLL.\n"));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedError(rcNt, false /*fFatal*/, "LdrRegisterDllNotification failed: %#x\n", rcNt);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic void supR3HardenedWinHookFailed(const char *pszWhich, uint8_t const *pbPrologue)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "Failed to install %s monitor: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n "
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "(It is also possible you are running 32-bit VirtualBox under 64-bit windows.)\n"
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[0], pbPrologue[1], pbPrologue[2], pbPrologue[3],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[4], pbPrologue[5], pbPrologue[6], pbPrologue[7],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[8], pbPrologue[9], pbPrologue[10], pbPrologue[11],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[12], pbPrologue[13], pbPrologue[14], pbPrologue[15]);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * IPRT thread that waits for the parent process to terminate and reacts by
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * exiting the current process.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @returns VINF_SUCCESS
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param hSelf The current thread. Ignored.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param pvUser The handle of the parent process.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsyncstatic DECLCALLBACK(int) supR3HardenedWinParentWatcherThread(RTTHREAD hSelf, void *pvUser)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Wait for the parent to terminate.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Proxy the termination code of the child, if it exited already.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync SUP_DPRINTF(("supR3HardenedWinParentWatcherThread: Quitting: ExitCode=%#x rcNt=%#x\n", BasicInfo.ExitStatus, rcNt));
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Creates the parent watcher thread that will make sure this process exits when
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * the parent does.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * This is a necessary evil to make VBoxNetDhcp and VBoxNetNat termination from
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Main work without too much new magic. It also makes Ctrl-C or similar work
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * in on the hardened processes in the windows console.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param hVBoxRT The VBoxRT.dll handle. We use RTThreadCreate to
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * spawn the thread to avoid duplicating thread
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * creation and thread naming code from IPRT.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsyncDECLHIDDEN(void) supR3HardenedWinCreateParentWatcherThread(HMODULE hVBoxRT)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Resolve runtime methods that we need.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PFNRTTHREADCREATE pfnRTThreadCreate = (PFNRTTHREADCREATE)GetProcAddress(hVBoxRT, "RTThreadCreate");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Find the parent process ID.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NTSTATUS rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: NtQueryInformationProcess failed: %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Open the parent process for waiting and exitcode query.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync ClientId.UniqueProcess = (HANDLE)BasicInfo.InheritedFromUniqueProcessId;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync rcNt = NtOpenProcess(&hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
0d73750f953d8569054777eab62f40ad88a66d88vboxsync supR3HardenedFatalMsg("supR3HardenedWinCreateParentWatcherThread", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync "NtOpenProcess(%p.0) failed: %#x\n", ClientId.UniqueProcess, rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Create the thread that should do the waiting.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync int rc = pfnRTThreadCreate(NULL, supR3HardenedWinParentWatcherThread, hParent, _64K /* stack */,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ParentWatcher");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: RTThreadCreate failed: %Rrc\n", rc);
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Checks if the calling thread is the only one in the process.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * @returns true if we're positive we're alone, false if not.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsyncstatic bool supR3HardenedWinAmIAlone(void)
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync NTSTATUS rcNt = NtQueryInformationThread(NtCurrentThread(), ThreadAmILastThread, &fAmIAlone, sizeof(fAmIAlone), &cbIgn);
30f07af559efcbd967e801903746fc21f81ee533vboxsync * Simplify NtProtectVirtualMemory interface.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * Modifies protection for the current process. Caller must know the current
30f07af559efcbd967e801903746fc21f81ee533vboxsync * protection as it's not returned.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @returns NT status code.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param pvMem The memory to change protection for.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param cbMem The amount of memory to change.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param fNewProt The new protection.
30f07af559efcbd967e801903746fc21f81ee533vboxsyncstatic NTSTATUS supR3HardenedWinProtectMemory(PVOID pvMem, SIZE_T cbMem, ULONG fNewProt)
30f07af559efcbd967e801903746fc21f81ee533vboxsync return NtProtectVirtualMemory(NtCurrentProcess(), &pvMem, &cbMem, fNewProt, &fOldProt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Installs or reinstalls the NTDLL patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinReInstallHooks(bool fFirstCall)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync const char *pszName;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" },
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync { sizeof(g_abLdrLoadDllPatch), g_abLdrLoadDllPatch, &g_pbLdrLoadDll, "LdrLoadDll" },
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPatches); i++)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (memcmp(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch) != 0)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Log the incident if it's not the initial call.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedWinReInstallHooks: Reinstalling %s (%p: %.*Rhxs).\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync s_aPatches[i].pszName, pbApi, s_aPatches[i].cbPatch, pbApi));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READWRITE));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * If we're alone, just memcpy the patch in.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Not alone. Start by injecting a JMP $-2, then waste some
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * CPU cycles to get the other threads a good chance of getting
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * out of the code before we replace it.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ASMAtomicXchgU32((uint32_t volatile *)pbApi, uJmpDollarMinus.u);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Copy in the tail bytes of the patch, then xchg the jmp $-2. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(&pbApi[4], &s_aPatches[i].pabPatch[4], s_aPatches[i].cbPatch - 4);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ASMAtomicXchgU32((uint32_t volatile *)pbApi, *(uint32_t *)s_aPatches[i].pabPatch);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READ));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Install hooks for intercepting calls dealing with mapping shared libraries
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * into the process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This allows us to prevent undesirable shared libraries from being loaded.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @remarks We assume we're alone in this process, so no seralizing trickery is
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * necessary when installing the patch.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @remarks We would normally just copy the prologue sequence somewhere and add
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * a jump back at the end of it. But because we wish to avoid
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * allocating executable memory, we need to have preprepared assembly
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * "copies". This makes the non-system call patching a little tedious
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and inflexible.
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync * Disable hard error popups so we can quietly refuse images to be loaded.
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr), NULL);
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync "NtQueryInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync rcNt = NtSetInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr));
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync "NtSetInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Locate the routines first so we can allocate memory that's near enough.
a6c871653045073d6ef74d0589de345ae62b607dvboxsync PFNRT pfnNtCreateSection = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "NtCreateSection");
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
a6c871653045073d6ef74d0589de345ae62b607dvboxsync PFNRT pfnLdrLoadDll = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "LdrLoadDll");
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * Exec page setup & management.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook #1 - NtCreateSection.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Purpose: Validate everything that can be mapped into the process before
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * it's mapped and we still have a file handle to work with.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abNtCreateSectionPatch, pbNtCreateSection, sizeof(g_abNtCreateSectionPatch));
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_pfnNtCreateSectionReal = NtCreateSection; /* our direct syscall */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 64-bit hosts.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Pattern #1: XP64/W2K3-64 thru Windows 8.1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000> u ntdll!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1750 4c8bd1 mov r10,rcx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1753 b847000000 mov eax,47h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1758 0f05 syscall
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f175a c3 ret
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f175b 0f1f440000 nop dword ptr [rax+rax]
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync The variant is the value loaded into eax: W2K3=??, Vista=47h?, W7=47h, W80=48h, W81=49h */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[0] = 0x48; /* mov rax, qword */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync *(uint64_t *)&g_abNtCreateSectionPatch[2] = (uint64_t)supR3HardenedMonitor_NtCreateSection;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 32-bit hosts.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Pattern #1: XP thru Windows 7
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync kd> u ntdll!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d160 b832000000 mov eax,32h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d165 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16a ff12 call dword ptr [edx]
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16c c21c00 ret 1Ch
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16f 90 nop
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync The variable bit is the value loaded into eax: XP=32h, W2K3=34h, Vista=4bh, W7=54h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Pattern #2: Windows 8.1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000:x86> u ntdll_6a0f0000!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll_6a0f0000!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eabc b854010000 mov eax,154h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac1 e803000000 call ntdll_6a0f0000!NtCreateSection+0xd (6a15eac9)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac6 c21c00 ret 1Ch
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac9 8bd4 mov edx,esp
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eacb 0f34 sysenter
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eacd c3 ret
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync The variable bit is the value loaded into eax: W81=154h */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[0] = 0xe9; /* jmp rel32 */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook #2 - LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Purpose: (a) Enforce LdrLoadDll search path constraints, and (b) pre-validate
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * DLLs so we can avoid calling WinVerifyTrust from the first hook,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and thus avoiding messing up the loader data on some installations.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * This differs from the above function in that is no a system call and
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * we're at the mercy of the compiler.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 64-bit hosts.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /* Just use the disassembler to skip 12 bytes or more. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Assemble the code for resuming the call.*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0xff; /* jmp qword [$+8 wrt RIP] */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0x25;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = RT_ALIGN_32(offExecPage + 4, 8) - (offExecPage + 4);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint64_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack];
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the LdrLoadDll patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abLdrLoadDllPatch[0] = 0x48; /* mov rax, qword */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync *(uint64_t *)&g_abLdrLoadDllPatch[2] = (uint64_t)supR3HardenedMonitor_LdrLoadDll;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 32-bit hosts.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /* Just use the disassembler to skip 5 bytes or more. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_32BIT, &Dis, &cbInstr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Assemble the code for resuming the call.*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; /* jmp rel32 */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4];
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the LdrLoadDll patch. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *(uint32_t *)&g_abLdrLoadDllPatch[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Seal the rwx page.
30f07af559efcbd967e801903746fc21f81ee533vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(g_abSupHardReadWriteExecPage, PAGE_SIZE, PAGE_EXECUTE_READ));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install the patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(true /*fFirstCall*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Common code used for child and parent to make new threads exit immediately.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This patches the LdrInitializeThunk code to call NtTerminateThread with
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * STATUS_SUCCESS instead of doing the NTDLL initialization.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns VBox status code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process to do this to.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * override.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvNtTerminateThread The address of the NtTerminateThread function in
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the NTDLL instance we're patching. (Must be +/-
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * 2GB from the thunk code.)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pabBackup Where to back up the original instruction bytes
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * at pvLdrInitThunk.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pErrInfo Where to return extended error information.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Optional.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtDisableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, void *pvNtTerminateThread,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint8_t *pabBackup, size_t cbBackup, PRTERRINFO pErrInfo)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtDisableThreadCreation: pvLdrInitThunk=%p pvNtTerminateThread=%p\n", pvLdrInitThunk, pvNtTerminateThread));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(RT_ABS((intptr_t)pvLdrInitThunk - (intptr_t)pvNtTerminateThread) < 16*_1M);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Back up the thunk code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtReadVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreation: NtReadVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Cook up replacement code that calls NtTerminateThread.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(abReplacement, pabBackup, sizeof(abReplacement));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Install the replacment code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, abReplacement, sizeof(abReplacement), &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk/2 failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Undo the effects of supR3HardNtDisableThreadCreationEx.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns VBox status code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process to do this to.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * override.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pabBackup Where to back up the original instruction bytes
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * at pvLdrInitThunk.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pErrInfo Where to return extended error information.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Optional.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtEnableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, uint8_t const *pabBackup, size_t cbBackup,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtEnableThreadCreation:\n"));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtEnableThreadCreation: NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtEnableThreadCreation: NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Disable thread creation for the current process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @remarks Doesn't really disables it, just makes the threads exit immediately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * without executing any real code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardenedWinDisableThreadCreation(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Cannot use the imported NtTerminateThread as it's pointing to our own
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync syscall assembly code. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync s_pfnNtTerminateThread = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "NtTerminateThread");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardNtDisableThreadCreationEx(NtCurrentProcess(),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Undoes the effects of supR3HardenedWinDisableThreadCreation.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncDECLHIDDEN(void) supR3HardenedWinEnableThreadCreation(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardNtEnableThreadCreationEx(NtCurrentProcess(),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Gets the SID of the user associated with the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns @c true if we've got a login SID, @c false if not.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSidUser Where to return the user SID.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbSidUser The size of the user SID buffer.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSidLogin Where to return the login SID.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbSidLogin The size of the login SID buffer.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic bool supR3HardNtChildGetUserAndLogSids(PSID pSidUser, ULONG cbSidUser, PSID pSidLogin, ULONG cbSidLogin)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtQueryInformationToken(hToken, TokenUser, &uBuf, sizeof(uBuf), &cbRet));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidUser, pSidUser, uBuf.UserInfo.User.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fLoginSid = false;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryInformationToken(hToken, TokenLogonSid, &uBuf, sizeof(uBuf), &cbRet);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ((uBuf.Groups.Groups[i].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidLogin, pSidLogin, uBuf.Groups.Groups[i].Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Build security attributes for the process or the primary thread (@a fProcess)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process DACLs can be bypassed using the SeDebugPrivilege (generally available
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * to admins, i.e. normal windows users), or by taking ownership and/or
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * modifying the DACL. However, it restricts
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSecAttrs Where to return the security attributes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pCleanup Cleanup record.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param fProcess Set if it's for the process, clear if it's for
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the primary thread.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildInitSecAttrs(PSECURITY_ATTRIBUTES pSecAttrs, PMYSECURITYCLEANUP pCleanup, bool fProcess)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Safe return values.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync suplibHardenedMemSet(pCleanup, 0, sizeof(*pCleanup));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** @todo This isn't at all complete, just sketches... */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Create an ACL detailing the access of the above groups.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateAcl(&pCleanup->Acl.AclHdr, sizeof(pCleanup->Acl), ACL_REVISION));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION | PROCESS_VM_WRITE
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_SET_QUOTA
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)) /* Introduced in Windows 8.1. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= THREAD_SUSPEND_RESUME | THREAD_SET_CONTEXT | THREAD_SET_INFORMATION | THREAD_SET_THREAD_TOKEN
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | THREAD_IMPERSONATE | THREAD_DIRECT_IMPERSONATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= THREAD_QUERY_LIMITED_INFORMATION | THREAD_SET_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= ~fAllow & (SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Deny everyone access to bad bits. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Everyone.Sid, &SIDAuthWorld, 1));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *RtlSubAuthoritySid(&pCleanup->Everyone.Sid, 0) = SECURITY_WORLD_RID;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Grant some access to the owner - doesn't work. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthCreator = SECURITY_CREATOR_SID_AUTHORITY;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Owner.Sid, &SIDAuthCreator, 1));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *RtlSubAuthoritySid(&pCleanup->Owner.Sid, 0) = SECURITY_CREATOR_OWNER_RID;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fHasLoginSid = supR3HardNtChildGetUserAndLogSids(&pCleanup->User.Sid, sizeof(pCleanup->User),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Grant minimal access to the user. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Grant very limited access to the login sid. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create a security descriptor with the above ACL.
30f07af559efcbd967e801903746fc21f81ee533vboxsync PSECURITY_DESCRIPTOR pSecDesc = (PSECURITY_DESCRIPTOR)RTMemAllocZ(SECURITY_DESCRIPTOR_MIN_LENGTH);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlSetDaclSecurityDescriptor(pSecDesc, TRUE /*fDaclPresent*/, &pCleanup->Acl.AclHdr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Predicate function which tests whether @a ch is a argument separator
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * character.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param ch The character to examine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLINLINE(bool) suplibCommandLineIsArgSeparator(int ch)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Construct the new command line.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Since argc/argv are both derived from GetCommandLineW (see
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * suplibHardenedWindowsMain), we skip the argument by argument UTF-8 -> UTF-16
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * conversion and quoting by going to the original source.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The executable name, though, is replaced in case it's not a fullly
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * qualified path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The re-spawn indicator is added immediately after the executable name
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * so that we don't get tripped up missing close quote chars in the last
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * argument.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to a command line string (heap).
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pUniStr Unicode string structure to initialize to the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * command line. Optional.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param iWhich Which respawn we're to check for, 1 being the first
edde275acba04aca58db4172a163741e3abadfbcvboxsync * one, and 2 the second and final.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PRTUTF16 supR3HardNtChildConstructCmdLine(PUNICODE_STRING pString, int iWhich)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the command line and skip the executable name.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync uint32_t cwcArgs = pCmdLineStr->Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Skip leading space (shouldn't be any, but whatever). */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs) )
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT(cwcArgs > 0 && *pawcArgs != '\0');
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Walk to the end of it. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int fQuoted = false;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync else if (*pawcArgs != '\\' || (pawcArgs[1] != '\\' && pawcArgs[1] != '"'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cSlashes = 0;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (cwcArgs > 0 && *pawcArgs == '"' && (cSlashes & 1))
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--, pawcArgs++; /* odd number of slashes == escaped quote */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync } while (cwcArgs > 0 && (fQuoted || !suplibCommandLineIsArgSeparator(*pawcArgs)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Skip trailing spaces. */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Allocate a new buffer.
edde275acba04aca58db4172a163741e3abadfbcvboxsync AssertCompile(sizeof(SUPR3_RESPAWN_1_ARG0) == sizeof(SUPR3_RESPAWN_2_ARG0));
edde275acba04aca58db4172a163741e3abadfbcvboxsync size_t cwcCmdLine = (sizeof(SUPR3_RESPAWN_1_ARG0) - 1) / sizeof(SUPR3_RESPAWN_1_ARG0[0]) /* Respawn exe name. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync + !!cwcArgs + cwcArgs; /* if arguments present, add space + arguments. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardNtChildConstructCmdLine", kSupInitOp_Misc, VERR_OUT_OF_RANGE,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Command line is too long (%u chars)!", cwcCmdLine);
30f07af559efcbd967e801903746fc21f81ee533vboxsync PRTUTF16 pwszCmdLine = (PRTUTF16)RTMemAlloc((cwcCmdLine + 1) * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct the new command line.
edde275acba04aca58db4172a163741e3abadfbcvboxsync for (const char *pszSrc = iWhich == 1 ? SUPR3_RESPAWN_1_ARG0 : SUPR3_RESPAWN_2_ARG0; *pszSrc; pszSrc++)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync suplibHardenedMemCopy(pwszDst, pawcArgs, cwcArgs * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(pwszDst - pwszCmdLine == cwcCmdLine);
edde275acba04aca58db4172a163741e3abadfbcvboxsync pString->Length = (USHORT)(cwcCmdLine * sizeof(WCHAR));
edde275acba04aca58db4172a163741e3abadfbcvboxsync pString->MaximumLength = pString->Length + sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Terminates the child process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process handle.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhere Who's having child rasing troubles.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param rc The status code to report.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszFormat The message format string.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param ... Message format arguments.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardenedWinKillChild(HANDLE hProcess, const char *pszWhere, int rc, const char *pszFormat, ...)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Terminate the process ASAP and display error.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedErrorV(rc, false /*fFatal*/, pszFormat, va);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the process to really go away.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && supR3HardenedWinGetMilliTS() - uMsTsStart < 60 * 1000);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtDuplicateObject failed and we failed to kill child: rc=%u (%#x) rcNtWait=%#x hProcess=%p\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Final error message.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsgV(pszWhere, kSupInitOp_Misc, rc, pszFormat, va);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Checks the child process when hEvtParent is signalled.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This will read the request data from the child and check it against expected
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * request. If an error is signalled, we'll raise it and make sure the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * terminates before terminating the calling process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param enmExpectedRequest The expected child request.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhat What we're waiting for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildProcessRequest(PSUPR3HARDNTCHILD pThis, SUPR3WINCHILDREQ enmExpectedRequest, const char *pszWhat)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Read the process parameters from the child.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uChildAddr = (uintptr_t)pThis->Peb.ImageBaseAddress
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtReadVirtualMemory(pThis->hProcess, (PVOID)uChildAddr,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &pThis->ProcParams, sizeof(pThis->ProcParams), &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildProcessRequest", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtReadVirtualMemory(,%p,) failed reading child process status: %#x\n", uChildAddr, rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Is it the expected request?
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmRequest == enmExpectedRequest)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * No, not the expected request. If it's an error request, tell the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * to terminate itself, otherwise we'll have to terminate it.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szErrorMsg[sizeof(pThis->ProcParams.szErrorMsg) - 1] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szWhere[sizeof(pThis->ProcParams.szWhere) - 1] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinCheckChild: enmRequest=%d rc=%d enmWhat=%d %s: %s\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest, pThis->ProcParams.rc, pThis->ProcParams.enmWhat,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szWhere, pThis->ProcParams.szErrorMsg));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmRequest != kSupR3WinChildReq_Error)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinCheckChild", VERR_INVALID_PARAMETER,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Unexpected child request #%d. Was expecting #%d (%s).\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest, enmExpectedRequest, pszWhat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildProcessRequest", rcNt, "NtSetEvent failed: %#x\n", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Wait for it to terminate. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWaitForSingleObject(pThis->hProcess, FALSE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildProcessRequest: Child is taking too long to quit (rcWait=%#x), killing it...\n", rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(pThis->hProcess, DBG_TERMINATE_PROCESS);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Report the error in the same way as it occured in the guest.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmWhat == kSupInitOp_Invalid)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardenedWinCheckChild", kSupInitOp_Misc, pThis->ProcParams.rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg(pThis->ProcParams.szWhere, pThis->ProcParams.enmWhat, pThis->ProcParams.rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Waits for the child to make a certain request or terminate.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The stub process will also wait on it's parent to terminate.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This call will only return if the child made the expected request.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param enmExpectedRequest The child request to wait for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cMsTimeout The number of milliseconds to wait (at least).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhat What we're waiting for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildWaitFor(PSUPR3HARDNTCHILD pThis, SUPR3WINCHILDREQ enmExpectedRequest, RTMSINTERVAL cMsTimeout,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync const char *pszWhat)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The wait loop.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Will return when the expected request arrives.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Will break out when one of the processes terminates.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Assemble handles to wait for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Do the waiting according to the callers wishes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*Timeout*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = -(int64_t)(cMsTimeout - cMsElapsed) * 10000;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process child request.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNtWait == STATUS_WAIT_0 + 1 && pThis->hEvtParent != NULL)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildProcessRequest(pThis, enmExpectedRequest, pszWhat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildWaitFor: Found expected request %d (%s) after %llu ms.\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync enmExpectedRequest, pszWhat, supR3HardenedWinGetMilliTS() - uMsTsStart));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return; /* Expected request received. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process termination?
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( (ULONG)rcNtWait - (ULONG)STATUS_WAIT_0 < cHandles
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || (ULONG)rcNtWait - (ULONG)STATUS_ABANDONED_WAIT_0 < cHandles)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Check sanity.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildWaitFor", rcNtWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtWaitForMultipleObjects returned %#x waiting for #%d (%s)\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Calc elapsed time for the next timeout calculation, checking to see
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * if we've timed out already.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cMsElapsed = supR3HardenedWinGetMilliTS() - uMsTsStart;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNtWait == STATUS_USER_APC || rcNtWait == STATUS_ALERTED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* We timed out. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildWaitFor", rcNtWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Timed out after %llu ms waiting for child request #%d (%s).\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Proxy the termination code of the child, if it exited already.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt1 = NtQueryInformationProcess(pThis->hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt2 = NtTerminateProcess(pThis->hProcess, RTEXITCODE_FAILURE);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = NT_SUCCESS(rcNt2) ? -20000000 /* 2 sec */ : -1280000 /* 128 ms */;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt3 = NtWaitForSingleObject(pThis->hProcess, FALSE /*Alertable*/, NULL /*Timeout*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildWaitFor[%d]: Quitting: ExitCode=%#x (rcNtWait=%#x, rcNt1=%#x, rcNt2=%#x, rcNt3=%#x, %llu ms, %s);\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->iWhich, BasicInfo.ExitStatus, rcNtWait, rcNt1, rcNt2, rcNt3,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinGetMilliTS() - uMsTsStart, pszWhat));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Closes full access child thread and process handles, making a harmless
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * duplicate of the process handle first.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The hProcess member of the child process data structure will be change to the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * harmless handle, while the hThread will be set to NULL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildCloseFullAccessHandles(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The thread handle.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", rcNt, "NtClose(hThread) failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Duplicate the process handle into a harmless one.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_VM_READ;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardenedWinDoReSpawn: NtDuplicateObject(,,,,%#x,,) -> %#x, retrying with only %#x...\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Close the process handle and replace it with the harmless one.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtClose failed on child process handle: %#x\n", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This restores the child PEB and tweaks a couple of fields before we do the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * child purification and let the process run normally.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildSanitizePeb(PSUPR3HARDNTCHILD pThis)
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Make a copy of the pre-execution PEB.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * There should not be any activation context, so if there is, we scratch the memory associated with it.
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.pShimData && !((uintptr_t)Peb.pShimData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.pShimData, PAGE_SIZE, "pShimData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.ActivationContextData && !((uintptr_t)Peb.ActivationContextData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ActivationContextData, PAGE_SIZE, "ActivationContextData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.ProcessAssemblyStorageMap && !((uintptr_t)Peb.ProcessAssemblyStorageMap & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "ProcessAssemblyStorageMap", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.SystemDefaultActivationContextData && !((uintptr_t)Peb.SystemDefaultActivationContextData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "SystemDefaultActivationContextData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.SystemAssemblyStorageMap && !((uintptr_t)Peb.SystemAssemblyStorageMap & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.SystemAssemblyStorageMap, PAGE_SIZE, "SystemAssemblyStorageMap", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Clear compatibility and activation related fields.
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*Peb.Diff0.W6.IsProtectedProcess = 1;*/
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Write back the PEB.
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildSanitizePeb", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Purifies the child process after very early init has been performed.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildPurify(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We loop until we no longer make any fixes. This is similar to what
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * we do (or used to do, really) in the fAvastKludge case of
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * supR3HardenedWinInit. We might be up against asynchronous changes,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * which we fudge by waiting a short while before earch purification. This
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * is arguably a fragile technique, but it's currently the best we've got.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Fortunately, most AVs seems to either favor immediate action on initial
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * load events or (much better for us) later events like kernel32.
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync uint64_t uMsTsOuterStart = supR3HardenedWinGetMilliTS();
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync } while ( supR3HardenedWinGetMilliTS() - uMsTsStart <= cMsFudge
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: Startup delay kludge #1/%u: %u ms, %u sleeps\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync iLoop, supR3HardenedWinGetMilliTS() - uMsTsStart, cSleeps));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supHardenedWinVerifyProcess(pThis->hProcess, pThis->hThread, SUPHARDNTVPKIND_CHILD_PURIFICATION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildPurify", rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supHardenedWinVerifyProcess failed with %Rrc: %s", g_ErrInfoStatic.szMsg);
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: Done after %llu ms and %u fixes (loop #%u).\n",
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync supR3HardenedWinGetMilliTS() - uMsTsOuterStart, cTotalFixes, iLoop));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return; /* We're probably good. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Log the KiOpPrefetchPatchCount value if available, hoping it might
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * sched some light on spider38's case.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n",
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We've given up fixing the child process. Probably fighting someone
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * that monitors their patches or/and our activities.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildPurify", VERR_TRY_AGAIN,
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync "Unable to purify child process! After 16 tries over %llu ms, we still %u fix(es) in the last pass.",
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync supR3HardenedWinGetMilliTS() - uMsTsOuterStart, cFixes);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Sets up the early process init.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildSetUpChildInit(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t const uChildExeAddr = (uintptr_t)pThis->Peb.ImageBaseAddress;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Plant the process parameters. This ASSUMES the handle inheritance is
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * performed when creating the child process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest = kSupR3WinChildReq_Error;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uintptr_t uChildAddr = uChildExeAddr + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, (PVOID)uChildAddr, &pThis->ProcParams,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtWriteVirtualMemory(,%p,) failed writing child process parameters: %#x\n", uChildAddr, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Locate the LdrInitializeThunk address in the child as well as pristine
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * code bits for it.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbChildNtDllBits, pThis->uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbChildNtDllBits, pThis->uNtDllAddr, UINT32_MAX,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedWinSetupChildInit: uLdrInitThunk=%p\n", (uintptr_t)uLdrInitThunk));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Calculate the address of our code in the child process.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uintptr_t uEarlyProcInitEP = uChildExeAddr + ( (uintptr_t)&supR3HardenedEarlyProcessInitThunk
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Compose the LdrInitializeThunk replacement bytes.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Note! The amount of code we replace here must be less or equal to what
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * the process verification code ignores.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(abNew, pbChildNtDllBits + ((uintptr_t)uLdrInitThunk - pThis->uNtDllAddr), sizeof(abNew));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync *(uint32_t *)&abNew[1] = uEarlyProcInitEP - ((uint32_t)uLdrInitThunk + 5);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Install the LdrInitializeThunk replacement code in the child process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(pThis->hProcess, pvLdrInitThunk, abNew, sizeof(abNew), &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /* Caller starts child execution. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedWinSetupChildInit: Start child.\n"));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This messes with the child PEB before we trigger the initial image events.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildScrewUpPebForInitialImageEvents(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Not sure if any of the cracker software uses the PEB at this point, but
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * just in case they do make some of the PEB fields a little less useful.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Make ImageBaseAddress useless. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress ^ UINT32_C(0x5f139000));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress | UINT64_C(0x0313000000000000));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Write the PEB.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildScrewUpPebForInitialImageEvents", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Check if the zero terminated NT unicode string is the path to the given
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * system32 DLL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns true if it is, false if not.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pUniStr The zero terminated NT unicode string path.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszName The name of the system32 DLL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic bool supR3HardNtIsNamedSystem32Dll(PUNICODE_STRING pUniStr, const char *pszName)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pUniStr->Length > g_System32NtPath.UniStr.Length)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (memcmp(pUniStr->Buffer, g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length) == 0)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR)] == '\\')
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (RTUtf16ICmpAscii(&pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR) + 1], pszName) == 0)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return true;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return false;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Worker for supR3HardNtChildGatherData that locates NTDLL in the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildFindNtdll(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Find NTDLL in this process first and take that as a starting point.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllParentAddr = (uintptr_t)GetModuleHandleW(L"ntdll.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(pThis->uNtDllParentAddr != 0 && !(pThis->uNtDllParentAddr & PAGE_OFFSET_MASK));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Scan the virtual memory of the child.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Query information. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync (void const *)uPtrWhere,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Get the image name. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (supR3HardNtIsNamedSystem32Dll(&uBuf.UniStr, "ntdll.dll"))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllAddr = (uintptr_t)MemInfo.AllocationBase;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChFindNtdll: uNtDllParentAddr=%p uNtDllChildAddr=%p\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildFindNtdll", VERR_MODULE_NOT_FOUND, "ntdll.dll not found in child process.");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Gather child data.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param This The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildGatherData(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Basic info.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryInformationProcess(pThis->hProcess, ProcessBasicInformation,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &pThis->BasicInfo, sizeof(pThis->BasicInfo), &cbActual);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildGatherData", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtQueryInformationProcess/ProcessBasicInformation failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * If this is the middle (stub) process, we wish to wait for both child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * and parent. So open the parent process. Not fatal if we cannnot.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ClientId.UniqueProcess = (HANDLE)pThis->BasicInfo.InheritedFromUniqueProcessId;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtOpenProcess(&pThis->hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildGatherData: Failed to open parent process (%#p): %#x\n", ClientId.UniqueProcess, rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process environment block.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildGatherData: PebBaseAddress=%p cbPeb=%#x\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtReadVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &pThis->Peb, sizeof(pThis->Peb), &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildGatherData", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Locate NtDll.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Does the actually respawning.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @returns Never, will call exit or raise fatal error.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param iWhich Which respawn we're to check for, 1 being the
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * first one, and 2 the second and final.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PRTL_USER_PROCESS_PARAMETERS pParentProcParams = pPeb->ProcessParameters;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Init the child process data structure, creating the child communication
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * event sempahores.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&This.hEvtChild, EVENT_ALL_ACCESS, &ObjAttrs, SynchronizationEvent, FALSE));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&This.hEvtParent, EVENT_ALL_ACCESS, &ObjAttrs, SynchronizationEvent, FALSE));
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Set up security descriptors.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildInitSecAttrs(&ThreadSecAttrs, &ThreadSecAttrsCleanup, false /*fProcess*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Configure the startup info and creation flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo experiment with protected process stuff later on. */
a505d18eaecf5f7faff58cc7c05397f8adaf6d71vboxsync SiEx.StartupInfo.dwFlags |= pParentProcParams->WindowFlags & STARTF_USESHOWWINDOW;
0aab9cd857ec35928a0e61c68d3f27a5b4d88a95vboxsync SiEx.StartupInfo.wShowWindow = (WORD)pParentProcParams->ShowWindowFlags;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdInput = pParentProcParams->StandardInput;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdOutput = pParentProcParams->StandardOutput;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdError = pParentProcParams->StandardError;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct the command line and launch the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PRTUTF16 pwszCmdLine = supR3HardNtChildConstructCmdLine(NULL, iWhich);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Error relaunching VirtualBox VM process: %u\n"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Command line: '%ls'",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [kernel32].\n",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync iWhich, ProcessInfoW32.dwProcessId, ProcessInfoW32.dwThreadId));
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Construct the process parameters.
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.Buffer = g_wszSupLibHardenedExePath; /* Yes the windows name for the process parameters. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.Length = (USHORT)RTUtf16Len(g_wszSupLibHardenedExePath) * sizeof(WCHAR);
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.MaximumLength = W32ImageName.Length + sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildConstructCmdLine(&CmdLine, iWhich);
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateProcessParameters(&pProcParams,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* CurrentDirectory - inherit from this process */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* Environment - inherit from this process */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* RuntimeInfo - none (byte array for MSVCRT file info) */)
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** @todo this doesn't work. :-( */
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->ConsoleHandle = pParentProcParams->ConsoleHandle;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->ConsoleFlags = pParentProcParams->ConsoleFlags;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardInput = pParentProcParams->StandardInput;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardOutput = pParentProcParams->StandardOutput;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardError = pParentProcParams->StandardError;
edde275acba04aca58db4172a163741e3abadfbcvboxsync RTL_USER_PROCESS_INFORMATION ProcessInfoNt = { sizeof(ProcessInfoNt) };
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = RtlCreateUserProcess(&g_SupLibHardenedExeNtPath.UniStr,
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Error relaunching VirtualBox VM process: %#x\n"
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Command line: '%ls'",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [ntdll].\n",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync iWhich, ProcessInfo.ClientId.UniqueProcess, ProcessInfo.ClientId.UniqueThread));
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Apply anti debugger notification trick to the thread. (Also done in
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync * supR3HardenedWinInit.) This may fail with STATUS_ACCESS_DENIED and
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync * maybe other errors.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtSetInformationThread(This.hThread, ThreadHideFromDebugger, NULL, 0);
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync SUP_DPRINTF(("supR3HardenedWinReSpawn: NtSetInformationThread/ThreadHideFromDebugger failed: %#x (harmless)\n", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Perform very early child initialization.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildScrewUpPebForInitialImageEvents(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtResumeThread(This.hThread, &cSuspendCount);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(&This, "supR3HardenedWinDoReSpawn", rcNt, "NtResumeThread failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Santizie the pre-NTDLL child when it's ready.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * AV software and other things injecting themselves into the embryonic
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * and budding process to intercept API calls and what not. Unfortunately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * this is also the behavior of viruses, malware and other unfriendly
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * software, so we won't stand for it. AV software can scan our image
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * as they are loaded via kernel hooks, that's sufficient. No need for
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * patching half of NTDLL or messing with the import table of the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * process executable.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_PurifyChildAndCloseHandles, 2000 /*ms*/, "PurifyChildAndCloseHandles");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Close the unrestricted access handles. Since we need to wait on the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * child process, we'll reopen the process with limited access before doing
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * away with the process handle returned by CreateProcess.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Signal the child that we've closed the unrestricted handles and it can
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * safely try open the driver.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(&This, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync "NtSetEvent failed on child process handle: %#x\n", rcNt);
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync * Ditch the loader cache so we don't sit on too much memory while waiting.
71e448b6623e801f76cb68355a28500169de5695vboxsync * Enable thread creation at this point so Ctrl-C and Ctrl-Break can be processed.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the child to get to suplibHardenedWindowsMain so we can close the handles.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_CloseEvents, 60000 /*ms*/, "CloseEvents");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the process to terminate.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_End, RT_INDEFINITE_WAIT, "the end");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(false); /* We're not supposed to get here! */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Logs the content of the given object directory.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @returns true if it exists, false if not.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param pszDir The path of the directory to log (ASCII).
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsyncstatic void supR3HardenedWinLogObjDir(const char *pszDir)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Open the driver object directory.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync int rc = RTUtf16CopyAscii(wszDir, RT_ELEMENTS(wszDir), pszDir);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: RTUtf16CopyAscii -> %Rrc on '%s'\n", rc, pszDir));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtDirName.Length = (USHORT)(RTUtf16Len(wszDir) * sizeof(WCHAR));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtDirName.MaximumLength = NtDirName.Length + sizeof(WCHAR);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: %ls => %#x\n", wszDir, rcNt));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Enumerate it, looking for the driver.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: NtQueryDirectoryObject => rcNt=%#x cbActual=%#x\n", rcNt, cbActual));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->TypeName.Length / sizeof(WCHAR), pObjDir->TypeName.Buffer,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->Name.Length / sizeof(WCHAR), pObjDir->Name.Buffer));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Next directory entry. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Clean up and return.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Checks if the driver exists.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * This checks whether the driver is present in the /Driver object directory.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Drivers being initialized or terminated will have an object there
edde275acba04aca58db4172a163741e3abadfbcvboxsync * before/after their devices nodes are created/deleted.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns true if it exists, false if not.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pszDriver The driver name.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsyncstatic bool supR3HardenedWinDriverExists(const char *pszDriver)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Open the driver object directory.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync return true;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Enumerate it, looking for the driver.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync bool fFound = true;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = '\0';
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync && RTUtf16ICmpAscii(pObjDir->Name.Buffer, pszDriver) == 0)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /* Next directory entry. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Clean up and return.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Open the stub device before the 2nd respawn.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszName[] = L"\\Device\\VBoxDrvStub";
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t const uMsTsStart = supR3HardenedWinGetMilliTS();
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync 0 /*EaLength*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /* The STATUS_NO_SUCH_DEVICE might be returned if the device is not
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync completely initialized. Delay a little bit and try again. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (iTry > 0 && supR3HardenedWinGetMilliTS() - uMsTsStart > 5000) /* 5 sec, at least two tries */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /** @todo Consider starting the VBoxdrv.sys service. Requires 2nd process
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * though, rather complicated actually as CreateProcess causes all
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * kind of things to happen to this process which would make it hard to
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * pass the process verification tests... :-/ */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync Time.QuadPart = -1000000 / 100; /* 1ms in 100ns units, relative time. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync Time.QuadPart = -32000000 / 100; /* 32ms in 100ns units, relative time. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Report trouble (fatal). For some errors codes we try gather some
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * extra information that goes into VBoxStartup.log so that we stand a
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * better chance resolving the issue.
40839c441cb305d84420565f7ca25403d8177413vboxsync if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * \Windows\ApiPort open trouble. So far only
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * STATUS_OBJECT_TYPE_MISMATCH has been observed.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync RTStrPrintf(szDir, sizeof(szDir), "\\Sessions\\%u\\Windows", uSessionId);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, rc,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Error getting %s\\ApiPort in the driver from vboxdrv.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Could be due to security software is redirecting access to it, so please include full "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "details of such software in a bug report. VBoxStartup.log may contain details important "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "to resolving the issue."
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Generic VBox failure message.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, rc,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt);
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_NO_SUCH_DEVICE: pszDefine = " STATUS_NO_SUCH_DEVICE"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_OBJECT_NAME_NOT_FOUND: pszDefine = " STATUS_OBJECT_NAME_NOT_FOUND"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_ACCESS_DENIED: pszDefine = " STATUS_ACCESS_DENIED"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_TRUST_FAILURE: pszDefine = " STATUS_TRUST_FAILURE"; break;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Problems opening the device is generally due to driver load/
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * unload issues. Check whether the driver is loaded and make
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * suggestions accordingly.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** @todo don't fail during early init, wait till later and try load the driver if missing or at least query the service manager for additional information. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: %s\n", pszDefine));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Driver is probably stuck stopping/starting. Try 'sc.exe query vboxdrv' to get more "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "information about its state. Rebooting may actually help.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Driver is does not appear to be loaded. Try 'sc.exe start vboxdrv', reinstall "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "VirtualBox or reboot.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Generic NT failure message. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n", s_wszName, rcNt, pszDefine, iTry);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns Program exit code.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Before the 2nd respawn we set up a child protection deal with the
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * support driver via /Devices/VBoxDrvStub. (We tried to do this
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * during the early init, but in case we had trouble accessing vboxdrv we
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * retry it here where we have kernel32.dll and others to pull in for
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * better diagnostics.)
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Make sure we're alone in the stub process before creating the VM process
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * and that there isn't any debuggers attached.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync int rc = supHardNtVpDebugger(NtCurrentProcess(), RTErrInfoInitStatic(&g_ErrInfoStatic));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync rc = supHardNtVpThread(NtCurrentProcess(), NtCurrentThread(), RTErrInfoInitStatic(&g_ErrInfoStatic));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Integrity, rc, "%s", g_ErrInfoStatic.szMsg);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Respawn the process with kernel protection for the new process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(false); /* We're not supposed to get here! */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Checks if re-spawning is required, replacing the respawn argument if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if required, false if not. In the latter case, the first
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * argument in the vector is replaced.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param iWhich Which respawn we're to check for, 1 being the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * first one, and 2 the second and final.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cArgs The number of arguments.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param papszArgs Pointer to the argument vector.
edde275acba04aca58db4172a163741e3abadfbcvboxsyncDECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
edde275acba04aca58db4172a163741e3abadfbcvboxsync return true;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
edde275acba04aca58db4172a163741e3abadfbcvboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Replace the argument. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Initializes the windows verficiation bits and other things we're better off
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * doing after main() has passed on it's data.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags The main flags.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param fAvastKludge Whether to apply the avast kludge.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsyncDECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install a anti debugging hack before we continue. This prevents most
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * notifications from ending up in the debugger. (Also applied to the
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * child process when respawning.)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Init the verifier.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardenedWinInitImageVerifier(&g_ErrInfoStatic.Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rc,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supHardenedWinInitImageVerifier failed: %s", g_ErrInfoStatic.szMsg);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Get the windows system directory from the KnownDlls dir.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync UNICODE_STRING UniStr = RTNT_CONSTANT_UNISTR(L"\\KnownDlls\\KnownDllPath");
9f997e760f610c92e3a365be21ead6972bc46130vboxsync InitializeObjectAttributes(&ObjAttrs, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
96d40ac897d5f0fd08ee7112800b4beab249179evboxsync rcNt = NtOpenSymbolicLinkObject(&hSymlink, SYMBOLIC_LINK_QUERY, &ObjAttrs);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error opening '%ls': %#x", UniStr.Buffer, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.Buffer = g_System32WinPath.awcBuffer;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.MaximumLength = sizeof(g_System32WinPath.awcBuffer) - sizeof(RTUTF16);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = NtQuerySymbolicLinkObject(hSymlink, &g_System32WinPath.UniStr, NULL);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error querying '%ls': %#x", UniStr.Buffer, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.Buffer[g_System32WinPath.UniStr.Length / sizeof(RTUTF16)] = '\0';
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("KnownDllPath: %ls\n", g_System32WinPath.UniStr.Buffer));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Do a self purification to cure avast's weird NtOpenFile write-thru
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * change in GetBinaryTypeW change in kernel32. Unfortunately, avast
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * uses a system thread to perform the process modifications, which
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * means it's hard to make sure it had the chance to make them...
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * We have to resort to kludge doing yield and sleep fudging for a
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * number of milliseconds and schedulings before we can hope that avast
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * and similar products have done what they need to do. If we do any
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * fixes, we wait for a while again and redo it until we're clean.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * This is unfortunately kind of fragile.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync } while ( supR3HardenedWinGetMilliTS() - uMsTsStart <= cMsFudge
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n",
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync iLoop, supR3HardenedWinGetMilliTS() - uMsTsStart, cSleeps));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n",
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries));
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * Install the hooks.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Complain about Vista w/o service pack if we're launching a VM.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_uNtVerCombined < SUP_MAKE_NT_VER_COMBINED(6, 0, 6001, 0, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, VERR_NOT_SUPPORTED,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Window Vista without any service pack installed is not supported. Please install the latest service pack.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Converts the Windows command line string (UTF-16) to an array of UTF-8
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * arguments suitable for passing to main().
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the argument array.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param pawcCmdLine The UTF-16 windows command line to parse.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param cwcCmdLine The length of the command line.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcArgs Where to return the number of arguments.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsyncstatic char **suplibCommandLineToArgvWStub(PCRTUTF16 pawcCmdLine, size_t cwcCmdLine, int *pcArgs)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the command line string to UTF-8.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT(RT_SUCCESS(RTUtf16ToUtf8Ex(pawcCmdLine, cwcCmdLine, &pszCmdLine, 0, NULL)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Parse the command line, carving argument strings out of it.
30f07af559efcbd967e801903746fc21f81ee533vboxsync char **papszArgs = (char **)RTMemAllocZ(sizeof(char *) * cArgsAllocated);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* skip leading blanks. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Add argument to the vector. */
30f07af559efcbd967e801903746fc21f81ee533vboxsync papszArgs = (char **)RTMemRealloc(papszArgs, sizeof(char *) * cArgsAllocated);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Unquote and unescape the string. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fQuoted = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (ch != '\\' || (*pszSrc != '\\' && *pszSrc != '"'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cSlashes = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cSlashes-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (ch != '\0' && (fQuoted || !suplibCommandLineIsArgSeparator(ch)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Terminate the argument. */
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Logs information about a file from a protection product or from Windows.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * The purpose here is to better see which version of the product is installed
100b161379af7255c69e27587cc746e5f76ff050vboxsync * and not needing to depend on the user supplying the correct information.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @param pwszFile The NT path to the file.
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * @param fAdversarial Set if from a protection product, false if
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * system file.
85f99ad10a7b126cf312171061d363fe56302bdavboxsyncstatic void supR3HardenedLogFileInfo(PCRTUTF16 pwszFile, bool fAdversarial)
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Open the file.
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Length = (USHORT)(RTUtf16Len(pwszFile) * sizeof(WCHAR));
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
100b161379af7255c69e27587cc746e5f76ff050vboxsync InitializeObjectAttributes(&ObjAttr, &UniStrName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync 0 /*EaLength*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Print basic file information available via NtQueryInformationFile.
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.BasicInfo, sizeof(u.BasicInfo), FileBasicInformation);
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" CreationTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.CreationTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*SUP_DPRINTF((" LastAccessTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastAccessTime.QuadPart), szTmp, sizeof(szTmp))));*/
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" LastWriteTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastWriteTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" ChangeTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.ChangeTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileAttributes: %#x\n", u.BasicInfo.FileAttributes));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileBasicInformation -> %#x %#x\n", rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.StdInfo, sizeof(u.StdInfo), FileStandardInformation);
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Size: %#llx\n", u.StdInfo.EndOfFile.QuadPart));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileStandardInformation -> %#x %#x\n", rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Read the image header and extract the timestamp and other useful info.
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (offNtHdrs < sizeof(u) - sizeof(IMAGE_NT_HEADERS))
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_NT_HEADERS64 pNtHdrs64 = (PIMAGE_NT_HEADERS64)&u.abBuf[offNtHdrs];
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_NT_HEADERS32 pNtHdrs32 = (PIMAGE_NT_HEADERS32)&u.abBuf[offNtHdrs];
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Machine: %#x%s\n", pNtHdrs64->FileHeader.Machine,
100b161379af7255c69e27587cc746e5f76ff050vboxsync pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ? " - i386"
100b161379af7255c69e27587cc746e5f76ff050vboxsync : pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ? " - amd64" : ""));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
100b161379af7255c69e27587cc746e5f76ff050vboxsync pNtHdrs64->OptionalHeader.MajorImageVersion, pNtHdrs64->OptionalHeader.MinorImageVersion));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" SizeOfImage: %#x (%u)\n", pNtHdrs64->OptionalHeader.SizeOfImage, pNtHdrs64->OptionalHeader.SizeOfImage));
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Very crude way to extract info from the file version resource.
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_SECTION_HEADER paSectHdrs = (PIMAGE_SECTION_HEADER)( (uintptr_t)&pNtHdrs64->OptionalHeader
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)
100b161379af7255c69e27587cc746e5f76ff050vboxsync && pNtHdrs64->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync RsrcDir = pNtHdrs64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
100b161379af7255c69e27587cc746e5f76ff050vboxsync else if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
100b161379af7255c69e27587cc746e5f76ff050vboxsync && pNtHdrs32->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync RsrcDir = pNtHdrs32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Resource Dir: %#x LB %#x\n", RsrcDir.VirtualAddress, RsrcDir.Size));
100b161379af7255c69e27587cc746e5f76ff050vboxsync && (uintptr_t)&u + sizeof(u) - (uintptr_t)paSectHdrs
100b161379af7255c69e27587cc746e5f76ff050vboxsync >= pNtHdrs64->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) )
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < pNtHdrs64->FileHeader.NumberOfSections; i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress < paSectHdrs[i].SizeOfRawData
100b161379af7255c69e27587cc746e5f76ff050vboxsync + (paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress);
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct { PCRTUTF16 pwsz; size_t cb; } s_abFields[] =
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define MY_WIDE_STR_TUPLE(a_sz) { L ## a_sz, sizeof(L ## a_sz) - sizeof(RTUTF16) }
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_abFields); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcLeft = (sizeof(u) - s_abFields[i].cb - 10) / sizeof(RTUTF16);
100b161379af7255c69e27587cc746e5f76ff050vboxsync while (cwcLeft-- > 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (memcmp(pwc + 1, s_abFields[i].pwsz, s_abFields[i].cb + sizeof(RTUTF16)) == 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcField = s_abFields[i].cb / sizeof(RTUTF16);
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t iPadding = 0; iPadding < 3; iPadding++, pwc++, cwcLeft--)
100b161379af7255c69e27587cc746e5f76ff050vboxsync s_abFields[i].pwsz, cwcField < 15 ? 15 - cwcField : 0, "", pwc));
100b161379af7255c69e27587cc746e5f76ff050vboxsync s_abFields[i].pwsz, cwcField < 15 ? 15 - cwcField : 0, "", rc));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" NtReadFile @%#llx -> %#x %#x\n", offRead.QuadPart, rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Nt Headers @%#x: Invalid signature\n", offNtHdrs));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Nt Headers @%#x: out side buffer\n", offNtHdrs));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" NtReadFile @0 -> %#x %#x\n", rcNt, Ios.Status));
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * Scans the Driver directory for drivers which may invade our processes.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * @returns Mask of SUPHARDNT_ADVERSARY_XXX flags.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @remarks The enumeration of \Driver normally requires administrator
100b161379af7255c69e27587cc746e5f76ff050vboxsync * privileges. So, the detection we're doing here isn't always gonna
100b161379af7255c69e27587cc746e5f76ff050vboxsync * work just based on that.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @todo Find drivers in \FileSystems as well, then we could detect VrNsdDrv
100b161379af7255c69e27587cc746e5f76ff050vboxsync * from ViRobot APT Shield 2.0.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsyncstatic uint32_t supR3HardenedWinFindAdversaries(void)
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmebc64" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmeevw" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmciesc" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "MBAMWebAccessControl" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync /*{ SUPHARDNT_ADVERSARY_COMODO, "cmdguard" }, file system */
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\SysPlant.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\sysfer.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\sysferThunk.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\ccsetx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\ironx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\srtsp64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\srtspx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symds64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symefa64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symelam.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symnets.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\symevent64x86.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswHwid.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswMonFlt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswRdr2.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswRvrt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswSnx.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswsp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswStm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswVmm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmcomm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmactmon.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmevtmgr.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmtdi.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmebc64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmeevw.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmciesc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\cfwids.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\McPvDrv.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfeapfk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfeavfk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfefirek.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfehidk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfencbdc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfewfpk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kl1.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klif.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klim6.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klkbdflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klmouflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kltdi.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kneps.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\klfphc.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\MBAMSwissArmy.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mwac.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mbamchameleon.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mbam.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgrkx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgmfx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsdrivera.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsha.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgtdia.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgloga.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgldx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgdiska.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINAflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINFile.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINKNC.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINProc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINProt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINReg.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSKMAD.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSAlpc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSHttp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNShttps.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSIds.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSNAHSL.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSpicc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPihsw.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPop3.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSProt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPrv.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSSmtp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSStrm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNStlsc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MSE, L"\\SystemRoot\\System32\\drivers\\MpFilter.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MSE, L"\\SystemRoot\\System32\\drivers\\NisDrvWFP.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdguard.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmderd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\inspect.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdhlp.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cfrmd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\hmd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\guard64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdvrt64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdkbd64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdcsr.dll" },
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync { SUPHARDNT_ADVERSARY_ZONE_ALARM, L"\\SystemRoot\\System32\\drivers\\vsdatant.sys" },
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync { SUPHARDNT_ADVERSARY_ZONE_ALARM, L"\\SystemRoot\\System32\\AntiTheftCredentialProvider.dll" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * Open the driver object directory.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Enumerate it, looking for the driver.
100b161379af7255c69e27587cc746e5f76ff050vboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
100b161379af7255c69e27587cc746e5f76ff050vboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
100b161379af7255c69e27587cc746e5f76ff050vboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
100b161379af7255c69e27587cc746e5f76ff050vboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = '\0';
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aDrivers); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (RTUtf16ICmpAscii(pObjDir->Name.Buffer, s_aDrivers[i].pszDriver) == 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("Found driver %s (%#x)\n", s_aDrivers[i].pszDriver, s_aDrivers[i].fAdversary));
100b161379af7255c69e27587cc746e5f76ff050vboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
100b161379af7255c69e27587cc746e5f76ff050vboxsync /* Next directory entry. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("NtOpenDirectoryObject failed on \\Driver: %#x\n", rcNt));
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Look for files.
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aFiles); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Length = (USHORT)(RTUtf16Len(s_aFiles[i].pwszFile) * sizeof(WCHAR));
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
100b161379af7255c69e27587cc746e5f76ff050vboxsync InitializeObjectAttributes(&ObjAttr, &UniStrName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtCreateFile(&hFile, GENERIC_READ, &ObjAttr, &Ios, NULL /* Allocation Size*/, FILE_ATTRIBUTE_NORMAL,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL /*EaBuffer*/, 0 /*EaLength*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Log details.
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("supR3HardenedWinFindAdversaries: %#x\n", fFound));
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aFiles); i++)
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(s_aFiles[i].pwszFile, true /* fAdversarial */);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncextern "C" int main(int argc, char **argv, char **envp);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The executable entry point.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This is normally taken care of by the C runtime library, but we don't want to
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * get involved with anything as complicated like the CRT in this setup. So, we
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * it everything ourselves, including parameter parsing.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncextern "C" void __stdcall suplibHardenedWindowsMain(void)
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Initialize the NTDLL API wrappers. This aims at bypassing patched NTDLL
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * in all the processes leading up the VM process.
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Notify the parent process that we're probably capable of reporting our
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * own errors.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (g_ProcParams.hEvtParent || g_ProcParams.hEvtChild)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_CloseEvents;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * After having resolved imports we patch the LdrInitializeThunk code so
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * that it's more difficult to invade our privacy by CreateRemoteThread.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * We'll re-enable this after opening the driver or temporarily while respawning.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Init g_uNtVerCombined. (The code is shared with SUPR3.lib and lives in
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_VERSION_INITIALIZED;
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * Convert the arguments to UTF-8 and open the log file if specified.
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * This must be done as early as possible since the code below may fail.
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync char **papszArgs = suplibCommandLineToArgvWStub(pCmdLineStr->Buffer, pCmdLineStr->Length / sizeof(WCHAR), &cArgs);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Log information about important system files.
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\ntdll.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\kernel32.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\KernelBase.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\apisetschema.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Scan the system for adversaries, logging information about them.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync g_fSupAdversaries = supR3HardenedWinFindAdversaries();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the executable name.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync DWORD cwcExecName = GetModuleFileNameW(GetModuleHandleW(NULL), g_wszSupLibHardenedExePath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwcExecName >= RT_ELEMENTS(g_wszSupLibHardenedExePath))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, VERR_BUFFER_OVERFLOW,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "The executable path is too long.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The NT version. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFile = CreateFileW(g_wszSupLibHardenedExePath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "Error opening the executable: %u (%ls).", RtlGetLastWin32Error());
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &g_SupLibHardenedExeNtPath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbIgn);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromNtStatus(rcNt),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtQueryObject -> %#x (on %ls)\n", rcNt, g_wszSupLibHardenedExePath);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The NT executable name offset / dir path length. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' )
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * If we've done early init already, register the DLL load notification
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * callback and reinstall the NtDll patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * Call the C/C++ main function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Exit the process (never return).
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("Terminating the normal way: rcExit=%d\n", rcExit));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Reports an error to the parent process via the process parameter structure.
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * @param pszWhere Where this error occured, if fatal message. NULL
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * if not message.
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * @param enmWhat Which init operation went wrong if fatal
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * message. kSupInitOp_Invalid if not message.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param rc The status code to report.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param pszFormat The format string.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param va The format arguments.
88d7b87c38cc3800f532139696785e8c96bfd531vboxsyncDECLHIDDEN(void) supR3HardenedWinReportErrorToParent(const char *pszWhere, SUPINITOP enmWhat, int rc,
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync RTStrCopy(g_ProcParams.szWhere, sizeof(g_ProcParams.szWhere), pszWhere);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync RTStrPrintfV(g_ProcParams.szErrorMsg, sizeof(g_ProcParams.szErrorMsg), pszFormat, va);
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync g_ProcParams.rc = RT_SUCCESS(rc) ? VERR_INTERNAL_ERROR_2 : rc;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NTSTATUS rcNt = NtSetEvent(g_ProcParams.hEvtParent, NULL);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NTSTATUS rcNt = NtWaitForSingleObject(g_ProcParams.hEvtChild, FALSE /*Alertable*/, &Timeout);
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Routine called by the supR3HardenedEarlyProcessInitThunk assembly routine
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * when LdrInitializeThunk is executed in during process initialization.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * This initializes the Stub and VM processes, hooking NTDLL APIs and opening
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * the device driver before any other DLLs gets loaded into the process. This
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * greately reduces and controls the trusted code base of the process compared
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * to opening the driver from SUPR3HardenedMain. It also avoids issues with so
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * call protection software that is in the habit of patching half of the ntdll
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * and kernel32 APIs in the process, making it almost indistinguishable from
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * software that is up to no good. Once we've opened vboxdrv, the process
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * should be locked down so thighly that only kernel software and csrss can mess
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * with the process.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncDECLASM(uintptr_t) supR3HardenedEarlyProcessInit(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * When the first thread gets here we wait for the parent to continue with
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the process purifications. The primary thread must execute for image
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * load notifications to trigger, at least in more recent windows versions.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The old trick of starting a different thread that terminates immediately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * thus doesn't work.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We are not allowed to modify any data at this point because it will be
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * reset by the child process purification the parent does when we stop. To
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * sabotage thread creation during purification, and to avoid unnecessary
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * work for the parent, we reset g_ProcParams before signalling the parent
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_enmSupR3HardenedMainState != SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Retrieve the data we need. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uNtDllAddr = ASMAtomicXchgPtrT(&g_ProcParams.uNtDllAddr, 0, uintptr_t);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Resolve the APIs we need. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinGetVeryEarlyImports(uNtDllAddr, &pfnNtWaitForSingleObject, &pfnNtSetEvent);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Signal the parent that we're ready for purification. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_PurifyChildAndCloseHandles;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Wait up to 2 mins for the parent to exorcise evil. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = pfnNtWaitForSingleObject(hEvtChild, FALSE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We're good to go, work global state and restore process parameters.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Note that we will not restore uNtDllAddr since that is our first defence
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * against unwanted threads (see above).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_INIT_CALLED;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Initialize the NTDLL imports that we consider usable before the
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * process has been initialized.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_IMPORTS_RESOLVED;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Init g_uNtVerCombined as well as we can at this point.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Convert the arguments to UTF-8 so we can open the log file if specified.
b106d14b607bb92c526257461d740a274dce64c9vboxsync * We may have to normalize the pointer on older windows version (not w7/64 +).
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Note! This leaks memory at present.
b106d14b607bb92c526257461d740a274dce64c9vboxsync PRTL_USER_PROCESS_PARAMETERS pUserProcParams = NtCurrentPeb()->ProcessParameters;
b106d14b607bb92c526257461d740a274dce64c9vboxsync UNICODE_STRING CmdLineStr = pUserProcParams->CommandLine;
b106d14b607bb92c526257461d740a274dce64c9vboxsync && !(pUserProcParams->Flags & RTL_USER_PROCESS_PARAMS_FLAG_NORMALIZED) )
b106d14b607bb92c526257461d740a274dce64c9vboxsync CmdLineStr.Buffer = (WCHAR *)((uintptr_t)CmdLineStr.Buffer + (uintptr_t)pUserProcParams);
b106d14b607bb92c526257461d740a274dce64c9vboxsync char **papszArgs = suplibCommandLineToArgvWStub(CmdLineStr.Buffer, CmdLineStr.Length / sizeof(WCHAR), &cArgs);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: uNtDllAddr=%p\n", uNtDllAddr));
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * Set up the direct system calls so we can more easily hook NtCreateSection.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync supR3HardenedWinInitSyscalls(true /*fReportErrors*/);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Determine the executable path and name. Will NOT determine the windows style
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * executable path here as we don't need it.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync rcNt = NtQueryVirtualMemory(NtCurrentProcess(), &g_ProcParams, MemorySectionName, &g_SupLibHardenedExeNtPath,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbActual);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("NtQueryVirtualMemory/MemorySectionName failed in supR3HardenedVmProcessInit: %#x\n", rcNt);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /* The NT executable name offset / dir path length. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' )
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Initialize the image verification stuff (hooks LdrLoadDll and NtCreateSection).
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Open the driver.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv stub...\n"));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync else if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n"));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync supR3HardenedFatal("Unexpected first argument '%s'!\n", papszArgs[0]);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Reinstall the NtDll patches since there is a slight possibility that
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * someone undid them while we where busy opening the device.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Restore the LdrInitializeThunk code so we can initialize the process
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * normally when we return.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Restoring LdrInitializeThunk...\n"));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, uNtDllAddr, UINT32_MAX, "LdrInitializeThunk", &uValue);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: Failed to find LdrInitializeThunk (%Rrc).\n", rc);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READWRITE));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(pvLdrInitThunk, pbBits + ((uintptr_t)uValue - uNtDllAddr), 16);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READ));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Returning to LdrInitializeThunk...\n"));