SUPR3HardenedMain-win.cpp revision a6c871653045073d6ef74d0589de345ae62b607d
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, GetLastError()); \
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. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/*******************************************************************************
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync* Global Variables *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync*******************************************************************************/
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** @name Global variables initialized by suplibHardenedWindowsMain.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Combined windows NT version number. See SUP_MAKE_NT_VER_COMBINED. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Count calls to the special main function for linking santity checks. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic uint32_t volatile g_cSuplibHardenedWindowsMainCalls;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** The UTF-16 windows path to the executable. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** The NT path of the executable. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** The offset into g_SupLibHardenedExeNtPath of the executable name (WCHAR,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * not byte). This also gives the length of the exectuable directory path,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * including a trailing slash. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** @name Hook related variables.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** The jump back address of the patched NtCreateSection. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsyncextern "C" PFNRT g_pfnNtCreateSectionJmpBack = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Pointer to the bit of assembly code that will perform the original
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * NtCreateSection operation. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic NTSTATUS (NTAPI * g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** The jump back address of the patched LdrLoadDll. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Pointer to the bit of assembly code that will perform the original
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * LdrLoadDll operation. */
88d7b87c38cc3800f532139696785e8c96bfd531vboxsyncstatic NTSTATUS (NTAPI * g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync/** The hash table of verifier cache . */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PVERIFIERCACHEENTRY volatile g_apVerifierCache[128];
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync/** Queue of cached images which needs WinVerifyTrust to check them. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PVERIFIERCACHEENTRY volatile g_pVerifierCacheTodoWvt = NULL;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Queue of cached images which needs their imports checked. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Static error info structure used during init. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** In the assembly file. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncextern "C" uint8_t g_abSupHardReadWriteExecPage[PAGE_SIZE];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Whether we've patched our own LdrInitializeThunk or not. We do this to
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * disable thread creation. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** The backup of our own LdrInitializeThunk code, for enabling and disabling
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * thread creation in this process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Mask of adversaries that we've detected (SUPHARDNT_ADVERSARY_XXX). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** @name SUPHARDNT_ADVERSARY_XXX - Adversaries
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Symantec endpoint protection or similar including SysPlant.sys. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT RT_BIT_32(0)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Symantec Norton 360. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_N360 RT_BIT_32(1)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Avast! */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** TrendMicro OfficeScan and probably others. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** McAfee. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Kaspersky. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Malwarebytes Anti-Malware (MBAM). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** AVG Internet Security. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Panda Security. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Microsoft Security Essentials. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Comodo. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Unknown adversary detected while waiting on child. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/*******************************************************************************
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync* Internal Functions *
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-amd64-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-x86-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple wide char search routine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the first location of @a wcNeedle in @a pwszHaystack.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * NULL if not found.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pwszHaystack Pointer to the string that should be searched.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param wcNeedle The character to search for.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic PRTUTF16 suplibHardenedWStrChr(PCRTUTF16 pwszHaystack, RTUTF16 wcNeedle)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Simple wide char string length routine.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * @returns The number of characters in the given string. (Excludes the
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * terminator.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Allocate zero filled memory on the heap.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @returns Pointer to the memory. Will never return NULL, triggers a fatal
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * error instead.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param cb The number of bytes to allocate.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync void *pv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync supR3HardenedFatal("HeapAlloc failed to allocate %zu bytes.\n", cb);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Reallocates memory on the heap.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @returns Pointer to the resized memory block. Will never return NULL,
100b161379af7255c69e27587cc746e5f76ff050vboxsync * triggers a fatal error instead.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @param pvOld The old memory block.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @param cbNew The new block size.
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsyncDECLHIDDEN(void *) suplibHardenedReAlloc(void *pvOld, size_t cbNew)
100b161379af7255c69e27587cc746e5f76ff050vboxsync void *pv = HeapReAlloc(GetProcessHeap(), 0 /*dwFlags*/, pvOld, cbNew);
100b161379af7255c69e27587cc746e5f76ff050vboxsync supR3HardenedFatal("HeapReAlloc failed to allocate %zu bytes.\n", cbNew);
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync * Frees memory allocated by suplibHardenedAlloc, suplibHardenedAllocZ or
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync * suplibHardenedReAlloc.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * @param pv Pointer to the memeory to be freed.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * Wrapper around LoadLibraryEx that deals with the UTF-8 to UTF-16 conversion
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * and supplies the right flags.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * @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. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvRet = (void *)LoadLibraryExW(wszPath, NULL /*hFile*/, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("RTStrToUtf16Ex failed on '%s': %Rrc", pszName, rc);
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Gets the internal index number of the file.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * @returns True if we got an index number, false if not.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * @param hFile The file in question.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * @param pIndexNumber where to return the index number.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncstatic bool supR3HardenedWinVerifyCacheGetIndexNumber(HANDLE hFile, PLARGE_INTEGER pIndexNumber)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync NTSTATUS rcNt = NtQueryInformationFile(hFile, &Ios, pIndexNumber, sizeof(*pIndexNumber), FileInternalInformation);
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync return NT_SUCCESS(rcNt) && pIndexNumber->QuadPart != 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * 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)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calculates the hash value for a directory + filename combo as if they were
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * one single string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Hash value.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pawcDir The directory name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cwcDir The length of the directory name. RTSTR_MAX if
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * not available.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszName The import name (UTF-8).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t supR3HardenedWinVerifyCacheHashDirAndFile(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcDir-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify string cache compare function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if the strings match, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pawcLeft The left hand string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pawcRight The right hand string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cwcToCompare The number of chars to compare.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedWinVerifyCacheIsMatch(PCRTUTF16 pawcLeft, PCRTUTF16 pawcRight, uint32_t cwcToCompare)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Try a quick memory compare first. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (memcmp(pawcLeft, pawcRight, cwcToCompare * sizeof(RTUTF16)) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Slow char by char compare. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcToCompare-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wcLeft = wcLeft != '/' ? RT_C_TO_LOWER(wcLeft) : '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wcLeft = wcRight != '/' ? RT_C_TO_LOWER(wcRight) : '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Inserts the given verifier result into the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pUniStr The full path of the image.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hFile The file handle - must either be entered into
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * the cache or closed.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param rc The verifier result.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param fWinVerifyTrust Whether verified by WinVerifyTrust or not.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param fFlags The image verification flags.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Allocate and initalize a new entry.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pEntry->wszPath, pUniStr->Buffer, pUniStr->Length);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pEntry->wszPath[pUniStr->Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pOther->wszPath, pEntry->wszPath, pEntry->cbPath / sizeof(RTUTF16)))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Duplicate entry (may happen due to races). */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pEntry);
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.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hFile The file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookup(PCUNICODE_STRING pUniStr, HANDLE hFile)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t iHashTab = uHash % RT_ELEMENTS(g_apVerifierCache);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PVERIFIERCACHEENTRY pCur = g_apVerifierCache[iHashTab];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pwszPath, cbPath / sizeof(RTUTF16)))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &IndexNumber);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && 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.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param cwcDir The length of the directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pszName The import name (UTF-8).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic 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))
30f07af559efcbd967e801903746fc21f81ee533vboxsync if (pCur->wszPath[cwcDir] == '\\' || pCur->wszPath[cwcDir] == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTUtf16ICmpAscii(&pCur->wszPath[cwcDir + 1], pszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Schedules the import DLLs for verification and entry into the cache.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hLdrMod The loader module which imports should be
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * scheduled for verification.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName The full NT path of the module.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyCacheScheduleImports(RTLDRMOD hLdrMod, PCRTUTF16 pwszName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Any imports?
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_COUNT, NULL /*pvBits*/, &cImports, sizeof(cImports), NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Figure out the DLL directory from pwszName.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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])
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEIMPORT pImport = (PVERIFIERCACHEIMPORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 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));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Check for DLL isolation / redirection / mapping.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UniStrName.Length = (USHORT)cwcName * sizeof(WCHAR);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UniStrStatic.MaximumLength = (USHORT)(sizeof(wszPath) - cwcName * sizeof(WCHAR) - sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNtRedir = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync InitializeObjectAttributes(&ObjAttr, pUniStrResult,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0 /*EaLength*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* For accurate logging. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync size_t cwcCopy = RT_MIN(pUniStrResult->Length / sizeof(RTUTF16), RT_ELEMENTS(wszPath) - 1);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(wszPath, pUniStrResult->Buffer, cwcCopy * sizeof(RTUTF16));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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 },
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /* Search System32 first, unless it's a 'V*' or 'm*' name, the latter for msvcrt. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (aDirs[i].pawcDir && aDirs[i].cwcDir && aDirs[i].cwcDir < RT_ELEMENTS(wszPath) / 3 * 2)
100b161379af7255c69e27587cc746e5f76ff050vboxsync 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*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
100b161379af7255c69e27587cc746e5f76ff050vboxsync 0 /*EaLength*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex #2 failed: %Rrc\n", rc));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * If we successfully opened it, verify it and cache the result.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' -> '%ls' [rcNtRedir=%#x]\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync bool fCallRealApi = false;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "Imports", false /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Failed to locate '%s'\n", pCur->szName));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' is in the cache.\n", pCur->szName));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Processes the list of WinVerifyTrust todos.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsyncstatic void supR3HardenedWinVerifyCacheProcessWvtTodos(void)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PVERIFIERCACHEENTRY volatile *ppReschedLastNext = NULL;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Work until we've got nothing more todo.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PVERIFIERCACHEENTRY pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoWvt, NULL, PVERIFIERCACHEENTRY);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync int rc = supHardenedWinVerifyImageTrust(pCur->hFile, pCur->wszPath, pCur->fFlags, pCur->rc,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Retry it at a later time. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls' [rescheduled]\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* else: already processed. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Anything to reschedule.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pReschedule, *ppReschedLastNext));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Checks whether the path could be containing alternative 8.3 names generated
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * by NTFS, FAT, or other similar file systems.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @returns Pointer to the first component that might be an 8.3 name, NULL if
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * not 8.3 path.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param pwszPath The path to check.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PRTUTF16 supR3HardenedWinIsPossible8dot3Path(PCRTUTF16 pwszPath)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Could check more here before jumping to conclusions... */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync else if (wc == 0)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Fixes up a path possibly containing one or more alternative 8-dot-3 style
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * components.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * The path is fixed up in place. Errors are ignored.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param hFile The handle to the file which path we're fixing up.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param pUniStr The path to fix up. MaximumLength is the max buffer
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic void supR3HardenedWinFix8dot3Path(HANDLE hFile, PUNICODE_STRING pUniStr)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * We could use FileNormalizedNameInformation here and slap the volume device
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * path in front of the result, but it's only supported since windows 8.0
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * according to some docs... So we expand all supicious names.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pwszFix = supR3HardenedWinIsPossible8dot3Path(pwszFix);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync 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));
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync 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 */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Query the name of the file, making sure to zero terminator the
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * string. (2nd half of buffer is used for error info, see below.)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint8_t abBuffer[sizeof(UNICODE_STRING) + 2048 * sizeof(WCHAR)];
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR) - 128, &cbNameBuf);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync "supR3HardenedScreenImage/%s: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n",
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer))
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Check the cache.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* If we haven't done the WinVerifyTrust thing, do it if we can. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [redoing WinVerifyTrust]\n",
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync int rc = supHardenedWinVerifyImageTrust(pCacheHit->hFile, pCacheHit->wszPath, pCacheHit->fFlags, pCacheHit->rc,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pszCaller, rc, pCacheHit->rc, fWinVerifyTrust, pCacheHit->wszPath));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: WinVerifyTrust not available, rescheduling %ls\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [avoiding WinVerifyTrust]\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls%s\n",
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync pszCaller, pCacheHit->rc, pCacheHit->wszPath, pCacheHit->fWinVerifyTrust ? "" : " [lacks WinVerifyTrust]"));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /* Return the cached value. */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync uint32_t cErrorHits = ASMAtomicIncU32(&pCacheHit->cErrorHits);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "supR3HardenedScreenImage/%s: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x cErrorHits=%u %ls\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 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(),
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync 0 /*EaLength*/);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync "supR3HardenedScreenImage/%s: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Check that we've got the same file. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync bool fMyValid = supR3HardenedWinVerifyCacheGetIndexNumber(hMyFile, &idMyFile);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync bool fInValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &idInFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "supR3HardenedScreenImage/%s: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync pszCaller, rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: NtDuplicateObject -> %#x\n", pszCaller, rcNt));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "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.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 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);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check the path. We don't allow DLLs to be loaded from just anywhere:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * 1. System32 - normal code or cat signing, owner TrustedInstaller.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * 2. WinSxS - normal code or cat signing, owner TrustedInstaller.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * 3. VirtualBox - kernel code signing and integrity checks.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * 4. AppPatchDir - normal code or cat signing, owner TrustedInstaller.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * 5. Program Files - normal code or cat signing, owner TrustedInstaller.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * 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*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesNtPath.UniStr, true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesX86NtPath.UniStr, true /*fCheckSlash*/))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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 )
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "supR3HardenedScreenImage/%s: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszCaller, uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync#else /* VBOX_PERMIT_EVEN_MORE */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Require trusted installer + some kind of signature on everything, except
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * for the VBox bits where we require kernel code signing and special
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * integrity checks.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync 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 fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync#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);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, fAvoidWinVerifyTrust, &fWinVerifyTrust, &ErrInfo);
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync "supR3HardenedScreenImage/%s: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync pszCaller, rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust, fFlags);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Insert into the cache.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 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.
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsyncDECLHIDDEN(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);
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync InitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync 0 /*EaLength*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: Error %#x opening '%ls'.\n", rcNt, pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: scanning %ls\n", pwszName));
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, "preload", false /*fAvoidWinVerifyTrust*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: done %ls\n", pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook that monitors NtCreateSection calls.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @returns NT status code.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param phSection Where to return the section handle.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param fAccess The desired access.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @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"));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "NtCreateSection", true /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 2 rcNt=%#x fCallRealApi=%#x\n", rcNt, fCallRealApi));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Call checked out OK, call the original.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Helper for supR3HardenedMonitor_LdrLoadDll.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @returns NT status code.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pwszPath The path destination buffer.
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync * @param cwcPath The size of the path buffer.
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync * @param pUniStrResult The result string.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pOrgName The orignal name (for errors).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pcwc Where to return the actual length.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncstatic NTSTATUS supR3HardenedCopyRedirectionResult(WCHAR *pwszPath, size_t cwcPath, PUNICODE_STRING pUniStrResult,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pcwc = cwc = pUniStrResult->Length / sizeof(WCHAR);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long: %.*ls -> %.*ls (RtlDosApplyFileIoslationRedirection_Ustr)\n",
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync pOrgName->Length / sizeof(WCHAR), pOrgName->Buffer,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync pUniStrResult->Length / sizeof(WCHAR), pUniStrResult->Buffer);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync memcpy(&pwszPath[0], pUniStrResult->Buffer, pUniStrResult->Length);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Hooks that intercepts LdrLoadDll calls.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Two purposes:
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * -# Enforce our own search path restrictions.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * -# Prevalidate DLLs about to be loaded so we don't upset the loader data
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * by doing it from within the NtCreateSection hook (WinVerifyTrust
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * seems to be doing harm there on W7/32).
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync * @param pwszSearchPath The search path to use.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pfFlags Flags on input. DLL characteristics or something
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * on return?
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param pName The name of the module.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param phMod Where the handle of the loaded DLL is to be
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * returned to the caller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncsupR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_STRING pName, PHANDLE phMod)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Process WinVerifyTrust todo before and after.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Reject things we don't want to deal with.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: name is NULL or have a zero length.\n");
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x (pName=%p)\n", STATUS_INVALID_PARAMETER, pName));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync /*SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));*/
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * Reject long paths that's close to the 260 limit without looking.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: too long name: %#x bytes\n", pName->Length);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * 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 };
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [redir]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer, rcNt));
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync * Not an absolute path. Check if it's one of those special API set DLLs
30f07af559efcbd967e801903746fc21f81ee533vboxsync * 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
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * if we can't.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool const fNeedDllSuffix = offLastDot == UINT32_MAX && offLastSlash == UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (offLastDot != UINT32_MAX && offLastDot == cwcName - 1)
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * Reject relative paths for now as they might be breakout attempts.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync "supR3HardenedMonitor_LdrLoadDll: relative name not permitted: %.*ls\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * Perform dll redirection to WinSxS such. We using an undocumented
30f07af559efcbd967e801903746fc21f81ee533vboxsync * API here, which as always is a bit risky... ASSUMES that the API
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * returns a full DOS path.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Search for the DLL. Only System32 is allowed as the target of
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * a search on the API level, all VBox calls will have full paths.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cwc = GetSystemDirectoryW(wszPath, RT_ELEMENTS(wszPath) - 32);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "supR3HardenedMonitor_LdrLoadDll: GetSystemDirectoryW failed: %u\n", GetLastError());
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_UNEXPECTED_IO_ERROR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcName, pawcName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [rcNt=%#x]\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * and the real API can come up with a fitting status code for it.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync HANDLE hFile = CreateFileW(wszPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync bool fCallRealApi = false;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "LdrLoadDll", false /*fAvoidWinVerifyTrust*/, &fQuietFailure);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: rejecting '%ls': rcNt=%#x\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u\n", wszPath, dwErr));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Screened successfully enough. Call the real thing.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls [calling]\n",
30f07af559efcbd967e801903746fc21f81ee533vboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = g_pfnLdrLoadDllReal(pwszSearchPath, pfFlags, pName, phMod);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Log the result and process pending WinVerifyTrust work if we can.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x hMod=%p '%ls'\n", rcNt, *phMod, wszPath));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Tries to allocate memory between @a uStart and @a uEnd.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns Pointer to the memory on success. NULL on failure.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param uStart The start address.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param uEnd The end address. This is lower than @a uStart
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * if @a iDirection is negative, and higher if
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * positive.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param iDirection The search direction.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cbAlloc The number of bytes to allocate.
9f997e760f610c92e3a365be21ead6972bc46130vboxsyncstatic void *supR3HardenedWinAllocHookMemory(uintptr_t uStart, uintptr_t uEnd, intptr_t iDirection, size_t cbAlloc)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync size_t const uAllocGranularityMask = ~(cbAllocGranularity - 1);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Make uEnd the last valid return address.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Search for free memory.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Examine the memory at this address, if it's free, try make the allocation here.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtQueryVirtualMemory(hProc,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync SUPR3HARDENED_ASSERT((uintptr_t)MemInfo.BaseAddress <= uCur);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync NTSTATUS rcNt = NtAllocateVirtualMemory(hProc, &pvMem, 0 /*ZeroBits*/, &cbAlloc,
30f07af559efcbd967e801903746fc21f81ee533vboxsync NtFreeVirtualMemory(hProc, &pvMem, &cbMem, MEM_RELEASE);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Advance within the free area and try again? */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uintptr_t uNext = iDirection > 0 ? uCur + cbAllocGranularity : uCur - cbAllocGranularity;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || uNext - (uintptr_t)MemInfo.BaseAddress > MemInfo.RegionSize
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync || MemInfo.RegionSize - (uNext - (uintptr_t)MemInfo.BaseAddress) < cbAlloc
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * Advance to the next memory region.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uCur = (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uCur = (uintptr_t)(MemInfo.AllocationBase ? MemInfo.AllocationBase : MemInfo.BaseAddress);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinHookFailed(const char *pszWhich, uint8_t const *pbPrologue)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "Failed to install %s monitor: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n "
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "(It is also possible you are running 32-bit VirtualBox under 64-bit windows.)\n"
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pbPrologue[0], pbPrologue[1], pbPrologue[2], pbPrologue[3],
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pbPrologue[4], pbPrologue[5], pbPrologue[6], pbPrologue[7],
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pbPrologue[8], pbPrologue[9], pbPrologue[10], pbPrologue[11],
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pbPrologue[12], pbPrologue[13], pbPrologue[14], pbPrologue[15]);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * IPRT thread that waits for the parent process to terminate and reacts by
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * exiting the current process.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @returns VINF_SUCCESS
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param hSelf The current thread. Ignored.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pvUser The handle of the parent process.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic DECLCALLBACK(int) supR3HardenedWinParentWatcherThread(RTTHREAD hSelf, void *pvUser)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Wait for the parent to terminate.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Proxy the termination code of the child, if it exited already.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedWinParentWatcherThread: Quitting: ExitCode=%#x rcNt=%#x\n", BasicInfo.ExitStatus, rcNt));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Creates the parent watcher thread that will make sure this process exits when
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * the parent does.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This is a necessary evil to make VBoxNetDhcp and VBoxNetNat termination from
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Main work without too much new magic. It also makes Ctrl-C or similar work
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * in on the hardened processes in the windows console.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param hVBoxRT The VBoxRT.dll handle. We use RTThreadCreate to
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * spawn the thread to avoid duplicating thread
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * creation and thread naming code from IPRT.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncDECLHIDDEN(void) supR3HardenedWinCreateParentWatcherThread(HMODULE hVBoxRT)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Resolve runtime methods that we need.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync PFNRTTHREADCREATE pfnRTThreadCreate = (PFNRTTHREADCREATE)GetProcAddress(hVBoxRT, "RTThreadCreate");
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Find the parent process ID.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NTSTATUS rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: NtQueryInformationProcess failed: %#x\n", rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Open the parent process for waiting and exitcode query.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ClientId.UniqueProcess = (HANDLE)BasicInfo.InheritedFromUniqueProcessId;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = NtOpenProcess(&hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatalMsg("supR3HardenedWinCreateParentWatcherThread", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "NtOpenProcess(%p.0) failed: %#x\n", ClientId.UniqueProcess, rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Create the thread that should do the waiting.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync int rc = pfnRTThreadCreate(NULL, supR3HardenedWinParentWatcherThread, hParent, _64K /* stack */,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ParentWatcher");
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: RTThreadCreate failed: %Rrc\n", rc);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install hooks for intercepting calls dealing with mapping shared libraries
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * into the process.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This allows us to prevent undesirable shared libraries from being loaded.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks We assume we're alone in this process, so no seralizing trickery is
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * necessary when installing the patch.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks We would normally just copy the prologue sequence somewhere and add
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * a jump back at the end of it. But because we wish to avoid
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * allocating executable memory, we need to have preprepared assembly
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * "copies". This makes the non-system call patching a little tedious
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * and inflexible.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install a anti debugging hack before we continue. This prevents most
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * notifications from ending up in the debugger. (Also applied to the
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * child process when respawning.)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Disable hard error popups so we can quietly refuse images to be loaded.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr), NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "NtQueryInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync rcNt = NtSetInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr));
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync "NtSetInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Locate the routines first so we can allocate memory that's near enough.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PFNRT pfnNtCreateSection = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "NtCreateSection");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync //SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PFNRT pfnLdrLoadDll = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "LdrLoadDll");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * For 64-bit hosts we need some memory within a +/-2GB range of the
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * actual function to be able to patch it.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync uintptr_t uStart = RT_MAX((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync void *pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart - _2G + PAGE_SIZE, -1, cbMem);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync uintptr_t uStart = RT_MIN((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart + _2G - PAGE_SIZE, 1, cbMem);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync "Failed to allocate memory within the +/-2GB range from NTDLL.\n");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Hook #1 - NtCreateSection.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Purpose: Validate everything that can be mapped into the process before
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * it's mapped and we still have a file handle to work with.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Patch 64-bit hosts.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /* Pattern #1: XP64/W2K3-64 thru Windows 8.1
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 0:000> u ntdll!NtCreateSection
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync ntdll!NtCreateSection:
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 00000000`779f1750 4c8bd1 mov r10,rcx
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 00000000`779f1753 b847000000 mov eax,47h
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 00000000`779f1758 0f05 syscall
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 00000000`779f175a c3 ret
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync 00000000`779f175b 0f1f440000 nop dword ptr [rax+rax]
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync The variant is the value loaded into eax: W2K3=??, Vista=47h?, W7=47h, W80=48h, W81=49h */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if ( pbNtCreateSection[ 0] == 0x4c /* mov r10, rcx */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync && pbNtCreateSection[ 3] == 0xb8 /* mov eax, 000000xxh */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync/* b8 22 35 ed 0 48 63 c0 ff e0 c3 f 1f 44 0 0 - necros2 - agnitum firewall? */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync offJmpBack = 8; /* the 3rd instruction (syscall). */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync# define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync# include "NtCreateSection-template-amd64-syscall-type-1.h"
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Patch 32-bit hosts.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync /* Pattern #1: XP thru Windows 7
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync kd> u ntdll!NtCreateSection
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync ntdll!NtCreateSection:
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync 7c90d160 b832000000 mov eax,32h
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync 7c90d165 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
30f07af559efcbd967e801903746fc21f81ee533vboxsync 7c90d16a ff12 call dword ptr [edx]
30f07af559efcbd967e801903746fc21f81ee533vboxsync 7c90d16c c21c00 ret 1Ch
30f07af559efcbd967e801903746fc21f81ee533vboxsync 7c90d16f 90 nop
30f07af559efcbd967e801903746fc21f81ee533vboxsync The variable bit is the value loaded into eax: XP=32h, W2K3=34h, Vista=4bh, W7=54h
30f07af559efcbd967e801903746fc21f81ee533vboxsync Pattern #2: Windows 8.1
30f07af559efcbd967e801903746fc21f81ee533vboxsync 0:000:x86> u ntdll_6a0f0000!NtCreateSection
30f07af559efcbd967e801903746fc21f81ee533vboxsync ntdll_6a0f0000!NtCreateSection:
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eabc b854010000 mov eax,154h
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eac1 e803000000 call ntdll_6a0f0000!NtCreateSection+0xd (6a15eac9)
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eac6 c21c00 ret 1Ch
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eac9 8bd4 mov edx,esp
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eacb 0f34 sysenter
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6a15eacd c3 ret
30f07af559efcbd967e801903746fc21f81ee533vboxsync The variable bit is the value loaded into eax: W81=154h
30f07af559efcbd967e801903746fc21f81ee533vboxsync Note! One nice thing here is that we can share code pattern #1. */
30f07af559efcbd967e801903746fc21f81ee533vboxsync if ( pbNtCreateSection[ 0] == 0xb8 /* mov eax, 000000xxh*/
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync && ( ( pbNtCreateSection[ 5] == 0xba /* mov edx, offset SharedUserData!SystemCallStub */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync || ( pbNtCreateSection[ 5] == 0xe8 /* call [$+3] */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync && RT_ABS(*(int32_t *)&pbNtCreateSection[6]) < 0x10
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync# define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync# include "NtCreateSection-template-x86-syscall-type-1.h"
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Hook #2 - LdrLoadDll
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Purpose: (a) Enforce LdrLoadDll search path constraints, and (b) pre-validate
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * DLLs so we can avoid calling WinVerifyTrust from the first hook,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * and thus avoiding messing up the loader data on some installations.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This differs from the above function in that is no a system call and
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * we're at the mercy of the compiler.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Patch 64-bit hosts.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Pattern #1:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Windows 8.1:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 0:000> u ntdll!LdrLoadDll
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ntdll!LdrLoadDll:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd44 488bc4 mov rax,rsp
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd47 48895808 mov qword ptr [rax+8],rbx
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd4b 48896810 mov qword ptr [rax+10h],rbp
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd4f 48897018 mov qword ptr [rax+18h],rsi
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd53 48897820 mov qword ptr [rax+20h],rdi
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd57 4156 push r14
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00007ffa`814ccd59 4883ec70 sub rsp,70h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00007ffa`814ccd5d f6059cd2100009 test byte ptr [ntdll!LdrpDebugFlags (00007ffa`815da000)],9
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbLdrLoadDll[3] == 0x48 /* mov qword ptr [rax+8],rbx */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Pattern #2:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Windows 8.0:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000> u ntdll_w8_64!LdrLoadDll
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync ntdll_w8_64!LdrLoadDll:
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7c0 48895c2408 mov qword ptr [rsp+8],rbx
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7c5 4889742410 mov qword ptr [rsp+10h],rsi
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7ca 48897c2418 mov qword ptr [rsp+18h],rdi
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7cf 55 push rbp
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7d0 4156 push r14
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7d2 4157 push r15
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7d4 488bec mov rbp,rsp
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7d7 4883ec60 sub rsp,60h
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7db 8b05df321000 mov eax,dword ptr [ntdll_w8_64!LdrpDebugFlags (00007ffa`530fdac0)]
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync 00007ffa`52ffa7e1 4d8bf1 mov r14,r9
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+8],rbx */
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync && pbLdrLoadDll[5] == 0x48 /* mov qword ptr [rsp+10h],rsi */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #3:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll_w7_64!LdrLoadDll:
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58be4a20 48895c2410 mov qword ptr [rsp+10h],rbx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58be4a25 48896c2418 mov qword ptr [rsp+18h],rbp
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58be4a2a 56 push rsi
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58be4a2b 57 push rdi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a2c 4154 push r12
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a2e 4883ec50 sub rsp,50h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a32 f605976e100009 test byte ptr [ntdll_w7_64!ShowSnaps (00000000`58ceb8d0)],9
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a39 498bf1 mov rsi,r9
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+10h],rbx */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type3;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Pattern #4:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Windows Vista:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000> u ntdll_vista_64!LdrLoadDll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll_vista_64!LdrLoadDll:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58c11f60 fff3 push rbx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58c11f62 56 push rsi
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58c11f63 57 push rdi
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58c11f64 4154 push r12
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`58c11f66 4155 push r13
30f07af559efcbd967e801903746fc21f81ee533vboxsync 00000000`58c11f68 4156 push r14
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00000000`58c11f6a 4157 push r15
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58c11f6c 4881ecb0020000 sub rsp,2B0h
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58c11f73 488b05367b0e00 mov rax,qword ptr [ntdll_vista_64!_security_cookie (00000000`58cf9ab0)]
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58c11f7a 4833c4 xor rax,rsp
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`58c11f7d 48898424a0020000 mov qword ptr [rsp+2A0h],rax
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Pattern #5:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Windows XP64:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000> u ntdll!LdrLoadDll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll!LdrLoadDll:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa580 4c8bdc mov r11,rsp
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa583 4881ece8020000 sub rsp,2E8h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa58a 49895bf8 mov qword ptr [r11-8],rbx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa58e 498973f0 mov qword ptr [r11-10h],rsi
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa592 49897be8 mov qword ptr [r11-18h],rdi
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa596 4d8963e0 mov qword ptr [r11-20h],r12
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa59a 4d896bd8 mov qword ptr [r11-28h],r13
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa59e 4d8973d0 mov qword ptr [r11-30h],r14
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`78efa5a2 4d897bc8 mov qword ptr [r11-38h],r15
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5a6 488b051bd10a00 mov rax,qword ptr [ntdll!_security_cookie (00000000`78fa76c8)]
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00000000`78efa5ad 48898424a0020000 mov qword ptr [rsp+2A0h],rax
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`78efa5b5 4d8bf9 mov r15,r9
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00000000`78efa5b8 4c8bf2 mov r14,rdx
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 00000000`78efa5bb 4c8be9 mov r13,rcx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`78efa5be 4c89442458 mov qword ptr [rsp+58h],r8
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync 00000000`78efa5c3 66c74424680000 mov word ptr [rsp+68h],0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0x4c /* mov r11,rsp */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type5;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Just use the disassembler to skip 6 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];
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /* Patch the function. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&pbLdrLoadDll[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 32-bit hosts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Pattern #1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000> u ntdll!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff585 8bff mov edi,edi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff587 55 push ebp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff588 8bec mov ebp,esp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff58a 51 push ecx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff58b 51 push ecx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77aff58c a1f8bdaf77 mov eax,dword ptr [ntdll!LdrpLogLevelStateTable+0x24 (77afbdf8)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 8 rtm:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000:x86> u ntdll_67150000!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_67150000!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f3f 8bff mov edi,edi
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 67189f41 55 push ebp
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 67189f42 8bec mov ebp,esp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f44 8b0d10eb2467 mov ecx,dword ptr [ntdll_67150000!LdrpDebugFlags (6724eb10)]
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Windows 8.1:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000:x86> u ntdll_w81_32!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_w81_32!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 6718aade 8bff mov edi,edi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 6718aae0 55 push ebp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 6718aae1 8bec mov ebp,esp
30f07af559efcbd967e801903746fc21f81ee533vboxsync 6718aae3 83ec14 sub esp,14h
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 6718aae6 f6050040246709 test byte ptr [ntdll_w81_32!LdrpDebugFlags (67244000)],9
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Pattern #2:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Windows XP:
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 0:000:x86> u ntdll_xp!LdrLoadDll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll_xp!LdrLoadDll:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 77f569d2 6858020000 push 258h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 77f569d7 68d866f777 push offset ntdll_xp!`string'+0x12c (77f766d8)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 77f569dc e83bb20200 call ntdll_xp!_SEH_prolog (77f81c1c)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 77f569e1 33db xor ebx,ebx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 77f569e3 66895de0 mov word ptr [ebp-20h],bx
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 77f569e7 33c0 xor eax,eax
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 77f569e9 8d7de2 lea edi,[ebp-1Eh]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 77f569ec ab stos dword ptr es:[edi]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Windows Server 2003:
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 0:000:x86> u ntdll_w2k3_32!LdrLoadDll
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ntdll_w2k3_32!LdrLoadDll:
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 7c833f63 6840020000 push 240h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c833f68 68b040837c push offset ntdll_w2k3_32!`string'+0x12c (7c8340b0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c833f6d e8a942ffff call ntdll_w2k3_32!_SEH_prolog (7c82821b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c833f72 a13077887c mov eax,dword ptr [ntdll_w2k3_32!__security_cookie (7c887730)]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 7c833f77 8945e4 mov dword ptr [ebp-1Ch],eax
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c833f7a 8b4508 mov eax,dword ptr [ebp+8]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 7c833f7d 8985b0fdffff mov dword ptr [ebp-250h],eax
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 7c833f83 8b450c mov eax,dword ptr [ebp+0Ch]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Windows Vista SP0 & SP1:
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 0:000:x86> u ntdll_vista_sp0_32!LdrLoadDll
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ntdll_vista_sp0_32!LdrLoadDll:
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb00 6844020000 push 244h
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb05 6838e9b269 push offset ntdll_vista_sp0_32! ?? ::FNODOBFM::`string'+0x39e (69b2e938)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb0a e835420300 call ntdll_vista_sp0_32!_SEH_prolog4_GS (69b42d44)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb0f 8b4508 mov eax,dword ptr [ebp+8]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb12 8985acfdffff mov dword ptr [ebp-254h],eax
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb18 8b450c mov eax,dword ptr [ebp+0Ch]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb1b 8985c0fdffff mov dword ptr [ebp-240h],eax
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 69b0eb21 8b4510 mov eax,dword ptr [ebp+10h]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( pbLdrLoadDll[0] == 0x8b /* mov edi, edi - for hot patching */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (pbLdrLoadDll[0] == 0x68 /* push dword XXXXXXXX */)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_supR3HardenedJmpBack_LdrLoadDll_Type2_PushDword = *(uint32_t const *)&pbLdrLoadDll[1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_pfnLdrLoadDllJmpBack = (PFNRT)(uintptr_t)(pbLdrLoadDll + offJmpBack);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Just use the disassembler to skip 6 bytes or more. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_32BIT, &Dis, &cbInstr);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) )
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Assemble the code for resuming the call.*/
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack]
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Patch LdrLoadDLl. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(uint32_t *)&pbLdrLoadDll[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Seal the rwx page.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), g_abSupHardReadWriteExecPage, PAGE_SIZE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the process integrity.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyProcess(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPHARDNTVPKIND_VERIFY_ONLY, NULL /*pcFixes*/, &g_ErrInfoStatic.Core);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardenedWinVerifyProcess", kSupInitOp_Integrity, rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Failed to verify process integrity: %s", g_ErrInfoStatic.szMsg);
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 supR3HardenedGetUserAndLogSids(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 supR3HardenedInitSecAttrs(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 = supR3HardenedGetUserAndLogSids(&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,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Grant very limited access to the login sid. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Create a security descriptor with the above ACL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PSECURITY_DESCRIPTOR pSecDesc = (PSECURITY_DESCRIPTOR)suplibHardenedAllocZ(SECURITY_DESCRIPTOR_MIN_LENGTH);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlSetDaclSecurityDescriptor(pSecDesc, TRUE /*fDaclPresent*/, &pCleanup->Acl.AclHdr,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Predicate function which tests whether @a ch is a argument separator
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * character.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param ch The character to examine.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncDECLINLINE(bool) suplibCommandLineIsArgSeparator(int ch)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Construct the new command line.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Since argc/argv are both derived from GetCommandLineW (see
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * suplibHardenedWindowsMain), we skip the argument by argument UTF-8 -> UTF-16
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * conversion and quoting by going to the original source.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The executable name, though, is replaced in case it's not a fullly
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * qualified path.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The re-spawn indicator is added immediately after the executable name
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * so that we don't get tripped up missing close quote chars in the last
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * argument.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns Pointer to a command line string (heap).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pUniStr Unicode string structure to initialize to the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * command line. Optional.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param iWhich Which respawn we're to check for, 1 being the first
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * one, and 2 the second and final.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PRTUTF16 supR3HardenedWinConstructCmdLine(PUNICODE_STRING pString, int iWhich)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Get the command line and skip the executable name.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint32_t cwcArgs = pCmdLineStr->Length / sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Skip leading space (shouldn't be any, but whatever). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs) )
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(cwcArgs > 0 && *pawcArgs != '\0');
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Walk to the end of it. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int fQuoted = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (*pawcArgs != '\\' || (pawcArgs[1] != '\\' && pawcArgs[1] != '"'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cSlashes = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwcArgs > 0 && *pawcArgs == '"' && (cSlashes & 1))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcArgs--, pawcArgs++; /* odd number of slashes == escaped quote */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (cwcArgs > 0 && (fQuoted || !suplibCommandLineIsArgSeparator(*pawcArgs)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Skip trailing spaces. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Allocate a new buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertCompile(sizeof(SUPR3_RESPAWN_1_ARG0) == sizeof(SUPR3_RESPAWN_2_ARG0));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinConstructCmdLine", kSupInitOp_Misc, VERR_OUT_OF_RANGE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Command line is too long (%u chars)!", cwcCmdLine);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwszCmdLine = (PRTUTF16)HeapAlloc(GetProcessHeap(), 0 /* dwFlags*/, (cwcCmdLine + 1) * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct the new command line.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pString->Length = (USHORT)(cwcCmdLine * sizeof(WCHAR));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pString->MaximumLength = pString->Length + sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Check if the zero terminated NT unicode string is the path to the given
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * system32 DLL.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns true if it is, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr The zero terminated NT unicode string path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszName The name of the system32 DLL.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsyncstatic bool supR3HardNtIsNamedSystem32Dll(PUNICODE_STRING pUniStr, const char *pszName)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (pUniStr->Length > g_System32NtPath.UniStr.Length)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (memcmp(pUniStr->Buffer, g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length) == 0)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR)] == '\\')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTUtf16ICmpAscii(&pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR) + 1], pszName) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Common code used for child and parent to make new threads exit immediately.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This patches the LdrInitializeThunk code to call NtTerminateThread with
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * STATUS_SUCCESS instead of doing the NTDLL initialization.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @returns VBox status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hProcess The process to do this to.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * override.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param pvNtTerminateThread The address of the NtTerminateThread function in
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * the NTDLL instance we're patching. (Must be +/-
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * 2GB from the thunk code.)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param pabBackup Where to back up the original instruction bytes
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * at pvLdrInitThunk.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Where to return extended error information.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Optional.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsyncstatic int supR3HardNtDisableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, void *pvNtTerminateThread,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t *pabBackup, size_t cbBackup, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtDisableThreadCreation: pvLdrInitThunk=%p pvNtTerminateThread=%p\n", pvLdrInitThunk, pvNtTerminateThread));
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT(RT_ABS((intptr_t)pvLdrInitThunk - (intptr_t)pvNtTerminateThread) < 16*_1M);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Back up the thunk code.
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtReadVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supR3HardNtDisableThreadCreation: NtReadVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Cook up replacement code that calls NtTerminateThread.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(abReplacement, pabBackup, sizeof(abReplacement));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
edde275acba04aca58db4172a163741e3abadfbcvboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
edde275acba04aca58db4172a163741e3abadfbcvboxsync *(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);
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync 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);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "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.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @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.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * 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);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtEnableThreadCreation: NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtEnableThreadCreation: NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Disable thread creation for the current process.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @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);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync * Child-Process Purification - release it from dubious influences.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * AV software and other things injecting themselves into the embryonic
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync * 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 * matching half of NTDLL or messing with the import table of the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * process executable.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Process handle. */
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync /** Primary thread handle. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** Error buffer. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** The address of NTDLL in the child. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of NTDLL in this process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The basic process info. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The probable size of the PEB. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** The pristine process environment block. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtPuChScrewUpPebForInitialImageEvents(PSUPR3HARDNTPUCH 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 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Unmaps a DLL from the child process that was previously mapped by
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * supR3HardNtPuChMapDllIntoChild.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns Pointer to the DLL mapping on success, NULL on failure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child purification instance data.
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync * @param pvBase The base address of the mapping. Nothing done
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszShort The short name (for logging).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtPuChUnmapDllFromChild(PSUPR3HARDNTPUCH pThis, PVOID pvBase, const char *pszShort)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*SUP_DPRINTF(("supR3HardNtPuChUnmapDllFromChild: Calling NtUnmapViewOfSection on %p / %s\n", pvBase, pszShort));*/
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtUnmapViewOfSection(pThis->hProcess, pvBase);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtUnmapViewOfSection failed on %s: %#x (%p)\n",
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Maps a DLL into the child process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns Pointer to the DLL mapping on success, NULL on failure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child purification instance data.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pNtName The path to the DLL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszShort The short name (for logging).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PVOID supR3HardNtPuChMapDllIntoChild(PSUPR3HARDNTPUCH pThis, PUNICODE_STRING pNtName, const char *pszShort)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync InitializeObjectAttributes(&ObjAttr, pNtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 0 /*EaLength*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync SECTION_MAP_EXECUTE | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: mapping view of %s\n", pszShort)); /* For SEP. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtMapViewOfSection(hSection, pThis->hProcess, &pvRet, 0 /*ZeroBits*/, 0 /*CommitSize*/,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NULL /*pOffSect*/, &cbView, ViewShare, 0 /*AllocationType*/, PAGE_READWRITE);
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: %s mapped at %p LB %#x\n", pszShort, pvRet, cbView));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtMapViewOfSection failed on %s: %#x\n", pszShort, rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtCreateSection failed on %s: %#x\n", pszShort, rcNt));
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Error opening %s: %#x\n", pszShort, rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Trigger the initial image events without actually initializing the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This is a trick to force sysplant.sys to call its hand by tripping the image
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * loaded event for the main executable and ntdll images. This will happen when
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the first thread in a process starts executing in PspUserThreadStartup. We
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * create a second thread that quits immediately by means of temporarily
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * replacing ntdll!LdrInitializeThunk by a NtTerminateThread call.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * (LdrInitializeThunk is called by way of an APC queued the thread is created,
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * thus NtSetContextThread is of no use.)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns VBox status code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child cleanup
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pErrInfo For extended error information.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsyncstatic int supR3HardNtPuChTriggerInitialImageEvents(PSUPR3HARDNTPUCH pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Use the on-disk image for the ntdll entrypoints here.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "supHardNtLdrCacheOpen failed on NTDLL: %Rrc", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, pThis->uNtDllAddr, UINT32_MAX,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, pThis->uNtDllAddr, UINT32_MAX,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "Error locating NtTerminateThread in NTDLL: %Rrc", rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: uLdrInitThunk=%p uNtTerminateThread=%p\n",
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync (uintptr_t)uLdrInitThunk, (uintptr_t)uNtTerminateThread));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Patch the child's LdrInitializeThunk to exit the thread immediately.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supR3HardNtDisableThreadCreationEx(pThis->hProcess, pvLdrInitThunk, (void *)(uintptr_t)uNtTerminateThread,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * To further muddle the waters, we map the executable image and ntdll.dll
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * a 2nd time into the process before we actually start executing the thread
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * and trigger the genuine image load events.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Update #1 (after 4.3.15 build 7):
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Turns out Symantec Endpoint Protection deadlocks when we map the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * executable into the process like this. The system only works
edde275acba04aca58db4172a163741e3abadfbcvboxsync * halfways after that Powerbutton, impossible to shutdown without
edde275acba04aca58db4172a163741e3abadfbcvboxsync * using the power or reset button. The order of the two mappings
edde275acba04aca58db4172a163741e3abadfbcvboxsync * below doesn't matter. Haven't had time to look at stack yet.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Observed on W7/64, SEP v12.1.4112.4156.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Update #2 (after 4.3.16):
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Some avast! users complain about a deadlock mapping ntdll.dll
edde275acba04aca58db4172a163741e3abadfbcvboxsync * as well. Unfortunately not reproducible, so there may possibly be
edde275acba04aca58db4172a163741e3abadfbcvboxsync * some other cause. Sad as it's really a serious bug in whichever
edde275acba04aca58db4172a163741e3abadfbcvboxsync * software it is that is causing it, and we'd like to report it to
edde275acba04aca58db4172a163741e3abadfbcvboxsync * the responsible party.
edde275acba04aca58db4172a163741e3abadfbcvboxsync PVOID pvExe2 = supR3HardNtPuChMapDllIntoChild(pThis, &g_SupLibHardenedExeNtPath.UniStr, "executable[2nd]");
edde275acba04aca58db4172a163741e3abadfbcvboxsync UNICODE_STRING NtName1 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\ntdll.dll");
edde275acba04aca58db4172a163741e3abadfbcvboxsync PVOID pvNtDll2 = supR3HardNtPuChMapDllIntoChild(pThis, &NtName1, "ntdll.dll[2nd]");
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Create the thread, waiting 10 seconds for it to complete.
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = RtlCreateUserThread(pThis->hProcess,
edde275acba04aca58db4172a163741e3abadfbcvboxsync 0 /* ZeroBits */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync 0 /* MaximumStackSize */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync 0 /* CommittedStackSize */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync Timeout.QuadPart = -10 * 10000000; /* 10 seconds */
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtWaitForSingleObject(hThread2, FALSE /* Alertable */, &Timeout);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Map kernel32.dll and kernelbase.dll (if applicable) into the process.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * This triggers should image load events that may set of AV activities
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * that we'd rather see early than later.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync UNICODE_STRING NtName2 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\kernel32.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PVOID pvKernel32 = supR3HardNtPuChMapDllIntoChild(pThis, &NtName2, "kernel32.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync UNICODE_STRING NtName3 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\KernelBase.dll");
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PVOID pvKernelBase = g_uNtVerCombined >= SUP_NT_VER_VISTA
9f997e760f610c92e3a365be21ead6972bc46130vboxsync ? supR3HardNtPuChMapDllIntoChild(pThis, &NtName3, "KernelBase.dll")
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Fudge factor for letting kernel threads get a chance to mess up our
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * process asynchronously.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint32_t cMsKludge = (g_fSupAdversaries & SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT) ? 256 : g_fSupAdversaries ? 64 : 16;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Startup delay kludge #1: %u ms\n", GetTickCount() - dwStart));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Unmap the image we mapped into the guest above.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvKernel32, "kernel32.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvKernelBase, "KernelBase.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvNtDll2, "ntdll.dll[2nd]");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvExe2, "executable[2nd]");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Restore the original thunk code and protection.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We do this after waiting as anyone trying to kick of threads in the
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync * process will get nothing done as long as our patch is in place.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rc = supR3HardNtEnableThreadCreationEx(pThis->hProcess, pvLdrInitThunk, abBackup, sizeof(abBackup), pThis->pErrInfo);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardenedWinScratchChildMemory(HANDLE hProcess, void *pv, size_t cb, const char *pszWhat, PRTERRINFO pErrInfo)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinScratchChildMemory: %p %#x\n", pv, cb));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtProtectVirtualMemory/%s (%p LB %#zx) failed: %#x",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtPuChSanitizePeb(PSUPR3HARDNTPUCH pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Make a copy of the pre-execution PEB.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * There should not be any activation context, so if there is, we scratch the memory associated with it.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_SUCCESS(rc) && Peb.pShimData && !((uintptr_t)Peb.pShimData & PAGE_OFFSET_MASK))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.pShimData, PAGE_SIZE, "pShimData", pErrInfo);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (RT_SUCCESS(rc) && Peb.ActivationContextData && !((uintptr_t)Peb.ActivationContextData & PAGE_OFFSET_MASK))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ActivationContextData, PAGE_SIZE, "ActivationContextData", pErrInfo);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_SUCCESS(rc) && Peb.ProcessAssemblyStorageMap && !((uintptr_t)Peb.ProcessAssemblyStorageMap & PAGE_OFFSET_MASK))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "ProcessAssemblyStorageMap", pErrInfo);
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync if (RT_SUCCESS(rc) && Peb.SystemDefaultActivationContextData && !((uintptr_t)Peb.SystemDefaultActivationContextData & PAGE_OFFSET_MASK))
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "SystemDefaultActivationContextData", pErrInfo);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_SUCCESS(rc) && Peb.SystemAssemblyStorageMap && !((uintptr_t)Peb.SystemAssemblyStorageMap & PAGE_OFFSET_MASK))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.SystemAssemblyStorageMap, PAGE_SIZE, "SystemAssemblyStorageMap", pErrInfo);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Clear compatibility and activation related fields.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*Peb.Diff0.W6.IsProtectedProcess = 1;*/
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Write back the PEB.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsyncstatic void supR3HardNtPuChFindNtdll(PSUPR3HARDNTPUCH pThis)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Find NTDLL in this process first and take that as a starting point.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync 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. */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync (void const *)uPtrWhere,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /* Get the image name. */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (supR3HardNtIsNamedSystem32Dll(&uBuf.UniStr, "ntdll.dll"))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync pThis->uNtDllAddr = (uintptr_t)MemInfo.AllocationBase;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("supR3HardNtPuChFindNtdll: uNtDllParentAddr=%p uNtDllChildAddr=%p\n",
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatal("%s: ntdll.dll not found in child.", __FUNCTION__);
9f997e760f610c92e3a365be21ead6972bc46130vboxsyncstatic int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Initialize the purifier instance data.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &This.BasicInfo, sizeof(This.BasicInfo), &cbActual);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtQueryInformationProcess/ProcessBasicInformation failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinPurifyChild: PebBaseAddress=%p cbPeb=%#x\n", This.BasicInfo.PebBaseAddress, This.cbPeb));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtReadVirtualMemory(hProcess, This.BasicInfo.PebBaseAddress, &This.Peb, sizeof(This.Peb), &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtReadVirtualMemory/Peb failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Do the work, the last bit we tag along with the process verfication code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardNtPuChScrewUpPebForInitialImageEvents(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supR3HardNtPuChTriggerInitialImageEvents(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supHardenedWinVerifyProcess(hProcess, hThread, SUPHARDNTVPKIND_CHILD_PURIFICATION, NULL /*pcFixes*/, pErrInfo);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Does the actually respawning.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns Never, will call exit or raise fatal error.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param iWhich Which respawn we're to check for, 1 being the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * first one, and 2 the second and final.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @todo Split up this function.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PRTL_USER_PROCESS_PARAMETERS pParentProcParams = pPeb->ProcessParameters;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Set up security descriptors.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedInitSecAttrs(&ThreadSecAttrs, &ThreadSecAttrsCleanup, false /*fProcess*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Configure the startup info and creation flags.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** @todo experiment with protected process stuff later on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SiEx.StartupInfo.dwFlags |= pParentProcParams->WindowFlags & STARTF_USESHOWWINDOW;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SiEx.StartupInfo.wShowWindow = (WORD)pParentProcParams->ShowWindowFlags;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SiEx.StartupInfo.hStdInput = pParentProcParams->StandardInput;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SiEx.StartupInfo.hStdOutput = pParentProcParams->StandardOutput;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SiEx.StartupInfo.hStdError = pParentProcParams->StandardError;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Construct the command line and launch the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine(NULL, iWhich);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Error relaunching VirtualBox VM process: %u\n"
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Command line: '%ls'",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [kernel32].\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync iWhich, ProcessInfoW32.dwProcessId, ProcessInfoW32.dwThreadId));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Construct the process parameters.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync W32ImageName.Buffer = g_wszSupLibHardenedExePath; /* Yes the windows name for the process parameters. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync W32ImageName.Length = (USHORT)RTUtf16Len(g_wszSupLibHardenedExePath) * sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync W32ImageName.MaximumLength = W32ImageName.Length + sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinConstructCmdLine(&CmdLine, iWhich);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateProcessParameters(&pProcParams,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NULL /* CurrentDirectory - inherit from this process */,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NULL /* Environment - inherit from this process */,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NULL /* RuntimeInfo - none (byte array for MSVCRT file info) */)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** @todo this doesn't work. :-( */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pProcParams->ConsoleHandle = pParentProcParams->ConsoleHandle;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pProcParams->ConsoleFlags = pParentProcParams->ConsoleFlags;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pProcParams->StandardInput = pParentProcParams->StandardInput;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pProcParams->StandardOutput = pParentProcParams->StandardOutput;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pProcParams->StandardError = pParentProcParams->StandardError;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RTL_USER_PROCESS_INFORMATION ProcessInfoNt = { sizeof(ProcessInfoNt) };
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = RtlCreateUserProcess(&g_SupLibHardenedExeNtPath.UniStr,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Error relaunching VirtualBox VM process: %#x\n"
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Command line: '%ls'",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [ntdll].\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync iWhich, ProcessInfo.ClientId.UniqueProcess, ProcessInfo.ClientId.UniqueThread));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Apply anti debugger notification trick to the thread. (Also done in
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * supR3HardenedWinInstallHooks.)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rcNt, true /*fFatal*/, "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Clean up the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardenedWinPurifyChild(hProcess, hThread, RTErrInfoInitStatic(&g_ErrInfoStatic));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Start the process execution.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtResumeThread(hThread, &cSuspendCount));
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
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * away with the process handle returned by CreateProcess.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
edde275acba04aca58db4172a163741e3abadfbcvboxsync /* Failure is unacceptable, kill the process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rcNt, false /*fFatal*/, "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
edde275acba04aca58db4172a163741e3abadfbcvboxsync bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
0aab9cd857ec35928a0e61c68d3f27a5b4d88a95vboxsync "NtDuplicateObject failed and we failed to kill child: rcNt=%u rcNtWait=%u hProcess=%p\n",
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Ditch the loader cache so we don't sit on too much memory while waiting.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Enable thread creation at this point so Ctrl-C and Ctrl-Break can be processed.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * If this is the middle process, wait for both parent and child to quit.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync ClientId.UniqueProcess = (HANDLE)BasicInfo.InheritedFromUniqueProcessId;
edde275acba04aca58db4172a163741e3abadfbcvboxsync rcNt = NtOpenProcess(&hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
edde275acba04aca58db4172a163741e3abadfbcvboxsync rcNt = NtWaitForMultipleObjects(2, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*pTimeout*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedFatal("NtWaitForMultipleObjects returned %#x\n", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Wait for the process to terminate.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Proxy the termination code of the child, if it exited already.
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): Quitting: ExitCode=%#x rcNt=%#x\n", iWhich, BasicInfo.ExitStatus, rcNt));
edde275acba04aca58db4172a163741e3abadfbcvboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync * Logs the content of the given object directory.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * @returns true if it exists, false if not.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszDir The path of the directory to log (ASCII).
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsyncstatic void supR3HardenedWinLogObjDir(const char *pszDir)
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Open the driver object directory.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = RTUtf16CopyAscii(wszDir, RT_ELEMENTS(wszDir), pszDir);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: RTUtf16CopyAscii -> %Rrc on '%s'\n", rc, pszDir));
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtDirName.Length = (USHORT)(RTUtf16Len(wszDir) * sizeof(WCHAR));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtDirName.MaximumLength = NtDirName.Length + sizeof(WCHAR);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: %ls => %#x\n", wszDir, rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Enumerate it, looking for the driver.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: NtQueryDirectoryObject => rcNt=%#x cbActual=%#x\n", rcNt, cbActual));
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
71e448b6623e801f76cb68355a28500169de5695vboxsync pObjDir->TypeName.Length / sizeof(WCHAR), pObjDir->TypeName.Buffer,
71e448b6623e801f76cb68355a28500169de5695vboxsync pObjDir->Name.Length / sizeof(WCHAR), pObjDir->Name.Buffer));
71e448b6623e801f76cb68355a28500169de5695vboxsync /* Next directory entry. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Clean up and return.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Checks if the driver exists.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This checks whether the driver is present in the /Driver object directory.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Drivers being initialized or terminated will have an object there
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * before/after their devices nodes are created/deleted.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @returns true if it exists, false if not.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param pszDriver The driver name.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsyncstatic bool supR3HardenedWinDriverExists(const char *pszDriver)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Open the driver object directory.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync return true;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Enumerate it, looking for the driver.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync bool fFound = true;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = '\0';
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync && RTUtf16ICmpAscii(pObjDir->Name.Buffer, pszDriver) == 0)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Next directory entry. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Clean up and return.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Open the stub device before the 2nd respawn.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
edde275acba04aca58db4172a163741e3abadfbcvboxsync static const WCHAR s_wszName[] = L"\\Device\\VBoxDrvStub";
edde275acba04aca58db4172a163741e3abadfbcvboxsync 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. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (iTry > 0 && GetTickCount() - uStartTick > 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. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Report trouble (fatal). For some errors codes we try gather some
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * extra information that goes into VBoxStartup.log so that we stand a
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * better chance resolving the issue.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * \Windows\ApiPort open trouble. So far only
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * STATUS_OBJECT_TYPE_MISMATCH has been observed.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"));
edde275acba04aca58db4172a163741e3abadfbcvboxsync RTStrPrintf(szDir, sizeof(szDir), "\\Sessions\\%u\\Windows", uSessionId);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, rc,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "Error getting %s\\ApiPort in the driver from vboxdrv.\n"
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "Could be due to security software is redirecting access to it, so please include full "
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "details of such software in a bug report. VBoxStartup.log may contain details important "
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "to resolving the issue."
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Generic VBox failure message.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, rc,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync case STATUS_NO_SUCH_DEVICE: pszDefine = " STATUS_NO_SUCH_DEVICE"; break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync case STATUS_OBJECT_NAME_NOT_FOUND: pszDefine = " STATUS_OBJECT_NAME_NOT_FOUND"; break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync case STATUS_ACCESS_DENIED: pszDefine = " STATUS_ACCESS_DENIED"; break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync case STATUS_TRUST_FAILURE: pszDefine = " STATUS_TRUST_FAILURE"; break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Problems opening the device is generally due to driver load/
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * unload issues. Check whether the driver is loaded and make
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * suggestions accordingly.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: %s\n", pszDefine));
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "Driver is probably stuck stopping/starting. Try 'sc.exe query vboxdrv' to get more "
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "information about its state. Rebooting may actually help.\n"
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "Driver is does not appear to be loaded. Try 'sc.exe start vboxdrv', reinstall "
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "VirtualBox or reboot.\n"
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync /* Generic NT failure message. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n", s_wszName, rcNt, pszDefine, iTry);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @returns Program exit code.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Before the 2nd respawn we set up a child protection deal with the
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * support driver via /Devices/VBoxDrvStub.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Respawn the process with kernel protection for the new process.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Checks if re-spawning is required, replacing the respawn argument if not.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @returns true if required, false if not. In the latter case, the first
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * argument in the vector is replaced.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param iWhich Which respawn we're to check for, 1 being the
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * first one, and 2 the second and final.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param cArgs The number of arguments.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param papszArgs Pointer to the argument vector.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsyncDECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync return true;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync return true;
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync else if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync return false;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync return true;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Replace the argument. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync return false;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Initializes the windows verficiation bits.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param fFlags The main flags.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsyncDECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync int rc = supHardenedWinInitImageVerifier(&g_ErrInfoStatic.Core);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rc,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "supHardenedWinInitImageVerifier failed: %s", g_ErrInfoStatic.szMsg);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Do a self purification to cure avast's weird NtOpenFile write-thru
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * change in GetBinaryTypeW change in kernel32. Unfortunately, avast
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * uses a system thread to perform the process modifications, which
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * means it's hard to make sure it had the chance to make them...
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * We have to resort to kludge doing yield and sleep fudging for a
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * number of milliseconds and schedulings before we can hope that avast
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and similar products have done what they need to do. If we do any
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * fixes, we wait for a while again and redo it until we're clean.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This is unfortunately kind of fragile.
edde275acba04aca58db4172a163741e3abadfbcvboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n",
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION,
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Install the hooks.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * 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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pawcCmdLine The UTF-16 windows command line to parse.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param cwcCmdLine The length of the command line.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcArgs Where to return the number of arguments.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic char **suplibCommandLineToArgvWStub(PCRTUTF16 pawcCmdLine, size_t cwcCmdLine, int *pcArgs)
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Convert the command line string to UTF-8.
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT(RT_SUCCESS(RTUtf16ToUtf8Ex(pawcCmdLine, cwcCmdLine, &pszCmdLine, 0, NULL)));
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Parse the command line, carving argument strings out of it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char **papszArgs = (char **)suplibHardenedAllocZ(sizeof(char *) * cArgsAllocated);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* skip leading blanks. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Add argument to the vector. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync papszArgs = (char **)suplibHardenedReAlloc(papszArgs, sizeof(char *) * cArgsAllocated);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Unquote and unescape the string. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync bool fQuoted = false;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else if (ch != '\\' || (*pszSrc != '\\' && *pszSrc != '"'))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync unsigned cSlashes = 0;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync while (cSlashes-- > 0)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync } while (ch != '\0' && (fQuoted || !suplibCommandLineIsArgSeparator(ch)));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /* Terminate the argument. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Logs information about a file from a protection product.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * The purpose here is to better see which version of the product is installed
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * and not needing to depend on the user supplying the correct information.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param pwszFile The NT path to the file.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsyncstatic void supR3HardenedLogAdversarialFile(PCRTUTF16 pwszFile)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Open the file.
e352c25b01398e5503235fed02436cb2992f1021vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync UniStrName.Length = (USHORT)(RTUtf16Len(pwszFile) * sizeof(WCHAR));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync InitializeObjectAttributes(&ObjAttr, &UniStrName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync 0 /*EaLength*/);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Print basic file information available via NtQueryInformationFile.
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.BasicInfo, sizeof(u.BasicInfo), FileBasicInformation);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" CreationTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.CreationTime.QuadPart), szTmp, sizeof(szTmp))));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*SUP_DPRINTF((" LastAccessTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastAccessTime.QuadPart), szTmp, sizeof(szTmp))));*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" LastWriteTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastWriteTime.QuadPart), szTmp, sizeof(szTmp))));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" ChangeTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.ChangeTime.QuadPart), szTmp, sizeof(szTmp))));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" FileAttributes: %#x\n", u.BasicInfo.FileAttributes));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" FileBasicInformation -> %#x %#x\n", rcNt, Ios.Status));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.StdInfo, sizeof(u.StdInfo), FileStandardInformation);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" Size: %#llx\n", u.StdInfo.EndOfFile.QuadPart));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" FileStandardInformation -> %#x %#x\n", rcNt, Ios.Status));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Read the image header and extract the timestamp and other useful info.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (offNtHdrs < sizeof(u) - sizeof(IMAGE_NT_HEADERS))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PIMAGE_NT_HEADERS64 pNtHdrs64 = (PIMAGE_NT_HEADERS64)&u.abBuf[offNtHdrs];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PIMAGE_NT_HEADERS32 pNtHdrs32 = (PIMAGE_NT_HEADERS32)&u.abBuf[offNtHdrs];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
30f07af559efcbd967e801903746fc21f81ee533vboxsync SUP_DPRINTF((" Machine: %#x%s\n", pNtHdrs64->FileHeader.Machine,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ? " - i386"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync : pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ? " - amd64" : ""));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtHdrs64->OptionalHeader.MajorImageVersion, pNtHdrs64->OptionalHeader.MinorImageVersion));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" SizeOfImage: %#x (%u)\n", pNtHdrs64->OptionalHeader.SizeOfImage, pNtHdrs64->OptionalHeader.SizeOfImage));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Very crude way to extract info from the file version resource.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PIMAGE_SECTION_HEADER paSectHdrs = (PIMAGE_SECTION_HEADER)( (uintptr_t)&pNtHdrs64->OptionalHeader
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)
30f07af559efcbd967e801903746fc21f81ee533vboxsync && pNtHdrs64->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RsrcDir = pNtHdrs64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pNtHdrs32->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RsrcDir = pNtHdrs32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF((" Resource Dir: %#x LB %#x\n", RsrcDir.VirtualAddress, RsrcDir.Size));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (uintptr_t)&u + sizeof(u) - (uintptr_t)paSectHdrs
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync >= pNtHdrs64->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < pNtHdrs64->FileHeader.NumberOfSections; i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress < paSectHdrs[i].SizeOfRawData
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync + (paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const struct { PCRTUTF16 pwsz; size_t cb; } s_abFields[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define MY_WIDE_STR_TUPLE(a_sz) { L ## a_sz, sizeof(L ## a_sz) - sizeof(RTUTF16) }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_abFields); i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cwcLeft = (sizeof(u) - s_abFields[i].cb - 10) / sizeof(RTUTF16);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcLeft-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (memcmp(pwc + 1, s_abFields[i].pwsz, s_abFields[i].cb + sizeof(RTUTF16)) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cwcField = s_abFields[i].cb / sizeof(RTUTF16);
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t iPadding = 0; iPadding < 3; iPadding++, pwc++, cwcLeft--)
85f99ad10a7b126cf312171061d363fe56302bdavboxsync s_abFields[i].pwsz, cwcField < 15 ? 15 - cwcField : 0, "", pwc));
85f99ad10a7b126cf312171061d363fe56302bdavboxsync 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));
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Scans the Driver directory for drivers which may invade our processes.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @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.
100b161379af7255c69e27587cc746e5f76ff050vboxsyncstatic 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" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*{ 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" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsdrivera.sys" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsha.sys" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgtdia.sys" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { 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" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINProt.sys" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINReg.sys" },
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync { 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" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdguard.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmderd.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\inspect.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdhlp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cfrmd.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\hmd.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\guard64.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdvrt64.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdkbd64.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdcsr.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Open the driver object directory.
100b161379af7255c69e27587cc746e5f76ff050vboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
100b161379af7255c69e27587cc746e5f76ff050vboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync 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));
a6c871653045073d6ef74d0589de345ae62b607dvboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync /* 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++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync supR3HardenedLogAdversarialFile(s_aFiles[i].pwszFile);
100b161379af7255c69e27587cc746e5f76ff050vboxsyncextern "C" int main(int argc, char **argv, char **envp);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * The executable entry point.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * This is normally taken care of by the C runtime library, but we don't want to
100b161379af7255c69e27587cc746e5f76ff050vboxsync * get involved with anything as complicated like the CRT in this setup. So, we
100b161379af7255c69e27587cc746e5f76ff050vboxsync * it everything ourselves, including parameter parsing.
100b161379af7255c69e27587cc746e5f76ff050vboxsyncextern "C" void __stdcall suplibHardenedWindowsMain(void)
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Initialize the NTDLL API wrappers. This aims at bypassing patched NTDLL
100b161379af7255c69e27587cc746e5f76ff050vboxsync * in all the processes leading up the VM process.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * After having resolved imports we patch the LdrInitializeThunk code so
100b161379af7255c69e27587cc746e5f76ff050vboxsync * that it's more difficult to invade our privacy by CreateRemoteThread.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * We'll re-enable this after opening the driver or temporarily while respawning.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Init g_uNtVerCombined. (The code is shared with SUPR3.lib and lives in
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Convert the arguments to UTF-8 and open the log file if specified.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * This must be done as early as possible since the code below may fail.
100b161379af7255c69e27587cc746e5f76ff050vboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
100b161379af7255c69e27587cc746e5f76ff050vboxsync char **papszArgs = suplibCommandLineToArgvWStub(pCmdLineStr->Buffer, pCmdLineStr->Length / sizeof(WCHAR), &cArgs);
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Scan the system for adversaries.
100b161379af7255c69e27587cc746e5f76ff050vboxsync g_fSupAdversaries = supR3HardenedWinFindAdversaries();
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Get the executable name.
100b161379af7255c69e27587cc746e5f76ff050vboxsync DWORD cwcExecName = GetModuleFileNameW(GetModuleHandleW(NULL), g_wszSupLibHardenedExePath,
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (cwcExecName >= RT_ELEMENTS(g_wszSupLibHardenedExePath))
a6c871653045073d6ef74d0589de345ae62b607dvboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, VERR_BUFFER_OVERFLOW,
a6c871653045073d6ef74d0589de345ae62b607dvboxsync "The executable path is too long.");
a6c871653045073d6ef74d0589de345ae62b607dvboxsync /* The NT version. */
a6c871653045073d6ef74d0589de345ae62b607dvboxsync HANDLE hFile = CreateFileW(g_wszSupLibHardenedExePath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
a6c871653045073d6ef74d0589de345ae62b607dvboxsync OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
a6c871653045073d6ef74d0589de345ae62b607dvboxsync if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
a6c871653045073d6ef74d0589de345ae62b607dvboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromWin32(GetLastError()),
a6c871653045073d6ef74d0589de345ae62b607dvboxsync "Error opening the executable: %u (%ls).", GetLastError());
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &g_SupLibHardenedExeNtPath,
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbIgn);
100b161379af7255c69e27587cc746e5f76ff050vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromNtStatus(rcNt),
100b161379af7255c69e27587cc746e5f76ff050vboxsync "NtQueryObject -> %#x (on %ls)\n", rcNt, g_wszSupLibHardenedExePath);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync /* The NT executable name offset / dir path length. */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' )
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * Call the C/C++ main function.
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Exit the process (never return).
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("Terminating the normal way: rcExit=%d\n", rcExit));