SUPR3HardenedMain-win.cpp revision cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* $Id$ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox Support Library - Hardened main(), windows bits.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
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 *
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 *
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
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/nt/nt-and-windows.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <AccCtrl.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <AclApi.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef PROCESS_SET_LIMITED_INFORMATION
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define PROCESS_SET_LIMITED_INFORMATION 0x2000
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x200
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBox/sup.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBox/err.h>
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#include <VBox/dis.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/ctype.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/initterm.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/param.h>
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#include <iprt/path.h>
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync#include <iprt/thread.h>
edde275acba04aca58db4172a163741e3abadfbcvboxsync#include <iprt/zero.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "SUPLibInternal.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "win/SUPHardenedVerify-win.h"
40839c441cb305d84420565f7ca25403d8177413vboxsync#include "../SUPDrvIOC.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifndef IMAGE_SCN_TYPE_NOLOAD
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# define IMAGE_SCN_TYPE_NOLOAD 0x00000002
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
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
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
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define SUPR3HARDENED_ASSERT(a_Expr) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do { \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!(a_Expr)) \
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("%s: %s\n", __FUNCTION__, #a_Expr); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion of NT_SUCCESS. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define SUPR3HARDENED_ASSERT_NT_SUCCESS(a_Expr) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do { \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNtAssert = (a_Expr); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNtAssert)) \
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("%s: %s -> %#x\n", __FUNCTION__, #a_Expr, rcNtAssert); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Unconditional assertion of a WIN32 API returning non-FALSE. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define SUPR3HARDENED_ASSERT_WIN32_SUCCESS(a_Expr) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do { \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync BOOL fRcAssert = (a_Expr); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fRcAssert == FALSE) \
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("%s: %s -> %#x\n", __FUNCTION__, #a_Expr, GetLastError()); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Structures and Typedefs *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Security descriptor cleanup structure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef struct MYSECURITYCLEANUP
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SID Sid;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abPadding[SECURITY_MAX_SID_SIZE];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } Everyone, Owner, User, Login;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ACL AclHdr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abPadding[1024];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } Acl;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSECURITY_DESCRIPTOR pSecDesc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync} MYSECURITYCLEANUP;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to security cleanup structure. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef MYSECURITYCLEANUP *PMYSECURITYCLEANUP;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Image verifier cache entry.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef struct VERIFIERCACHEENTRY
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Pointer to the next entry with the same hash value. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync struct VERIFIERCACHEENTRY * volatile pNext;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Next entry in the WinVerifyTrust todo list. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync struct VERIFIERCACHEENTRY * volatile pNextTodoWvt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The file handle. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** If fIndexNumber is set, this is an file system internal file identifier. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LARGE_INTEGER IndexNumber;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The path hash value. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The verification result. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc;
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync /** Used for shutting up errors after a while. */
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync uint32_t volatile cErrorHits;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /** The validation flags (for WinVerifyTrust retry). */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync uint32_t fFlags;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Whether IndexNumber is valid */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fIndexNumberValid;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Whether verified by WinVerifyTrust. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool volatile fWinVerifyTrust;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** cwcPath * sizeof(RTUTF16). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint16_t cbPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The full path of this entry (variable size). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wszPath[1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync} VERIFIERCACHEENTRY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to an image verifier path entry. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef VERIFIERCACHEENTRY *PVERIFIERCACHEENTRY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Name of an import DLL that we need to check out.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsynctypedef struct VERIFIERCACHEIMPORT
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** Pointer to the next DLL in the list. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync struct VERIFIERCACHEIMPORT * volatile pNext;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** The length of pwszAltSearchDir if available. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cwcAltSearchDir;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** This points the directory containing the DLL needing it, this will be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * NULL for a System32 DLL. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PWCHAR pwszAltSearchDir;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /** The name of the import DLL (variable length). */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync char szName[1];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync} VERIFIERCACHEIMPORT;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Pointer to a import DLL that needs checking out. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsynctypedef VERIFIERCACHEIMPORT *PVERIFIERCACHEIMPORT;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @name Global variables initialized by suplibHardenedWindowsMain.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @{ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Combined windows NT version number. See SUP_MAKE_NT_VER_COMBINED. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncuint32_t g_uNtVerCombined = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Count calls to the special main function for linking santity checks. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t volatile g_cSuplibHardenedWindowsMainCalls;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The UTF-16 windows path to the executable. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTUTF16 g_wszSupLibHardenedExePath[1024];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The NT path of the executable. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncSUPSYSROOTDIRBUF g_SupLibHardenedExeNtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The offset into g_SupLibHardenedExeNtPath of the executable name (WCHAR,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * not byte). This also gives the length of the exectuable directory path,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * including a trailing slash. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncuint32_t g_offSupLibHardenedExeNtName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @} */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @name Hook related variables.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @{ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The jump back address of the patched NtCreateSection. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncextern "C" PFNRT g_pfnNtCreateSectionJmpBack = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to the bit of assembly code that will perform the original
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * NtCreateSection operation. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic NTSTATUS (NTAPI * g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PLARGE_INTEGER, ULONG, ULONG, HANDLE);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#if 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** The jump back address of the patched LdrLoadDll. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncextern "C" PFNRT g_pfnLdrLoadDllJmpBack = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Pointer to the bit of assembly code that will perform the original
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * LdrLoadDll operation. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS (NTAPI * g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The hash table of verifier cache . */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_apVerifierCache[128];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs WinVerifyTrust to check them. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_pVerifierCacheTodoWvt = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs their imports checked. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Static error info structure used during init. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTERRINFOSTATIC g_ErrInfoStatic;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** In the assembly file. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncextern "C" uint8_t g_abSupHardReadWriteExecPage[PAGE_SIZE];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/** Whether we've patched our own LdrInitializeThunk or not. We do this to
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * disable thread creation. */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncstatic bool g_fSupInitThunkSelfPatched;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/** The backup of our own LdrInitializeThunk code, for enabling and disabling
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * thread creation in this process. */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncstatic uint8_t g_abLdrInitThunkSelfBackup[16];
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfQuietFailure);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-amd64-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# undef SYSCALL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef RT_ARCH_X86
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-x86-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# undef SYSCALL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple wide char search routine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the first location of @a wcNeedle in @a pwszHaystack.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * NULL if not found.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszHaystack Pointer to the string that should be searched.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param wcNeedle The character to search for.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic PRTUTF16 suplibHardenedWStrChr(PCRTUTF16 pwszHaystack, RTUTF16 wcNeedle)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wcCur = *pwszHaystack;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wcCur == wcNeedle)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return (PRTUTF16)pwszHaystack;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wcCur == '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszHaystack++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple wide char string length routine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns The number of characters in the given string. (Excludes the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terminator.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic size_t suplibHardenedWStrLen(PCRTUTF16 pwsz)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTUTF16 pwszCur = pwsz;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (*pwszCur != '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszCur++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pwszCur - pwsz;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Allocate zero filled memory on the heap.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the memory. Will never return NULL, triggers a fatal
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * error instead.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cb The number of bytes to allocate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void *) suplibHardenedAllocZ(size_t cb)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync void *pv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pv)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("HeapAlloc failed to allocate %zu bytes.\n", cb);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pv;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Reallocates memory on the heap.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the resized memory block. Will never return NULL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * triggers a fatal error instead.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pvOld The old memory block.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbNew The new block size.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void *) suplibHardenedReAlloc(void *pvOld, size_t cbNew)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pvOld)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return suplibHardenedAllocZ(cbNew);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync void *pv = HeapReAlloc(GetProcessHeap(), 0 /*dwFlags*/, pvOld, cbNew);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pv)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("HeapReAlloc failed to allocate %zu bytes.\n", cbNew);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pv;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Frees memory allocated by suplibHardenedAlloc, suplibHardenedAllocZ or
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * suplibHardenedReAlloc.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pv Pointer to the memeory to be freed.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) suplibHardenedFree(void *pv)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pv)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pv);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Wrapper around LoadLibraryEx that deals with the UTF-8 to UTF-16 conversion
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and supplies the right flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Module handle on success, NULL on failure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszName The full path to the DLL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fSystem32Only Whether to only look for imports in the system32
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directory. If set to false, the application
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directory is also searched.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void *) supR3HardenedWinLoadLibrary(const char *pszName, bool fSystem32Only)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WCHAR wszPath[RTPATH_MAX];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwszPath = wszPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTStrToUtf16Ex(pszName, RTSTR_MAX, &pwszPath, RT_ELEMENTS(wszPath), NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (*pwszPath)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (*pwszPath == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pwszPath = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszPath++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD fFlags = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags |= LOAD_LIBRARY_SEARCH_SYSTEM32;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!fSystem32Only)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags |= LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync void *pvRet = (void *)LoadLibraryExW(wszPath, NULL /*hFile*/, fFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Vista, W7, W2K8R might not work without KB2533623, so retry with no flags. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !pvRet
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && fFlags
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && GetLastError() == ERROR_INVALID_PARAMETER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvRet = (void *)LoadLibraryExW(wszPath, NULL /*hFile*/, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pvRet;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("RTStrToUtf16Ex failed on '%s': %Rrc", pszName, rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Gets the internal index number of the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns True if we got an index number, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file in question.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pIndexNumber where to return the index number.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedWinVerifyCacheGetIndexNumber(HANDLE hFile, PLARGE_INTEGER pIndexNumber)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryInformationFile(hFile, &Ios, pIndexNumber, sizeof(*pIndexNumber), FileInternalInformation);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = Ios.Status;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG_bird
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync __debugbreak();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NT_SUCCESS(rcNt) && pIndexNumber->QuadPart != 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Calculates the hash value for the given UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Hash value.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr String to hash.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t supR3HardenedWinVerifyCacheHashPath(PCUNICODE_STRING pUniStr)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uHash = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cwcLeft = pUniStr->Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwc = pUniStr->Buffer;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cwcLeft-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wc = *pwc++;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (wc < 0x80)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wc = wc != '/' ? RT_C_TO_LOWER(wc) : '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uHash = wc + (uHash << 6) + (uHash << 16) - uHash;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return uHash;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Calculates the hash value for a directory + filename combo as if they were
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * one single string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns Hash value.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcDir The directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcDir The length of the directory name. RTSTR_MAX if
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * not available.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pszName The import name (UTF-8).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic uint32_t supR3HardenedWinVerifyCacheHashDirAndFile(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t uHash = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (cwcDir-- > 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wc = *pawcDir++;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (wc < 0x80)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wc = wc != '/' ? RT_C_TO_LOWER(wc) : '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uHash = wc + (uHash << 6) + (uHash << 16) - uHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync unsigned char ch = '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uHash = ch + (uHash << 6) + (uHash << 16) - uHash;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while ((ch = *pszName++) != '\0')
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ch = RT_C_TO_LOWER(ch);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uHash = ch + (uHash << 6) + (uHash << 16) - uHash;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Verify string cache compare function.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns true if the strings match, false if not.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcLeft The left hand string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcRight The right hand string.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcToCompare The number of chars to compare.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic bool supR3HardenedWinVerifyCacheIsMatch(PCRTUTF16 pawcLeft, PCRTUTF16 pawcRight, uint32_t cwcToCompare)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Try a quick memory compare first. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (memcmp(pawcLeft, pawcRight, cwcToCompare * sizeof(RTUTF16)) == 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Slow char by char compare. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (cwcToCompare-- > 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wcLeft = *pawcLeft++;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wcRight = *pawcRight++;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (wcLeft != wcRight)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wcLeft = wcLeft != '/' ? RT_C_TO_LOWER(wcLeft) : '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wcLeft = wcRight != '/' ? RT_C_TO_LOWER(wcRight) : '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (wcLeft != wcRight)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Inserts the given verifier result into the cache.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr The full path of the image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file handle - must either be entered into
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the cache or closed.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param rc The verifier result.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param fWinVerifyTrust Whether verified by WinVerifyTrust or not.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * @param fFlags The image verification flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync bool fWinVerifyTrust, uint32_t fFlags)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Allocate and initalize a new entry.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync sizeof(VERIFIERCACHEENTRY) + pUniStr->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pEntry)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->pNext = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->pNextTodoWvt = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->hFile = hFile;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync pEntry->rc = rc;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pEntry->fFlags = fFlags;
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync pEntry->cErrorHits = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->fWinVerifyTrust = fWinVerifyTrust;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->cbPath = pUniStr->Length;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(pEntry->wszPath, pUniStr->Buffer, pUniStr->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->wszPath[pUniStr->Length / sizeof(WCHAR)] = '\0';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &pEntry->IndexNumber);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try insert it, careful with concurrent code as well as potential duplicates.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t iHashTab = pEntry->uHash % RT_ELEMENTS(g_apVerifierCache);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync VERIFIERCACHEENTRY * volatile *ppEntry = &g_apVerifierCache[iHashTab];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (ASMAtomicCmpXchgPtr(ppEntry, pEntry, NULL))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!fWinVerifyTrust)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync do
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pEntry->pNextTodoWvt = g_pVerifierCacheTodoWvt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pEntry, pEntry->pNextTodoWvt));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheInsert: %ls\n", pUniStr->Buffer));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEENTRY pOther = *ppEntry;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pOther)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync continue;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( pOther->uHash == pEntry->uHash
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pOther->cbPath == pEntry->cbPath
e17f6f8a70a7709a9a6319d9a473596fb600b552vboxsync && supR3HardenedWinVerifyCacheIsMatch(pOther->wszPath, pEntry->wszPath, pEntry->cbPath / sizeof(RTUTF16)))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync break;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ppEntry = &pOther->pNext;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Duplicate entry (may happen due to races). */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pEntry);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtClose(hFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Looks up an entry in the verifier hash table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @return Pointer to the entry on if found, NULL if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStr The full path of the image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookup(PCUNICODE_STRING pUniStr, HANDLE hFile)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 const pwszPath = pUniStr->Buffer;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint16_t const cbPath = pUniStr->Length;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t uHash = supR3HardenedWinVerifyCacheHashPath(pUniStr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t iHashTab = uHash % RT_ELEMENTS(g_apVerifierCache);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PVERIFIERCACHEENTRY pCur = g_apVerifierCache[iHashTab];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (pCur)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pCur->uHash == uHash
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pCur->cbPath == cbPath
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pwszPath, cbPath / sizeof(RTUTF16)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pCur->fIndexNumberValid)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pCur;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LARGE_INTEGER IndexNumber;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &IndexNumber);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( fIndexNumberValid
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && IndexNumber.QuadPart == pCur->IndexNumber.QuadPart)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pCur;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG_bird
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync __debugbreak();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCur = pCur->pNext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Looks up an import DLL in the verifier hash table.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @return Pointer to the entry on if found, NULL if not.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pawcDir The directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param cwcDir The length of the directory name.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pszName The import name (UTF-8).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookupImport(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
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 while (pCur)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( pCur->uHash == uHash
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pCur->cbPath == cbPath)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pawcDir, cwcDir))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pCur->wszPath[cwcDir] == '\\' || pCur->wszPath[cwcDir] == '/')
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (RTUtf16ICmpAscii(&pCur->wszPath[cwcDir + 1], pszName))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return pCur;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pCur = pCur->pNext;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Schedules the import DLLs for verification and entry into the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hLdrMod The loader module which imports should be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * scheduled for verification.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszName The full NT path of the module.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyCacheScheduleImports(RTLDRMOD hLdrMod, PCRTUTF16 pwszName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Any imports?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cImports;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_COUNT, NULL /*pvBits*/, &cImports, sizeof(cImports), NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (RT_SUCCESS(rc))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (cImports)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Figure out the DLL directory from pwszName.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PCRTUTF16 pawcDir = pwszName;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cwcDir = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t i = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wc;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while ((wc = pawcDir[i++]) != '\0')
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ((wc == '\\' || wc == '/' || wc == ':') && cwcDir + 2 != i)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cwcDir = i - 1;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( g_System32NtPath.UniStr.Length / sizeof(WCHAR) == cwcDir
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && supR3HardenedWinVerifyCacheIsMatch(pawcDir, g_System32NtPath.UniStr.Buffer, cwcDir))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pawcDir = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Enumerate the imports.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync for (i = 0; i < cImports; i++)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync union
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync char szName[256];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t iImport;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync } uBuf;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uBuf.iImport = i;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_MODULE, NULL /*pvBits*/, &uBuf, sizeof(uBuf), NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (RT_SUCCESS(rc))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Skip kernel32, ntdll and API set stuff.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTStrToLower(uBuf.szName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( RTStrCmp(uBuf.szName, "kernel32.dll") == 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || RTStrCmp(uBuf.szName, "kernelbase.dll") == 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || RTStrCmp(uBuf.szName, "ntdll.dll") == 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || RTStrNCmp(uBuf.szName, RT_STR_TUPLE("api-ms-win-")) == 0 )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync continue;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Skip to the next one if it's already in the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_System32NtPath.UniStr.Length / sizeof(WCHAR),
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uBuf.szName) != NULL)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for system32\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync continue;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_offSupLibHardenedExeNtName,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uBuf.szName) != NULL)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for appdir\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync continue;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pawcDir && supR3HardenedWinVerifyCacheLookupImport(pawcDir, cwcDir, uBuf.szName) != NULL)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for dll dir\n", uBuf.szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync continue;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* We could skip already scheduled modules, but that'll require serialization and extra work... */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Add it to the todo list.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
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 + (pawcDir ? (cwcDir + 1) * sizeof(RTUTF16) : 0);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEIMPORT pImport = (PVERIFIERCACHEIMPORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNeeded);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pImport)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Init it. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(pImport->szName, uBuf.szName, cbName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pawcDir)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->cwcAltSearchDir = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->pwszAltSearchDir = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->cwcAltSearchDir = cwcDir;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->pwszAltSearchDir = (PRTUTF16)&pImport->szName[cbNameAligned];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(pImport->pwszAltSearchDir, pawcDir, cwcDir * sizeof(RTUTF16));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->pwszAltSearchDir[cwcDir] = '\0';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Insert it. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync do
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pImport->pNext = g_pVerifierCacheTodoImports;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoImports, pImport, pImport->pNext));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("RTLDRPROP_IMPORT_MODULE failed with rc=%Rrc i=%#x on '%ls'\n", rc, i, pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("'%ls' has no imports\n", pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("RTLDRPROP_IMPORT_COUNT failed with rc=%Rrc on '%ls'\n", rc, pwszName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Processes the list of import todos.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic void supR3HardenedWinVerifyCacheProcessImportTodos(void)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Work until we've got nothing more todo.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync for (;;)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEIMPORT pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoImports, NULL, PVERIFIERCACHEIMPORT);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pTodo)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync break;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync do
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PVERIFIERCACHEIMPORT pCur = pTodo;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pTodo = pTodo->pNext;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Not in the cached already?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( !supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_System32NtPath.UniStr.Length / sizeof(WCHAR),
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pCur->szName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && !supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_offSupLibHardenedExeNtName,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pCur->szName)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && ( pCur->cwcAltSearchDir == 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || !supR3HardenedWinVerifyCacheLookupImport(pCur->pwszAltSearchDir, pCur->cwcAltSearchDir, pCur->szName)) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try locate the imported DLL and open it.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Processing '%s'...\n", pCur->szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync NTSTATUS rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync HANDLE hFile = INVALID_HANDLE_VALUE;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUTF16 wszPath[260 + 260]; /* Assumes we've limited the import name length to 256. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync AssertCompile(sizeof(wszPath) > sizeof(g_System32NtPath));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync /*
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Check for DLL isolation / redirection / mapping.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync size_t cwcName = 260;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PRTUTF16 pwszName = &wszPath[0];
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync int rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (RT_SUCCESS(rc))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING UniStrName;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrName.Buffer = wszPath;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrName.Length = (USHORT)cwcName * sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING UniStrStatic;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrStatic.Buffer = &wszPath[cwcName + 1];
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UniStrStatic.Length = 0;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync UniStrStatic.MaximumLength = (USHORT)(sizeof(wszPath) - cwcName * sizeof(WCHAR) - sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING UniStrDynamic = { 0, 0, NULL };
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PUNICODE_STRING pUniStrResult = NULL;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &UniStrName,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync (PUNICODE_STRING)&s_DefaultSuffix,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &UniStrStatic,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &UniStrDynamic,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &pUniStrResult,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pNewFlags*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pcbFilename*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pcbNeeded*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync OBJECT_ATTRIBUTES ObjAttr;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync InitializeObjectAttributes(&ObjAttr, pUniStrResult,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = NtCreateFile(&hFile,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &ObjAttr,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &Ios,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /* Allocation Size*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_ATTRIBUTE_NORMAL,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_SHARE_READ,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_OPEN,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*EaBuffer*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync 0 /*EaLength*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = Ios.Status;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (!NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync hFile = INVALID_HANDLE_VALUE;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync RtlFreeUnicodeString(&UniStrDynamic);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync else
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex #1 failed: %Rrc\n", rc));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync /*
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * If not something that gets remapped, do the half normal searching we need.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (hFile == INVALID_HANDLE_VALUE)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync struct
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PRTUTF16 pawcDir;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync uint32_t cwcDir;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync } Tmp, aDirs[] =
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync { g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length / sizeof(WCHAR) },
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync { g_SupLibHardenedExeNtPath.UniStr.Buffer, g_offSupLibHardenedExeNtName - 1 },
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync { pCur->pwszAltSearchDir, pCur->cwcAltSearchDir },
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync };
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync /* Search System32 first, unless it's a 'V*' or 'm*' name, the latter for msvcrt. */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if ( pCur->szName[0] == 'v'
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync || pCur->szName[0] == 'V'
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync || pCur->szName[0] == 'm'
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync || pCur->szName[0] == 'M')
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync Tmp = aDirs[0];
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync aDirs[0] = aDirs[1];
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync aDirs[1] = Tmp;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync for (uint32_t i = 0; i < RT_ELEMENTS(aDirs); i++)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (aDirs[i].pawcDir && aDirs[i].cwcDir && aDirs[i].cwcDir < RT_ELEMENTS(wszPath) / 3 * 2)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(wszPath, aDirs[i].pawcDir, aDirs[i].cwcDir * sizeof(RTUTF16));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync uint32_t cwc = aDirs[i].cwcDir;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wszPath[cwc++] = '\\';
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync cwcName = RT_ELEMENTS(wszPath) - cwc;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync pwszName = &wszPath[cwc];
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (RT_SUCCESS(rc))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING NtName;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NtName.Buffer = wszPath;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NtName.Length = (USHORT)((cwc + cwcName) * sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync OBJECT_ATTRIBUTES ObjAttr;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = NtCreateFile(&hFile,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &ObjAttr,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &Ios,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /* Allocation Size*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_ATTRIBUTE_NORMAL,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_SHARE_READ,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_OPEN,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*EaBuffer*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync 0 /*EaLength*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = Ios.Status;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync break;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync hFile = INVALID_HANDLE_VALUE;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync else
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex #2 failed: %Rrc\n", rc));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * If we successfully opened it, verify it and cache the result.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (hFile != INVALID_HANDLE_VALUE)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' -> '%ls'\n", pCur->szName, wszPath));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ULONG fAccess = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ULONG fProtect = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fCallRealApi = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "Imports", false /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync NtClose(hFile);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Failed to locate '%s'\n", pCur->szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' is in the cache.\n", pCur->szName));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pCur);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync } while (pTodo);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync/**
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Processes the list of WinVerifyTrust todos.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic void supR3HardenedWinVerifyCacheProcessWvtTodos(void)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync{
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY pReschedule = NULL;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY volatile *ppReschedLastNext = NULL;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /*
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Work until we've got nothing more todo.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync for (;;)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (!supHardenedWinIsWinVerifyTrustCallable())
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync break;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoWvt, NULL, PVERIFIERCACHEENTRY);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (!pTodo)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync break;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync do
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync PVERIFIERCACHEENTRY pCur = pTodo;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pTodo = pTodo->pNextTodoWvt;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCur->pNextTodoWvt = NULL;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if ( !pCur->fWinVerifyTrust
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync && RT_SUCCESS(pCur->rc))
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync bool fWinVerifyTrust = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync int rc = supHardenedWinVerifyImageTrust(pCur->hFile, pCur->wszPath, pCur->fFlags, pCur->rc,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync &fWinVerifyTrust, NULL /* pErrInfo*/);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (RT_FAILURE(rc) || fWinVerifyTrust)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rc, pCur->rc, fWinVerifyTrust, pCur->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCur->fWinVerifyTrust = true;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCur->rc = rc;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync else
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Retry it at a later time. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessWvtTodos: %d (was %d) fWinVerifyTrust=%d for '%ls' [rescheduled]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rc, pCur->rc, fWinVerifyTrust, pCur->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (!pReschedule)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync ppReschedLastNext = &pCur->pNextTodoWvt;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCur->pNextTodoWvt = pReschedule;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* else: already processed. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync } while (pTodo);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /*
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Anything to reschedule.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (pReschedule)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync do
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync *ppReschedLastNext = g_pVerifierCacheTodoWvt;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pReschedule, *ppReschedLastNext));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync}
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync/**
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Checks whether the path could be containing alternative 8.3 names generated
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * by NTFS, FAT, or other similar file systems.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync *
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @returns Pointer to the first component that might be an 8.3 name, NULL if
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * not 8.3 path.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param pwszPath The path to check.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsyncstatic PRTUTF16 supR3HardenedWinIsPossible8dot3Path(PCRTUTF16 pwszPath)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync{
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync PCRTUTF16 pwszName = pwszPath;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync for (;;)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync RTUTF16 wc = *pwszPath++;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (wc == '~')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* Could check more here before jumping to conclusions... */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (pwszPath - pwszName <= 8+1+3)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync return (PRTUTF16)pwszName;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync else if (wc == '\\' || wc == '/' || wc == ':')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszName = pwszPath;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync else if (wc == 0)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync break;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync return NULL;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync}
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync/**
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * Fixes up a path possibly containing one or more alternative 8-dot-3 style
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * components.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync *
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * The path is fixed up in place. Errors are ignored.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync *
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param hFile The handle to the file which path we're fixing up.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * @param pUniStr The path to fix up. MaximumLength is the max buffer
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * length.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsyncstatic void supR3HardenedWinFix8dot3Path(HANDLE hFile, PUNICODE_STRING pUniStr)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync{
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /*
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * We could use FileNormalizedNameInformation here and slap the volume device
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * path in front of the result, but it's only supported since windows 8.0
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync * according to some docs... So we expand all supicious names.
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync PRTUTF16 pwszFix = pUniStr->Buffer;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync while (*pwszFix)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszFix = supR3HardenedWinIsPossible8dot3Path(pwszFix);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (pwszFix == NULL)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync break;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync RTUTF16 wc;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync PRTUTF16 pwszFixEnd = pwszFix;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '//')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszFixEnd++;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (wc == '\0')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync break;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync RTUTF16 const wcSaved = *pwszFix;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync *pwszFix = '\0'; /* paranoia. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync UNICODE_STRING NtDir;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtDir.Buffer = pUniStr->Buffer;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync HANDLE hDir = RTNT_INVALID_HANDLE_VALUE;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync OBJECT_ATTRIBUTES ObjAttr;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NTSTATUS rcNt = NtCreateFile(&hDir,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_READ_DATA | SYNCHRONIZE,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync &ObjAttr,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync &Ios,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NULL /* Allocation Size*/,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_ATTRIBUTE_NORMAL,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_OPEN,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NULL /*EaBuffer*/,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync 0 /*EaLength*/);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync *pwszFix = wcSaved;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (NT_SUCCESS(rcNt))
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync union
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FILE_BOTH_DIR_INFORMATION Info;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync } uBuf;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync RT_ZERO(uBuf);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync UNICODE_STRING NtFilterStr;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtFilterStr.Buffer = pwszFix;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtFilterStr.MaximumLength = NtFilterStr.Length;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync rcNt = NtQueryDirectoryFile(hDir,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NULL /* Event */,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NULL /* ApcRoutine */,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NULL /* ApcContext */,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync &Ios,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync &uBuf,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync sizeof(uBuf) - sizeof(WCHAR),
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FileBothDirectoryInformation,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FALSE /*ReturnSingleEntry*/,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync &NtFilterStr,
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync FALSE /*RestartScan */);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (NT_SUCCESS(rcNt) && uBuf.Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint32_t offName = uBuf.Info.FileNameLength / sizeof(WCHAR);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync while (offName > 0 && uBuf.Info.FileName[offName - 1] != '\\' && uBuf.Info.FileName[offName - 1] != '/')
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync offName--;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint32_t cwcNameNew = (uBuf.Info.FileNameLength / sizeof(WCHAR)) - offName;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync uint32_t cwcNameOld = pwszFixEnd - pwszFix;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync if (cwcNameOld == cwcNameNew)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync <= pUniStr->MaximumLength)
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync {
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 pwszFixEnd -= cwcNameOld;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszFixEnd -= cwcNameNew;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* else: ignore overflow. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* else: ignore failure. */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync NtClose(hDir);
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync /* Advance */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync pwszFix = pwszFixEnd;
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync }
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync}
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool *pfQuietFailure)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfCallRealApi = false;
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync if (pfQuietFailure)
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync *pfQuietFailure = false;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Query the name of the file, making sure to zero terminator the
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * string. (2nd half of buffer is used for error info, see below.)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UNICODE_STRING UniStr;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync uint8_t abBuffer[sizeof(UNICODE_STRING) + 2048 * sizeof(WCHAR)];
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync } uBuf;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync RT_ZERO(uBuf);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync ULONG cbNameBuf;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR) - 128, &cbNameBuf);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (!NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, fImage, *pfProtect, *pfAccess);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return rcNt;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync uBuf.UniStr.MaximumLength = sizeof(uBuf) - 128;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinFix8dot3Path(hFile, &uBuf.UniStr);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Check the cache.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (pCacheHit)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* If we haven't done the WinVerifyTrust thing, do it if we can. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if ( !pCacheHit->fWinVerifyTrust
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync && RT_SUCCESS(pCacheHit->rc)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync && supHardenedWinIsWinVerifyTrustCallable() )
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (!fAvoidWinVerifyTrust)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [redoing WinVerifyTrust]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, pCacheHit->rc, pCacheHit->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync bool fWinVerifyTrust = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync int rc = supHardenedWinVerifyImageTrust(pCacheHit->hFile, pCacheHit->wszPath, pCacheHit->fFlags, pCacheHit->rc,
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync &fWinVerifyTrust, NULL /* pErrInfo*/);
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (RT_FAILURE(rc) || fWinVerifyTrust)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync {
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: %d (was %d) fWinVerifyTrust=%d for '%ls'\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, rc, pCacheHit->rc, fWinVerifyTrust, pCacheHit->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCacheHit->fWinVerifyTrust = true;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pCacheHit->rc = rc;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync else
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: WinVerifyTrust not available, rescheduling %ls\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, pCacheHit->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync else
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls [avoiding WinVerifyTrust]\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, pCacheHit->rc, pCacheHit->wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync }
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync else if (pCacheHit->cErrorHits < 16)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls%s\n",
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync pszCaller, pCacheHit->rc, pCacheHit->wszPath, pCacheHit->fWinVerifyTrust ? "" : " [lacks WinVerifyTrust]"));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /* Return the cached value. */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (RT_SUCCESS(pCacheHit->rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfCallRealApi = true;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_SUCCESS;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync uint32_t cErrorHits = ASMAtomicIncU32(&pCacheHit->cErrorHits);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync if ( cErrorHits < 8
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync || RT_IS_POWER_OF_TWO(cErrorHits))
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync supR3HardenedError(VINF_SUCCESS, false,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "supR3HardenedScreenImage/%s: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x cErrorHits=%u %ls\n",
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync pszCaller, pCacheHit->rc, fImage, *pfProtect, *pfAccess, cErrorHits, uBuf.UniStr.Buffer);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync else if (pfQuietFailure)
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync *pfQuietFailure = true;
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_TRUST_FAILURE;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
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 */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync HANDLE hMyFile = NULL;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hFile, NtCurrentProcess(),
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync &hMyFile,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 0 /* Handle attributes*/, 0 /* Options */);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (!NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (rcNt == STATUS_ACCESS_DENIED)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync OBJECT_ATTRIBUTES ObjAttr;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rcNt = NtCreateFile(&hMyFile,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync &ObjAttr,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync &Ios,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NULL /* Allocation Size*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_ATTRIBUTE_NORMAL,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_SHARE_READ,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_OPEN,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NULL /*EaBuffer*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 0 /*EaLength*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rcNt = Ios.Status;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, rcNt, hFile, uBuf.UniStr.Buffer);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rcNt;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /* Check that we've got the same file. */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync LARGE_INTEGER idMyFile, idInFile;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fMyValid = supR3HardenedWinVerifyCacheGetIndexNumber(hMyFile, &idMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fInValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &idInFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if ( fMyValid
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && ( fMyValid != fInValid
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync || idMyFile.QuadPart != idInFile.QuadPart))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hMyFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return STATUS_TRUST_FAILURE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: NtDuplicateObject -> %#x\n", pszCaller, rcNt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef DEBUG
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: NtDuplicateObject(,%#x,) failed: %#x\n", pszCaller, hFile, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync hMyFile = hFile;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
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 */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if ( !fImage
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 {
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 {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Drop all executable access to the mapping and let it continue.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedScreenImage/%s: Applying the drop-exec-kludge for '%ls'\n", pszCaller, uBuf.UniStr.Buffer));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (*pfAccess & SECTION_MAP_EXECUTE)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfAccess = (*pfAccess & ~SECTION_MAP_EXECUTE) | SECTION_MAP_READ;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (*pfProtect & PAGE_EXECUTE)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfProtect = (*pfProtect & ~PAGE_EXECUTE) | PAGE_READONLY;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfProtect = (*pfProtect & ~UINT32_C(0xf0)) | ((*pfProtect & UINT32_C(0xe0)) >> 4);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (hMyFile != hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfCallRealApi = true;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_SUCCESS;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#ifndef VBOX_PERMIT_EVEN_MORE
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Check the path. We don't allow DLLs to be loaded from just anywhere:
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 1. System32 - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 2. WinSxS - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 3. VirtualBox - kernel code signing and integrity checks.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 4. AppPatchDir - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 5. Program Files - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 6. Common Files - normal code or cat signing, owner TrustedInstaller.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * 7. x86 variations of 4 & 5 - ditto.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync uint32_t fFlags = 0;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_System32NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_WinSxSNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync g_SupLibHardenedExeNtPath.UniStr.Buffer,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifdef VBOX_PERMIT_MORE
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViIsAppPatchDir(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR)))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesNtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifdef RT_ARCH_AMD64
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_ProgramFilesX86NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else if (supHardViUniStrPathStartsWithUniStr(&uBuf.UniStr, &g_CommonFilesX86NtPath.UniStr, true /*fCheckSlash*/))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifdef VBOX_PERMIT_VISUAL_STUDIO_PROFILING
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 {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (hMyFile != hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfCallRealApi = true;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_SUCCESS;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync else
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedError(VINF_SUCCESS, false,
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync "supR3HardenedScreenImage/%s: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (hMyFile != hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_TRUST_FAILURE;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#else /* VBOX_PERMIT_EVEN_MORE */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync /*
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Require trusted installer + some kind of signature on everything, except
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * for the VBox bits where we require kernel code signing and special
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * integrity checks.
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync Assert(g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] == '\\');
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync uint32_t fFlags = 0;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if (supHardViUtf16PathStartsWithEx(uBuf.UniStr.Buffer, uBuf.UniStr.Length / sizeof(WCHAR),
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync g_SupLibHardenedExeNtPath.UniStr.Buffer,
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync g_offSupLibHardenedExeNtName, false /*fCheckSlash*/))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync fFlags |= SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING | SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync else
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync fFlags |= SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION | SUPHNTVI_F_TRUSTED_INSTALLER_OWNER;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#endif /* VBOX_PERMIT_EVEN_MORE */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Do the verification. For better error message we borrow what's
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * left of the path buffer for an RTERRINFO buffer.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync RTERRINFO ErrInfo;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync RTErrInfoInit(&ErrInfo, (char *)&uBuf.abBuffer[cbNameBuf], sizeof(uBuf) - cbNameBuf);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync int rc;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fWinVerifyTrust = false;
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, fAvoidWinVerifyTrust, &fWinVerifyTrust, &ErrInfo);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (RT_FAILURE(rc))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedScreenImage/%s: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszCaller, rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (hMyFile != hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hMyFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_TRUST_FAILURE;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Insert into the cache.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync if (hMyFile != hFile)
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust, fFlags);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *pfCallRealApi = true;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return STATUS_SUCCESS;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync}
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync/**
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Preloads a file into the verify cache if possible.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * This is used to avoid known cyclic LoadLibrary issues with WinVerifyTrust.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pwszName The name of the DLL to verify.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyCachePreload(PCRTUTF16 pwszName)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync{
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UNICODE_STRING UniStr;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UniStr.Buffer = (PWCHAR)pwszName;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UniStr.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync UniStr.MaximumLength = UniStr.Length + sizeof(WCHAR);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync OBJECT_ATTRIBUTES ObjAttr;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync InitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync &ObjAttr,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync &Ios,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NULL /* Allocation Size*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_ATTRIBUTE_NORMAL,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_SHARE_READ,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_OPEN,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NULL /*EaBuffer*/,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 0 /*EaLength*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync rcNt = Ios.Status;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (!NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: Error %#x opening '%ls'.\n", rcNt, pwszName));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync ULONG fAccess = 0;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync ULONG fProtect = 0;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fCallRealApi;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: scanning %ls\n", pwszName));
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, "preload", false /*fAvoidWinVerifyTrust*/,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync NULL /*pfQuietFailure*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: done %ls\n", pwszName));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync NtClose(hFile);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync}
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync/**
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Hook that monitors NtCreateSection calls.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @returns NT status code.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param phSection Where to return the section handle.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fAccess The desired access.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pObjAttribs The object attributes (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pcbSection The section size (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fProtect The max section protection.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param fAttribs The section attributes.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param hFile The file to create a section from (optional).
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncstatic NTSTATUS NTAPI
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncsupR3HardenedMonitor_NtCreateSection(PHANDLE phSection, ACCESS_MASK fAccess, POBJECT_ATTRIBUTES pObjAttribs,
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync PLARGE_INTEGER pcbSection, ULONG fProtect, ULONG fAttribs, HANDLE hFile)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync{
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if ( hFile != NULL
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && hFile != INVALID_HANDLE_VALUE)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
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 | PAGE_EXECUTE_READWRITE));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (fImage || fExecMap || fExecProt)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DWORD dwSavedLastError = GetLastError();
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync bool fCallRealApi;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 1\n"));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "NtCreateSection", true /*fAvoidWinVerifyTrust*/, NULL /*pfQuietFailure*/);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 2 rcNt=%#x fCallRealApi=%#x\n", rcNt, fCallRealApi));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SetLastError(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (!NT_SUCCESS(rcNt))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return rcNt;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync Assert(fCallRealApi);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (!fCallRealApi)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return STATUS_TRUST_FAILURE;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Call checked out OK, call the original.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/**
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hooks that intercepts LdrLoadDll calls.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Two purposes:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * -# Enforce our own search path restrictions.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * -# Prevalidate DLLs about to be loaded so we don't upset the loader data
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * by doing it from within the NtCreateSection hook (WinVerifyTrust
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * seems to be doing harm there on W7/32).
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @returns
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszSearchPath The search path to use.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pfFlags Flags on input. DLL characteristics or something
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * on return?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pName The name of the module.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param phMod Where the handle of the loaded DLL is to be
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * returned to the caller.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS NTAPI
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncsupR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_STRING pName, PHANDLE phMod)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync DWORD dwSavedLastError = GetLastError();
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NTSTATUS rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync /*
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync * Process WinVerifyTrust todo before and after.
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync supR3HardenedWinVerifyCacheProcessWvtTodos();
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject things we don't want to deal with.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pName || pName->Length == 0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: name is NULL or have a zero length.\n");
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_INVALID_PARAMETER));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return STATUS_INVALID_PARAMETER;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject long paths that's close to the 260 limit without looking.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pName->Length > 256 * sizeof(WCHAR))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: too long name: %#x bytes\n", pName->Length);
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return STATUS_NAME_TOO_LONG;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Absolute path?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fSkipValidation = false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync WCHAR wszPath[260];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UNICODE_STRING ResolvedName;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( ( pName->Length >= 4 * sizeof(WCHAR)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && RT_C_IS_ALPHA(pName->Buffer[0])
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pName->Buffer[1] == ':'
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && RTPATH_IS_SLASH(pName->Buffer[2]) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || ( pName->Length >= 1 * sizeof(WCHAR)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && RTPATH_IS_SLASH(pName->Buffer[1]) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(wszPath, pName->Buffer, pName->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wszPath[pName->Length / sizeof(WCHAR)] = '\0';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Not an absolute path. Check if it's one of those special API set DLLs
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * or something we're known to use but should be taken from WinSxS.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if (supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync L"api-ms-win-", 11, false /*fCheckSlash*/))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(wszPath, pName->Buffer, pName->Length);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wszPath[pName->Length / sizeof(WCHAR)] = '\0';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fSkipValidation = true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Not an absolute path or special API set. There are two alternatives
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * now, either there is no path at all or there is a relative path. We
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * will resolve it to an absolute path in either case, failing the call
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * if we can't.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PCWCHAR pawcName = pName->Buffer;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cwcName = pName->Length / sizeof(WCHAR);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t offLastSlash = UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t offLastDot = UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync for (uint32_t i = 0; i < cwcName; i++)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync switch (pawcName[i])
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync case '\\':
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync case '/':
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offLastSlash = i;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offLastDot = UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync break;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync case '.':
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offLastDot = i;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync break;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool const fNeedDllSuffix = offLastDot == UINT32_MAX && offLastSlash == UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (offLastDot != UINT32_MAX && offLastDot == cwcName - 1)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cwcName--;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Reject relative paths for now as they might be breakout attempts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (offLastSlash != UINT32_MAX)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedError(VINF_SUCCESS, false,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "supR3HardenedMonitor_LdrLoadDll: relative name not permitted: %.*ls\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cwcName, pawcName);
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return STATUS_OBJECT_NAME_INVALID;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Perform dll redirection to WinSxS such. We using an undocumented
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * API here, which as always is a bit risky... ASSUMES that the API
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * returns a full DOS path.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UINT cwc;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING UniStrStatic = { 0, (USHORT)sizeof(wszPath) - sizeof(WCHAR), wszPath };
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync UNICODE_STRING UniStrDynamic = { 0, 0, NULL };
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync PUNICODE_STRING pUniStrResult = NULL;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync pName,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync (PUNICODE_STRING)&s_DefaultSuffix,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &UniStrStatic,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &UniStrDynamic,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync &pUniStrResult,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pNewFlags*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pcbFilename*/,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NULL /*pcbNeeded*/);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (NT_SUCCESS(rcNt))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync cwc = pUniStrResult->Length / sizeof(WCHAR);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (pUniStrResult != &UniStrDynamic)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wszPath[cwc] = '\0';
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync else
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (pUniStrResult->Length > sizeof(wszPath) - sizeof(WCHAR))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync supR3HardenedError(VINF_SUCCESS, false,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long: %.*ls -> %.*ls (RtlDosApplyFileIoslationRedirection_Ustr)\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync pName->Length / sizeof(WCHAR), pName->Buffer,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync pUniStrResult->Length / sizeof(WCHAR), pUniStrResult->Buffer);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync RtlFreeUnicodeString(&UniStrDynamic);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return STATUS_NAME_TOO_LONG;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(&wszPath[0], pUniStrResult->Buffer, pUniStrResult->Length);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wszPath[cwc] = '\0';
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync RtlFreeUnicodeString(&UniStrDynamic);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync /*
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Search for the DLL. Only System32 is allowed as the target of
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * a search on the API level, all VBox calls will have full paths.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync cwc = GetSystemDirectoryW(wszPath, RT_ELEMENTS(wszPath) - 32);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (!cwc)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync supR3HardenedError(VINF_SUCCESS, false,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "supR3HardenedMonitor_LdrLoadDll: GetSystemDirectoryW failed: %u\n", GetLastError());
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_UNEXPECTED_IO_ERROR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return STATUS_UNEXPECTED_IO_ERROR;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync supR3HardenedError(VINF_SUCCESS, false,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcName, pawcName);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_NAME_TOO_LONG));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return STATUS_NAME_TOO_LONG;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wszPath[cwc++] = '\\';
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync cwc += cwcName;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (!fNeedDllSuffix)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wszPath[cwc] = '\0';
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync else
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync memcpy(&wszPath[cwc], L".dll", 5 * sizeof(WCHAR));
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync cwc += 4;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.Buffer = wszPath;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [rcNt=%#x]\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer, rcNt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pName = &ResolvedName;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!fSkipValidation)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Try open the file. If this fails, never mind, just pass it on to
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * the real API as we've replaced any searchable name with a full name
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and the real API can come up with a fitting status code for it.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync HANDLE hFile = CreateFileW(wszPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (hFile != INVALID_HANDLE_VALUE)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ULONG fAccess = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ULONG fProtect = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fCallRealApi = false;
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync bool fQuietFailure = false;
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync "LdrLoadDll", false /*fAvoidWinVerifyTrust*/, &fQuietFailure);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync NtClose(hFile);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!NT_SUCCESS(rcNt))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync if (!fQuietFailure)
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync {
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: rejecting '%ls': rcNt=%#x\n",
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync wszPath, rcNt);
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
eb259de2a9eac4b4dda56e89f5004671f926bd9bvboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinVerifyCacheProcessImportTodos();
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DWORD dwErr = GetLastError();
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u\n", wszPath, dwErr));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Screened successfully enough. Call the real thing.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SetLastError(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = g_pfnLdrLoadDllReal(pwszSearchPath, pfFlags, pName, phMod);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync /*
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * Log the result and process pending WinVerifyTrust work if we can.
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync dwSavedLastError = GetLastError();
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (NT_SUCCESS(rcNt) && phMod)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x hMod=%p '%ls'\n", rcNt, *phMod, wszPath));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync supR3HardenedWinVerifyCacheProcessWvtTodos();
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SetLastError(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Tries to allocate memory between @a uStart and @a uEnd.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the memory on success. NULL on failure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param uStart The start address.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param uEnd The end address. This is lower than @a uStart
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * if @a iDirection is negative, and higher if
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * positive.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param iDirection The search direction.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbAlloc The number of bytes to allocate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic void *supR3HardenedWinAllocHookMemory(uintptr_t uStart, uintptr_t uEnd, intptr_t iDirection, size_t cbAlloc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t const cbAllocGranularity = _64K;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t const uAllocGranularityMask = ~(cbAllocGranularity - 1);
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync HANDLE const hProc = NtCurrentProcess();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Make uEnd the last valid return address.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iDirection > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(uEnd > cbAlloc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uEnd -= cbAlloc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uEnd &= uAllocGranularityMask;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uEnd = RT_ALIGN_Z(uEnd, cbAllocGranularity);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Search for free memory.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uintptr_t uCur = uStart & uAllocGranularityMask;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Examine the memory at this address, if it's free, try make the allocation here.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SIZE_T cbIgn;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync MEMORY_BASIC_INFORMATION MemInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtQueryVirtualMemory(hProc,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (void *)uCur,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync MemoryBasicInformation,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &MemInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(MemInfo),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &cbIgn));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( MemInfo.State == MEM_FREE
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && MemInfo.RegionSize >= cbAlloc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT((uintptr_t)MemInfo.BaseAddress <= uCur);
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync PVOID pvMem = (PVOID)uCur;
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync SIZE_T cbMem = cbAlloc;
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NTSTATUS rcNt = NtAllocateVirtualMemory(hProc, &pvMem, 0 /*ZeroBits*/, &cbAlloc,
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( iDirection > 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ? (uintptr_t)pvMem >= uStart
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (uintptr_t)pvMem <= uEnd
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync : (uintptr_t)pvMem >= uEnd
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (uintptr_t)pvMem <= uStart)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pvMem;
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NtFreeVirtualMemory(hProc, &pvMem, &cbMem, MEM_RELEASE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Advance within the free area and try again? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uintptr_t uNext = iDirection > 0 ? uCur + cbAllocGranularity : uCur - cbAllocGranularity;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uNext &= uAllocGranularityMask;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( iDirection > 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ? uNext <= uCur
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || uNext > uEnd
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || uNext - (uintptr_t)MemInfo.BaseAddress > MemInfo.RegionSize
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || MemInfo.RegionSize - (uNext - (uintptr_t)MemInfo.BaseAddress) < cbAlloc
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync : uNext >= uCur
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || uNext < uEnd
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || uNext < (uintptr_t)MemInfo.BaseAddress)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur = uNext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Advance to the next memory region.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iDirection > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur = (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur = RT_ALIGN_Z(uCur, cbAllocGranularity);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uCur >= uEnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur = (uintptr_t)(MemInfo.AllocationBase ? MemInfo.AllocationBase : MemInfo.BaseAddress);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uCur > uEnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur -= cbAlloc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uCur &= uAllocGranularityMask;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uCur < uEnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic void supR3HardenedWinHookFailed(const char *pszWhich, uint8_t const *pbPrologue)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "Failed to install %s monitor: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n "
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef RT_ARCH_X86
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync "(It is also possible you are running 32-bit VirtualBox under 64-bit windows.)\n"
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pszWhich,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[0], pbPrologue[1], pbPrologue[2], pbPrologue[3],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[4], pbPrologue[5], pbPrologue[6], pbPrologue[7],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[8], pbPrologue[9], pbPrologue[10], pbPrologue[11],
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbPrologue[12], pbPrologue[13], pbPrologue[14], pbPrologue[15]);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync/**
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * IPRT thread that waits for the parent process to terminate and reacts by
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * exiting the current process.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync *
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @returns VINF_SUCCESS
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param hSelf The current thread. Ignored.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param pvUser The handle of the parent process.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsyncstatic DECLCALLBACK(int) supR3HardenedWinParentWatcherThread(RTTHREAD hSelf, void *pvUser)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync{
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync HANDLE hProcWait = (HANDLE)pvUser;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NOREF(hSelf);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Wait for the parent to terminate.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NTSTATUS rcNt;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync for (;;)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync {
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if ( rcNt == STATUS_WAIT_0
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync || rcNt == STATUS_ABANDONED_WAIT_0)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync break;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if ( rcNt != STATUS_TIMEOUT
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync && rcNt != STATUS_USER_APC
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync && rcNt != STATUS_ALERTED)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync }
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Proxy the termination code of the child, if it exited already.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PROCESS_BASIC_INFORMATION BasicInfo;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if ( !NT_SUCCESS(rcNt2)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync || BasicInfo.ExitStatus == STATUS_PENDING)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync BasicInfo.ExitStatus = RTEXITCODE_FAILURE;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NtClose(hProcWait);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync SUP_DPRINTF(("supR3HardenedWinParentWatcherThread: Quitting: ExitCode=%#x rcNt=%#x\n", BasicInfo.ExitStatus, rcNt));
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync return VINF_SUCCESS; /* won't be reached. */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync}
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync/**
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Creates the parent watcher thread that will make sure this process exits when
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * the parent does.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync *
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * This is a necessary evil to make VBoxNetDhcp and VBoxNetNat termination from
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Main work without too much new magic. It also makes Ctrl-C or similar work
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * in on the hardened processes in the windows console.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync *
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * @param hVBoxRT The VBoxRT.dll handle. We use RTThreadCreate to
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * spawn the thread to avoid duplicating thread
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * creation and thread naming code from IPRT.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsyncDECLHIDDEN(void) supR3HardenedWinCreateParentWatcherThread(HMODULE hVBoxRT)
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync{
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Resolve runtime methods that we need.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PFNRTTHREADCREATE pfnRTThreadCreate = (PFNRTTHREADCREATE)GetProcAddress(hVBoxRT, "RTThreadCreate");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync SUPR3HARDENED_ASSERT(pfnRTThreadCreate != NULL);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Find the parent process ID.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync PROCESS_BASIC_INFORMATION BasicInfo;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync NTSTATUS rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if (!NT_SUCCESS(rcNt))
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: NtQueryInformationProcess failed: %#x\n", rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Open the parent process for waiting and exitcode query.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync OBJECT_ATTRIBUTES ObjAttr;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync CLIENT_ID ClientId;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync ClientId.UniqueProcess = (HANDLE)BasicInfo.InheritedFromUniqueProcessId;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync ClientId.UniqueThread = NULL;
0d73750f953d8569054777eab62f40ad88a66d88vboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync HANDLE hParent;
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync rcNt = NtOpenProcess(&hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if (!NT_SUCCESS(rcNt))
0d73750f953d8569054777eab62f40ad88a66d88vboxsync supR3HardenedFatalMsg("supR3HardenedWinCreateParentWatcherThread", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync "NtOpenProcess(%p.0) failed: %#x\n", ClientId.UniqueProcess, rcNt);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync /*
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync * Create the thread that should do the waiting.
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync */
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync int rc = pfnRTThreadCreate(NULL, supR3HardenedWinParentWatcherThread, hParent, _64K /* stack */,
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ParentWatcher");
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync if (RT_FAILURE(rc))
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync supR3HardenedFatal("supR3HardenedWinCreateParentWatcherThread: RTThreadCreate failed: %Rrc\n", rc);
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync}
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
2fce40121ae472df2fd959fbe19775ed43304a0bvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Install hooks for intercepting calls dealing with mapping shared libraries
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * into the process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This allows us to prevent undesirable shared libraries from being loaded.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @remarks We assume we're alone in this process, so no seralizing trickery is
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * necessary when installing the patch.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @remarks We would normally just copy the prologue sequence somewhere and add
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * a jump back at the end of it. But because we wish to avoid
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * allocating executable memory, we need to have preprepared assembly
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * "copies". This makes the non-system call patching a little tedious
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and inflexible.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supR3HardenedWinInstallHooks(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync NTSTATUS rcNt;
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Install a anti debugging hack before we continue. This prevents most
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * notifications from ending up in the debugger. (Also applied to the
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * child process when respawning.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync /*
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync * Disable hard error popups so we can quietly refuse images to be loaded.
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync */
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync ULONG fHardErr = 0;
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr), NULL);
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync if (!NT_SUCCESS(rcNt))
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync "NtQueryInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync if (fHardErr & PROCESS_HARDERR_CRITICAL_ERROR)
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync {
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync fHardErr &= ~PROCESS_HARDERR_CRITICAL_ERROR;
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync rcNt = NtSetInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &fHardErr, sizeof(fHardErr));
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync if (!NT_SUCCESS(rcNt))
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync "NtSetInformationProcess/ProcessDefaultHardErrorMode failed: %#x\n", rcNt);
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync }
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Locate the routines first so we can allocate memory that's near enough.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HMODULE hmodNtDll = GetModuleHandleW(L"NTDLL");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(hmodNtDll != NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FARPROC pfnNtCreateSection = GetProcAddress(hmodNtDll, "NtCreateSection");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(pfnNtCreateSection != NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync FARPROC pfnLdrLoadDll = GetProcAddress(hmodNtDll, "LdrLoadDll");
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT(pfnLdrLoadDll != NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * For 64-bit hosts we need some memory within a +/-2GB range of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * actual function to be able to patch it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uintptr_t uStart = RT_MAX((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync size_t cbMem = _4K;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync void *pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart - _2G + PAGE_SIZE, -1, cbMem);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pvMem)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uintptr_t uStart = RT_MIN((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart + _2G - PAGE_SIZE, 1, cbMem);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pvMem)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Failed to allocate memory within the +/-2GB range from NTDLL.\n");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uintptr_t *puJmpTab = (uintptr_t *)pvMem;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook #1 - NtCreateSection.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Purpose: Validate everything that can be mapped into the process before
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * it's mapped and we still have a file handle to work with.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 64-bit hosts.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNRT pfnCallReal = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t offJmpBack = UINT8_MAX;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Pattern #1: XP64/W2K3-64 thru Windows 8.1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000> u ntdll!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1750 4c8bd1 mov r10,rcx
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1753 b847000000 mov eax,47h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f1758 0f05 syscall
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f175a c3 ret
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 00000000`779f175b 0f1f440000 nop dword ptr [rax+rax]
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync The variant is the value loaded into eax: W2K3=??, Vista=47h?, W7=47h, W80=48h, W81=49h */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pbNtCreateSection[ 0] == 0x4c /* mov r10, rcx */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 1] == 0x8b
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 2] == 0xd1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 3] == 0xb8 /* mov eax, 000000xxh */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 5] == 0x00
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 6] == 0x00
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 7] == 0x00
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 8] == 0x0f /* syscall */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 9] == 0x05
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[10] == 0xc3 /* ret */
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync
4f2b002896072b0b5a7cb566341c8bac5e69392bvboxsync/* b8 22 35 ed 0 48 63 c0 ff e0 c3 f 1f 44 0 0 - necros2 - agnitum firewall? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync offJmpBack = 8; /* the 3rd instruction (syscall). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch (pbNtCreateSection[4])
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-amd64-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# undef SYSCALL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pfnCallReal)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DWORD dwOldProt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READWRITE, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbNtCreateSection[0] = 0xff;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbNtCreateSection[1] = 0x25;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READ, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync puJmpTab++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 32-bit hosts.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNRT pfnCallReal = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t offJmpBack = UINT8_MAX;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Pattern #1: XP thru Windows 7
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync kd> u ntdll!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d160 b832000000 mov eax,32h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d165 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16a ff12 call dword ptr [edx]
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16c c21c00 ret 1Ch
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 7c90d16f 90 nop
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync The variable bit is the value loaded into eax: XP=32h, W2K3=34h, Vista=4bh, W7=54h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Pattern #2: Windows 8.1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0:000:x86> u ntdll_6a0f0000!NtCreateSection
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ntdll_6a0f0000!NtCreateSection:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eabc b854010000 mov eax,154h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac1 e803000000 call ntdll_6a0f0000!NtCreateSection+0xd (6a15eac9)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac6 c21c00 ret 1Ch
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eac9 8bd4 mov edx,esp
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eacb 0f34 sysenter
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 6a15eacd c3 ret
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync The variable bit is the value loaded into eax: W81=154h
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Note! One nice thing here is that we can share code pattern #1. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pbNtCreateSection[ 0] == 0xb8 /* mov eax, 000000xxh*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 2] <= 0x02
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 3] == 0x00
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 4] == 0x00
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync && ( ( pbNtCreateSection[ 5] == 0xba /* mov edx, offset SharedUserData!SystemCallStub */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 6] == 0x00
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 7] == 0x03
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 8] == 0xfe
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[ 9] == 0x7f
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[10] == 0xff /* call [edx] */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[11] == 0x12
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[12] == 0xc2 /* ret 1ch */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[13] == 0x1c
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[14] == 0x00)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || ( pbNtCreateSection[ 5] == 0xe8 /* call [$+3] */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && RT_ABS(*(int32_t *)&pbNtCreateSection[6]) < 0x10
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[10] == 0xc2 /* ret 1ch */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[11] == 0x1c
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pbNtCreateSection[12] == 0x00 )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync offJmpBack = 5; /* the 2nd instruction. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch (*(uint32_t const *)&pbNtCreateSection[1])
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "NtCreateSection-template-x86-syscall-type-1.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# undef SYSCALL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!pfnCallReal)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DWORD dwOldProt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READWRITE, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbNtCreateSection[0] = 0xe9;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync - (uintptr_t)&pbNtCreateSection[1+4];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READ, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook #2 - LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Purpose: (a) Enforce LdrLoadDll search path constraints, and (b) pre-validate
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * DLLs so we can avoid calling WinVerifyTrust from the first hook,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * and thus avoiding messing up the loader data on some installations.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * This differs from the above function in that is no a system call and
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * we're at the mercy of the compiler.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t offExecPage = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef RT_ARCH_AMD64
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 64-bit hosts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# if 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Pattern #1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 8.1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000> u ntdll!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd44 488bc4 mov rax,rsp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd47 48895808 mov qword ptr [rax+8],rbx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd4b 48896810 mov qword ptr [rax+10h],rbp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd4f 48897018 mov qword ptr [rax+18h],rsi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd53 48897820 mov qword ptr [rax+20h],rdi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd57 4156 push r14
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd59 4883ec70 sub rsp,70h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`814ccd5d f6059cd2100009 test byte ptr [ntdll!LdrpDebugFlags (00007ffa`815da000)],9
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( pbLdrLoadDll[0] == 0x48 /* mov rax,rsp */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0x8b
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0xc4
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x48 /* mov qword ptr [rax+8],rbx */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0x89
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[5] == 0x58
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[6] == 0x08)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 7; /* the 3rd instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #2:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 8.0:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000> u ntdll_w8_64!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_w8_64!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7c0 48895c2408 mov qword ptr [rsp+8],rbx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7c5 4889742410 mov qword ptr [rsp+10h],rsi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7ca 48897c2418 mov qword ptr [rsp+18h],rdi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7cf 55 push rbp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7d0 4156 push r14
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7d2 4157 push r15
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7d4 488bec mov rbp,rsp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7d7 4883ec60 sub rsp,60h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7db 8b05df321000 mov eax,dword ptr [ntdll_w8_64!LdrpDebugFlags (00007ffa`530fdac0)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00007ffa`52ffa7e1 4d8bf1 mov r14,r9
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+8],rbx */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0x89
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0x5c
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x24
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0x08
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[5] == 0x48 /* mov qword ptr [rsp+10h],rsi */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[6] == 0x89
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[7] == 0x74
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[8] == 0x24
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[9] == 0x10)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 10; /* the 3rd instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #3:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 7:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_w7_64!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a20 48895c2410 mov qword ptr [rsp+10h],rbx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a25 48896c2418 mov qword ptr [rsp+18h],rbp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58be4a2a 56 push rsi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+10h],rbx */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0x89
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0x5c
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x24
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0x10)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 5; /* the 2nd instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type3;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #4:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows Vista:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000> u ntdll_vista_64!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_vista_64!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f60 fff3 push rbx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f62 56 push rsi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f63 57 push rdi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f64 4154 push r12
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f66 4155 push r13
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f68 4156 push r14
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f6a 4157 push r15
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f6c 4881ecb0020000 sub rsp,2B0h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f73 488b05367b0e00 mov rax,qword ptr [ntdll_vista_64!_security_cookie (00000000`58cf9ab0)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f7a 4833c4 xor rax,rsp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`58c11f7d 48898424a0020000 mov qword ptr [rsp+2A0h],rax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0xff /* push rbx */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0xf3
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0x56 /* push rsi */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x57 /* push rdi */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0x41 /* push r12 */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[5] == 0x54)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 6; /* the 5th instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type4;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #5:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows XP64:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000> u ntdll!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa580 4c8bdc mov r11,rsp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa583 4881ece8020000 sub rsp,2E8h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa58a 49895bf8 mov qword ptr [r11-8],rbx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa58e 498973f0 mov qword ptr [r11-10h],rsi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa592 49897be8 mov qword ptr [r11-18h],rdi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa596 4d8963e0 mov qword ptr [r11-20h],r12
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa59a 4d896bd8 mov qword ptr [r11-28h],r13
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa59e 4d8973d0 mov qword ptr [r11-30h],r14
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5a2 4d897bc8 mov qword ptr [r11-38h],r15
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5a6 488b051bd10a00 mov rax,qword ptr [ntdll!_security_cookie (00000000`78fa76c8)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5ad 48898424a0020000 mov qword ptr [rsp+2A0h],rax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5b5 4d8bf9 mov r15,r9
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5b8 4c8bf2 mov r14,rdx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5bb 4c8be9 mov r13,rcx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5be 4c89442458 mov qword ptr [rsp+58h],r8
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 00000000`78efa5c3 66c74424680000 mov word ptr [rsp+68h],0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if ( pbLdrLoadDll[0] == 0x4c /* mov r11,rsp */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0x8b
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0xdc
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x48 /* sub rsp,2e8h */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0x81
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[5] == 0xec
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[6] == 0xe8
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[7] == 0x02
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[8] == 0x00
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[9] == 0x00)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 10; /* the 3rd instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type5;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Just use the disassembler to skip 6 bytes or more. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DISSTATE Dis;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cbInstr;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (offJmpBack < 6)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cbInstr = 1;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( RT_FAILURE(rc)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack += cbInstr;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Assemble the code for resuming the call.*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offExecPage += offJmpBack;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
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 offExecPage = RT_ALIGN_32(offExecPage + 4, 8);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint64_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offExecPage = RT_ALIGN_32(offJmpBack + 8, 16);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Patch the function. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Assert(offJmpBack >= 6);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbLdrLoadDll[0] = 0xff;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbLdrLoadDll[1] = 0x25;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&pbLdrLoadDll[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync puJmpTab++;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 32-bit hosts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# if 0
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Pattern #1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 7:
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
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 8 rtm:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000:x86> u ntdll_67150000!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_67150000!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f3f 8bff mov edi,edi
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f41 55 push ebp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f42 8bec mov ebp,esp
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 67189f44 8b0d10eb2467 mov ecx,dword ptr [ntdll_67150000!LdrpDebugFlags (6724eb10)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows 8.1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 6718aae3 83ec14 sub esp,14h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 6718aae6 f6050040246709 test byte ptr [ntdll_w81_32!LdrpDebugFlags (67244000)],9
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Pattern #2:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows XP:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000:x86> u ntdll_xp!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_xp!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569d2 6858020000 push 258h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569d7 68d866f777 push offset ntdll_xp!`string'+0x12c (77f766d8)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569dc e83bb20200 call ntdll_xp!_SEH_prolog (77f81c1c)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569e1 33db xor ebx,ebx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569e3 66895de0 mov word ptr [ebp-20h],bx
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569e7 33c0 xor eax,eax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569e9 8d7de2 lea edi,[ebp-1Eh]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 77f569ec ab stos dword ptr es:[edi]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows Server 2003:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000:x86> u ntdll_w2k3_32!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_w2k3_32!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f63 6840020000 push 240h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f68 68b040837c push offset ntdll_w2k3_32!`string'+0x12c (7c8340b0)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f6d e8a942ffff call ntdll_w2k3_32!_SEH_prolog (7c82821b)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f72 a13077887c mov eax,dword ptr [ntdll_w2k3_32!__security_cookie (7c887730)]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f77 8945e4 mov dword ptr [ebp-1Ch],eax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f7a 8b4508 mov eax,dword ptr [ebp+8]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f7d 8985b0fdffff mov dword ptr [ebp-250h],eax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 7c833f83 8b450c mov eax,dword ptr [ebp+0Ch]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Windows Vista SP0 & SP1:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 0:000:x86> u ntdll_vista_sp0_32!LdrLoadDll
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync ntdll_vista_sp0_32!LdrLoadDll:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb00 6844020000 push 244h
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb05 6838e9b269 push offset ntdll_vista_sp0_32! ?? ::FNODOBFM::`string'+0x39e (69b2e938)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb0a e835420300 call ntdll_vista_sp0_32!_SEH_prolog4_GS (69b42d44)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb0f 8b4508 mov eax,dword ptr [ebp+8]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb12 8985acfdffff mov dword ptr [ebp-254h],eax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb18 8b450c mov eax,dword ptr [ebp+0Ch]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb1b 8985c0fdffff mov dword ptr [ebp-240h],eax
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 69b0eb21 8b4510 mov eax,dword ptr [ebp+10h]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( pbLdrLoadDll[0] == 0x8b /* mov edi, edi - for hot patching */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[1] == 0xff
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[2] == 0x55 /* push ebp */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[3] == 0x8b /* mov ebp,esp */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync && pbLdrLoadDll[4] == 0xec)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 5; /* the 3rd instruction. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else if (pbLdrLoadDll[0] == 0x68 /* push dword XXXXXXXX */)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 5;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_supR3HardenedJmpBack_LdrLoadDll_Type2_PushDword = *(uint32_t const *)&pbLdrLoadDll[1];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnLdrLoadDllJmpBack = (PFNRT)(uintptr_t)(pbLdrLoadDll + offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = pfnCallReal;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Just use the disassembler to skip 6 bytes or more. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync DISSTATE Dis;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync uint32_t cbInstr;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack = 0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync while (offJmpBack < 5)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync cbInstr = 1;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_32BIT, &Dis, &cbInstr);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if ( RT_FAILURE(rc)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) )
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offJmpBack += cbInstr;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Assemble the code for resuming the call.*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offExecPage += offJmpBack;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack]
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync offExecPage = RT_ALIGN_32(offJmpBack + 4, 16);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync# endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /* Patch LdrLoadDLl. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READWRITE, &dwOldProt));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Assert(offJmpBack >= 5);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync pbLdrLoadDll[0] = 0xe9;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *(uint32_t *)&pbLdrLoadDll[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Seal the rwx page.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), g_abSupHardReadWriteExecPage, PAGE_SIZE,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync PAGE_EXECUTE_READ, &dwOldProt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the process integrity.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supR3HardenedWinVerifyProcess(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoInitStatic(&g_ErrInfoStatic);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(),
e352c25b01398e5503235fed02436cb2992f1021vboxsync SUPHARDNTVPKIND_VERIFY_ONLY, NULL /*pcFixes*/, &g_ErrInfoStatic.Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinVerifyProcess", kSupInitOp_Integrity, rc,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Failed to verify process integrity: %s", g_ErrInfoStatic.szMsg);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Gets the SID of the user associated with the process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns @c true if we've got a login SID, @c false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pSidUser Where to return the user SID.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbSidUser The size of the user SID buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pSidLogin Where to return the login SID.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbSidLogin The size of the login SID buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedGetUserAndLogSids(PSID pSidUser, ULONG cbSidUser, PSID pSidLogin, ULONG cbSidLogin)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hToken;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TOKEN_USER UserInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TOKEN_GROUPS Groups;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abPadding[4096];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } uBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbRet = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtQueryInformationToken(hToken, TokenUser, &uBuf, sizeof(uBuf), &cbRet));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidUser, pSidUser, uBuf.UserInfo.User.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fLoginSid = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryInformationToken(hToken, TokenLogonSid, &uBuf, sizeof(uBuf), &cbRet);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (DWORD i = 0; i < uBuf.Groups.GroupCount; i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ((uBuf.Groups.Groups[i].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidLogin, pSidLogin, uBuf.Groups.Groups[i].Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fLoginSid = true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hToken));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return fLoginSid;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Build security attributes for the process or the primary thread (@a fProcess)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Process DACLs can be bypassed using the SeDebugPrivilege (generally available
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * to admins, i.e. normal windows users), or by taking ownership and/or
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * modifying the DACL. However, it restricts
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pSecAttrs Where to return the security attributes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pCleanup Cleanup record.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fProcess Set if it's for the process, clear if it's for
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the primary thread.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic void supR3HardenedInitSecAttrs(PSECURITY_ATTRIBUTES pSecAttrs, PMYSECURITYCLEANUP pCleanup, bool fProcess)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Safe return values.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync suplibHardenedMemSet(pCleanup, 0, sizeof(*pCleanup));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pSecAttrs->nLength = sizeof(*pSecAttrs);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pSecAttrs->bInheritHandle = FALSE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pSecAttrs->lpSecurityDescriptor = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @todo This isn't at all complete, just sketches... */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create an ACL detailing the access of the above groups.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateAcl(&pCleanup->Acl.AclHdr, sizeof(pCleanup->Acl), ACL_REVISION));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
0d73750f953d8569054777eab62f40ad88a66d88vboxsync ULONG fDeny = DELETE | WRITE_DAC | WRITE_OWNER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG fAllow = SYNCHRONIZE | READ_CONTROL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG fAllowLogin = SYNCHRONIZE | READ_CONTROL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fProcess)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny |= PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION | PROCESS_VM_WRITE
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_SET_QUOTA
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllowLogin |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow |= PROCESS_QUERY_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllowLogin |= PROCESS_QUERY_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)) /* Introduced in Windows 8.1. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow |= PROCESS_SET_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny |= THREAD_SUSPEND_RESUME | THREAD_SET_CONTEXT | THREAD_SET_INFORMATION | THREAD_SET_THREAD_TOKEN
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | THREAD_IMPERSONATE | THREAD_DIRECT_IMPERSONATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllowLogin |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow |= THREAD_QUERY_LIMITED_INFORMATION | THREAD_SET_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllowLogin |= THREAD_QUERY_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny |= ~fAllow & (SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Deny everyone access to bad bits. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Everyone.Sid, &SIDAuthWorld, 1));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&pCleanup->Everyone.Sid, 0) = SECURITY_WORLD_RID;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny, &pCleanup->Everyone.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Grant some access to the owner - doesn't work. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthCreator = SECURITY_CREATOR_SID_AUTHORITY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Owner.Sid, &SIDAuthCreator, 1));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&pCleanup->Owner.Sid, 0) = SECURITY_CREATOR_OWNER_RID;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny, &pCleanup->Owner.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow, &pCleanup->Owner.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fHasLoginSid = supR3HardenedGetUserAndLogSids(&pCleanup->User.Sid, sizeof(pCleanup->User),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &pCleanup->Login.Sid, sizeof(pCleanup->Login));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# if 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Grant minimal access to the user. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fDeny, &pCleanup->User.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllow, &pCleanup->User.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# if 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Grant very limited access to the login sid. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fHasLoginSid)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fAllowLogin, &pCleanup->Login.Sid));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create a security descriptor with the above ACL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSECURITY_DESCRIPTOR pSecDesc = (PSECURITY_DESCRIPTOR)suplibHardenedAllocZ(SECURITY_DESCRIPTOR_MIN_LENGTH);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCleanup->pSecDesc = pSecDesc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlSetDaclSecurityDescriptor(pSecDesc, TRUE /*fDaclPresent*/, &pCleanup->Acl.AclHdr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FALSE /*fDaclDefaulted*/));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pSecAttrs->lpSecurityDescriptor = pSecDesc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Predicate function which tests whether @a ch is a argument separator
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * character.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns True/false.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param ch The character to examine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLINLINE(bool) suplibCommandLineIsArgSeparator(int ch)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return ch == ' '
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || ch == '\t'
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || ch == '\n'
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || ch == '\r';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Construct the new command line.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync *
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Since argc/argv are both derived from GetCommandLineW (see
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * suplibHardenedWindowsMain), we skip the argument by argument UTF-8 -> UTF-16
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * conversion and quoting by going to the original source.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The executable name, though, is replaced in case it's not a fullly
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * qualified path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The re-spawn indicator is added immediately after the executable name
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * so that we don't get tripped up missing close quote chars in the last
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * argument.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to a command line string (heap).
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pUniStr Unicode string structure to initialize to the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * command line. Optional.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param iWhich Which respawn we're to check for, 1 being the first
edde275acba04aca58db4172a163741e3abadfbcvboxsync * one, and 2 the second and final.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic PRTUTF16 supR3HardenedWinConstructCmdLine(PUNICODE_STRING pString, int iWhich)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the command line and skip the executable name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PCRTUTF16 pawcArgs = pCmdLineStr->Buffer;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync uint32_t cwcArgs = pCmdLineStr->Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Skip leading space (shouldn't be any, but whatever). */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs) )
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--, pawcArgs++;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT(cwcArgs > 0 && *pawcArgs != '\0');
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Walk to the end of it. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int fQuoted = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (*pawcArgs == '"')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fQuoted = !fQuoted;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--; pawcArgs++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync else if (*pawcArgs != '\\' || (pawcArgs[1] != '\\' && pawcArgs[1] != '"'))
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--, pawcArgs++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cSlashes = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cSlashes++;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync pawcArgs++;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync while (cwcArgs > 0 && *pawcArgs == '\\');
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (cwcArgs > 0 && *pawcArgs == '"' && (cSlashes & 1))
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--, pawcArgs++; /* odd number of slashes == escaped quote */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync } while (cwcArgs > 0 && (fQuoted || !suplibCommandLineIsArgSeparator(*pawcArgs)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Skip trailing spaces. */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync while (cwcArgs > 0 && suplibCommandLineIsArgSeparator(*pawcArgs))
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync cwcArgs--, pawcArgs++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Allocate a new buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync AssertCompile(sizeof(SUPR3_RESPAWN_1_ARG0) == sizeof(SUPR3_RESPAWN_2_ARG0));
edde275acba04aca58db4172a163741e3abadfbcvboxsync size_t cwcCmdLine = (sizeof(SUPR3_RESPAWN_1_ARG0) - 1) / sizeof(SUPR3_RESPAWN_1_ARG0[0]) /* Respawn exe name. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync + !!cwcArgs + cwcArgs; /* if arguments present, add space + arguments. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (cwcCmdLine * sizeof(WCHAR) >= 0xfff0)
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedFatalMsg("supR3HardenedWinConstructCmdLine", kSupInitOp_Misc, VERR_OUT_OF_RANGE,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Command line is too long (%u chars)!", cwcCmdLine);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwszCmdLine = (PRTUTF16)HeapAlloc(GetProcessHeap(), 0 /* dwFlags*/, (cwcCmdLine + 1) * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(pwszCmdLine != NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct the new command line.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwszDst = pwszCmdLine;
edde275acba04aca58db4172a163741e3abadfbcvboxsync for (const char *pszSrc = iWhich == 1 ? SUPR3_RESPAWN_1_ARG0 : SUPR3_RESPAWN_2_ARG0; *pszSrc; pszSrc++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pwszDst++ = *pszSrc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwcArgs)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pwszDst++ = ' ';
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync suplibHardenedMemCopy(pwszDst, pawcArgs, cwcArgs * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszDst += cwcArgs;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pwszDst = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(pwszDst - pwszCmdLine == cwcCmdLine);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (pString)
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync pString->Buffer = pwszCmdLine;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pString->Length = (USHORT)(cwcCmdLine * sizeof(WCHAR));
edde275acba04aca58db4172a163741e3abadfbcvboxsync pString->MaximumLength = pString->Length + sizeof(WCHAR);
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pwszCmdLine;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync/**
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync * Check if the zero terminated NT unicode string is the path to the given
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync * system32 DLL.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync *
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync * @returns true if it is, false if not.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync * @param pUniStr The zero terminated NT unicode string path.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync * @param pszName The name of the system32 DLL.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync */
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsyncstatic bool supR3HardNtIsNamedSystem32Dll(PUNICODE_STRING pUniStr, const char *pszName)
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync{
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync if (pUniStr->Length > g_System32NtPath.UniStr.Length)
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync {
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync if (memcmp(pUniStr->Buffer, g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length) == 0)
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync {
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync if (pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR)] == '\\')
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync {
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync if (RTUtf16ICmpAscii(&pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR) + 1], pszName) == 0)
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync return true;
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync }
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync }
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync }
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync return false;
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync}
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Common code used for child and parent to make new threads exit immediately.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * This patches the LdrInitializeThunk code to call NtTerminateThread with
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * STATUS_SUCCESS instead of doing the NTDLL initialization.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @returns VBox status code.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param hProcess The process to do this to.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * override.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pvNtTerminateThread The address of the NtTerminateThread function in
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * the NTDLL instance we're patching. (Must be +/-
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * 2GB from the thunk code.)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pabBackup Where to back up the original instruction bytes
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * at pvLdrInitThunk.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pErrInfo Where to return extended error information.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Optional.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncstatic int supR3HardNtDisableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, void *pvNtTerminateThread,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync uint8_t *pabBackup, size_t cbBackup, PRTERRINFO pErrInfo)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync{
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUP_DPRINTF(("supR3HardNtDisableThreadCreation: pvLdrInitThunk=%p pvNtTerminateThread=%p\n", pvLdrInitThunk, pvNtTerminateThread));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUPR3HARDENED_ASSERT(cbBackup == 16);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUPR3HARDENED_ASSERT(RT_ABS((intptr_t)pvLdrInitThunk - (intptr_t)pvNtTerminateThread) < 16*_1M);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Back up the thunk code.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SIZE_T cbIgnored;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NTSTATUS rcNt = NtReadVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreation: NtReadVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Cook up replacement code that calls NtTerminateThread.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync uint8_t abReplacement[16];
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync memcpy(abReplacement, pabBackup, sizeof(abReplacement));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync#ifdef RT_ARCH_AMD64
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[0] = 0x31; /* xor ecx, ecx */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[1] = 0xc9;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[2] = 0x31; /* xor edx, edx */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[3] = 0xd2;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[9] = 0xcc; /* int3 */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync#elif defined(RT_ARCH_X86)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[0] = 0x6a; /* push 0 */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[1] = 0x00;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[2] = 0x6a; /* push 0 */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[3] = 0x00;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abReplacement[9] = 0xcc; /* int3 */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync#else
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync# error "Unsupported arch."
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync#endif
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Install the replacment code.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync PVOID pvProt = pvLdrInitThunk;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SIZE_T cbProt = cbBackup;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync ULONG fOldProt = 0;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, abReplacement, sizeof(abReplacement), &cbIgnored);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreationEx: NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync pvProt = pvLdrInitThunk;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync cbProt = cbBackup;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk/2 failed: %#x", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return VINF_SUCCESS;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync}
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Undo the effects of supR3HardNtDisableThreadCreationEx.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @returns VBox status code.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param hProcess The process to do this to.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * override.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pabBackup Where to back up the original instruction bytes
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * at pvLdrInitThunk.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pErrInfo Where to return extended error information.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Optional.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncstatic int supR3HardNtEnableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, uint8_t const *pabBackup, size_t cbBackup,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync PRTERRINFO pErrInfo)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync{
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUP_DPRINTF(("supR3HardNtEnableThreadCreation:\n"));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUPR3HARDENED_ASSERT(cbBackup == 16);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync PVOID pvProt = pvLdrInitThunk;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SIZE_T cbProt = cbBackup;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync ULONG fOldProt = 0;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SIZE_T cbIgnored;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtEnableThreadCreation: NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync pvProt = pvLdrInitThunk;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync cbProt = cbBackup;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (!NT_SUCCESS(rcNt))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync "supR3HardNtEnableThreadCreation: NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return VINF_SUCCESS;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync}
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Disable thread creation for the current process.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @remarks Doesn't really disables it, just makes the threads exit immediately
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * without executing any real code.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncstatic void supR3HardenedWinDisableThreadCreation(void)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync{
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /* Cannot use the imported NtTerminateThread as it's pointing to our own
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync syscall assembly code. */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync FARPROC pfnNtTerminateThread = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtTerminateThread");
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync SUPR3HARDENED_ASSERT(pfnNtTerminateThread);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync int rc = supR3HardNtDisableThreadCreationEx(NtCurrentProcess(),
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync (void *)(uintptr_t)&LdrInitializeThunk,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync (void *)(uintptr_t)pfnNtTerminateThread,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NULL /* pErrInfo*/);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync g_fSupInitThunkSelfPatched = RT_SUCCESS(rc);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync}
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Undoes the effects of supR3HardenedWinDisableThreadCreation.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsyncDECLHIDDEN(void) supR3HardenedWinEnableThreadCreation(void)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync{
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (g_fSupInitThunkSelfPatched)
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync {
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync int rc = supR3HardNtEnableThreadCreationEx(NtCurrentProcess(),
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync (void *)(uintptr_t)&LdrInitializeThunk,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync RTErrInfoInitStatic(&g_ErrInfoStatic));
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (RT_FAILURE(rc))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync g_fSupInitThunkSelfPatched = false;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync }
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync}
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync/*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Child-Process Purification - release it from dubious influences.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * AV software and other things injecting themselves into the embryonic
edde275acba04aca58db4172a163741e3abadfbcvboxsync * and budding process to intercept API calls and what not. Unfortunately
edde275acba04aca58db4172a163741e3abadfbcvboxsync * this is also the behavior of viruses, malware and other unfriendly
edde275acba04aca58db4172a163741e3abadfbcvboxsync * software, so we won't stand for it. AV software can scan our image
edde275acba04aca58db4172a163741e3abadfbcvboxsync * as they are loaded via kernel hooks, that's sufficient. No need for
edde275acba04aca58db4172a163741e3abadfbcvboxsync * matching half of NTDLL or messing with the import table of the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * process executable.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsynctypedef struct SUPR3HARDNTPUCH
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** Process handle. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hProcess;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** Primary thread handle. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hThread;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** Error buffer. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PRTERRINFO pErrInfo;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /** The address of NTDLL in the child. */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uintptr_t uNtDllAddr;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /** The address of NTDLL in this process. */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uintptr_t uNtDllParentAddr;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** The basic process info. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PROCESS_BASIC_INFORMATION BasicInfo;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** The probable size of the PEB. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync size_t cbPeb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** The pristine process environment block. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PEB Peb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync} SUPR3HARDNTPUCH;
edde275acba04aca58db4172a163741e3abadfbcvboxsynctypedef SUPR3HARDNTPUCH *PSUPR3HARDNTPUCH;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardNtPuChScrewUpPebForInitialImageEvents(PSUPR3HARDNTPUCH pThis)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Not sure if any of the cracker software uses the PEB at this point, but
edde275acba04aca58db4172a163741e3abadfbcvboxsync * just in case they do make some of the PEB fields a little less useful.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PEB Peb = pThis->Peb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /* Make ImageBaseAddress useless. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress ^ UINT32_C(0x5f139000));
edde275acba04aca58db4172a163741e3abadfbcvboxsync#ifdef RT_ARCH_AMD64
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress | UINT64_C(0x0313000000000000));
edde275acba04aca58db4172a163741e3abadfbcvboxsync#endif
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Write the PEB.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SIZE_T cbActualMem = pThis->cbPeb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync return VINF_SUCCESS;
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync/**
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * Unmaps a DLL from the child process that was previously mapped by
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * supR3HardNtPuChMapDllIntoChild.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync *
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * @returns Pointer to the DLL mapping on success, NULL on failure.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * @param pThis The child purification instance data.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * @param pvBase The base address of the mapping. Nothing done
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * if NULL.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * @param pszShort The short name (for logging).
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync */
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsyncstatic void supR3HardNtPuChUnmapDllFromChild(PSUPR3HARDNTPUCH pThis, PVOID pvBase, const char *pszShort)
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync{
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync if (pvBase)
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync {
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync NTSTATUS rcNt = NtUnmapViewOfSection(pThis->hProcess, pvBase);
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync if (!NT_SUCCESS(!rcNt))
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtUnmapViewOfSection failed on %s: %#x (%p)\n",
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync pszShort, rcNt, pvBase));
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync }
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync}
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Maps a DLL into the child process.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @returns Pointer to the DLL mapping on success, NULL on failure.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pThis The child purification instance data.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pNtName The path to the DLL.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * @param pszShort The short name (for logging).
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsyncstatic PVOID supR3HardNtPuChMapDllIntoChild(PSUPR3HARDNTPUCH pThis, PUNICODE_STRING pNtName, const char *pszShort)
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync{
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync OBJECT_ATTRIBUTES ObjAttr;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync InitializeObjectAttributes(&ObjAttr, pNtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync GENERIC_READ | GENERIC_EXECUTE,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync &ObjAttr,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync &Ios,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NULL /* Allocation Size*/,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync FILE_ATTRIBUTE_NORMAL,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync FILE_SHARE_READ,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync FILE_OPEN,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync FILE_NON_DIRECTORY_FILE,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NULL /*EaBuffer*/,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync 0 /*EaLength*/);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync if (NT_SUCCESS(rcNt))
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync rcNt = Ios.Status;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync PVOID pvRet = NULL;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync if (NT_SUCCESS(rcNt))
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync {
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync HANDLE hSection = RTNT_INVALID_HANDLE_VALUE;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync rcNt = NtCreateSection(&hSection,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SECTION_MAP_EXECUTE | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NULL /* pObjAttr*/, NULL /*pMaxSize*/,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync PAGE_EXECUTE, SEC_IMAGE, hFile);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync if (NT_SUCCESS(rcNt))
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync {
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SIZE_T cbView = 0;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync rcNt = NtMapViewOfSection(hSection, pThis->hProcess, &pvRet, 0 /*ZeroBits*/, 0 /*CommitSize*/,
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NULL /*pOffSect*/, &cbView, ViewShare, 0 /*AllocationType*/, PAGE_READWRITE);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync if (NT_SUCCESS(rcNt))
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: %s mapped at %p LB %#x\n", pszShort, pvRet, cbView));
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync else
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync {
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtMapViewOfSection failed on %s: %#x\n", pszShort, rcNt));
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync pvRet = NULL;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync }
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NtClose(hSection);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync }
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync else
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: NtCreateSection failed on %s: %#x\n", pszShort, rcNt));
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync NtClose(hFile);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync }
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync else
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Error opening %s: %#x\n", pszShort, rcNt));
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync return pvRet;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync}
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync/**
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Trigger the initial image events without actually initializing the process.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * This is a trick to force sysplant.sys to call its hand by tripping the image
edde275acba04aca58db4172a163741e3abadfbcvboxsync * loaded event for the main executable and ntdll images. This will happen when
edde275acba04aca58db4172a163741e3abadfbcvboxsync * the first thread in a process starts executing in PspUserThreadStartup. We
edde275acba04aca58db4172a163741e3abadfbcvboxsync * create a second thread that quits immediately by means of temporarily
edde275acba04aca58db4172a163741e3abadfbcvboxsync * replacing ntdll!LdrInitializeThunk by a NtTerminateThread call.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * (LdrInitializeThunk is called by way of an APC queued the thread is created,
edde275acba04aca58db4172a163741e3abadfbcvboxsync * thus NtSetContextThread is of no use.)
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns VBox status code.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pThis The child cleanup
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pErrInfo For extended error information.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardNtPuChTriggerInitialImageEvents(PSUPR3HARDNTPUCH pThis)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync /*
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync * Use the on-disk image for the ntdll entrypoints here.
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync */
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync PSUPHNTLDRCACHEENTRY pLdrEntry;
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync if (RT_FAILURE(rc))
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "supHardNtLdrCacheOpen failed on NTDLL: %Rrc", rc);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync RTLDRADDR uLdrInitThunk;
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, pThis->uNtDllAddr, UINT32_MAX,
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync "LdrInitializeThunk", &uLdrInitThunk);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync if (RT_FAILURE(rc))
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk;
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync RTLDRADDR uNtTerminateThread;
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pLdrEntry->pbBits, pThis->uNtDllAddr, UINT32_MAX,
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync "NtTerminateThread", &uNtTerminateThread);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync if (RT_FAILURE(rc))
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync return RTErrInfoSetF(pThis->pErrInfo, rc, "Error locating NtTerminateThread in NTDLL: %Rrc", rc);
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: uLdrInitThunk=%p uNtTerminateThread=%p\n",
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync (uintptr_t)uLdrInitThunk, (uintptr_t)uNtTerminateThread));
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Patch the child's LdrInitializeThunk to exit the thread immediately.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync uint8_t abBackup[16];
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rc = supR3HardNtDisableThreadCreationEx(pThis->hProcess, pvLdrInitThunk, (void *)(uintptr_t)uNtTerminateThread,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync abBackup, sizeof(abBackup), pThis->pErrInfo);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (RT_FAILURE(rc))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return rc;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync /*
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * To further muddle the waters, we map the executable image and ntdll.dll
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * a 2nd time into the process before we actually start executing the thread
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * and trigger the genuine image load events.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync */
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync PVOID pvExe2 = supR3HardNtPuChMapDllIntoChild(pThis, &g_SupLibHardenedExeNtPath.UniStr, "executable[2nd]");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync UNICODE_STRING NtName1 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\ntdll.dll");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync PVOID pvNtDll2 = supR3HardNtPuChMapDllIntoChild(pThis, &NtName1, "ntdll.dll[2nd]");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Create the thread, waiting 10 seconds for it to complete.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync CLIENT_ID Thread2Id;
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hThread2;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NTSTATUS rcNt = RtlCreateUserThread(pThis->hProcess,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NULL /* SecurityAttribs */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync FALSE /* CreateSuspended */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync 0 /* ZeroBits */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync 0 /* MaximumStackSize */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync 0 /* CommittedStackSize */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync (PFNRT)2 /* StartAddress */,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync NULL /*Parameter*/ ,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync &hThread2,
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync &Thread2Id);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync LARGE_INTEGER Timeout;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Timeout.QuadPart = -10 * 10000000; /* 10 seconds */
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtWaitForSingleObject(hThread2, FALSE /* Alertable */, &Timeout);
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtTerminateThread(hThread2, DBG_TERMINATE_THREAD);
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtClose(hThread2);
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync /*
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync * Map kernel32.dll and kernelbase.dll (if applicable) into the process.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync * This triggers should image load events that may set of AV activities
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync * that we'd rather see early than later.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync */
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync UNICODE_STRING NtName2 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\kernel32.dll");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync PVOID pvKernel32 = supR3HardNtPuChMapDllIntoChild(pThis, &NtName2, "kernel32.dll");
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync UNICODE_STRING NtName3 = RTNT_CONSTANT_UNISTR(L"\\SystemRoot\\System32\\KernelBase.dll");
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync PVOID pvKernelBase = g_uNtVerCombined >= SUP_NT_VER_VISTA
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync ? supR3HardNtPuChMapDllIntoChild(pThis, &NtName3, "KernelBase.dll")
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync : NULL;
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync /*
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * Fudge factor for letting kernel threads get a chance to mess up our
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * process asynchronously.
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync */
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync DWORD dwStart = GetTickCount();
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync NtYieldExecution();
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync LARGE_INTEGER Time;
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync NtDelayExecution(FALSE, &Time);
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync NtYieldExecution();
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync NtDelayExecution(FALSE, &Time);
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync NtYieldExecution();
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Startup delay kludge #1: %u ms\n", GetTickCount() - dwStart));
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync /*
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync * Unmap the image we mapped into the guest above.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync */
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvKernel32, "kernel32.dll");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvKernelBase, "KernelBase.dll");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvNtDll2, "ntdll.dll[2nd]");
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync supR3HardNtPuChUnmapDllFromChild(pThis, pvExe2, "executable[2nd]");
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * Restore the original thunk code and protection.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * We do this after waiting as anyone trying to kick of threads in the
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * process will get nothing done as long as our patch is in place.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync rc = supR3HardNtEnableThreadCreationEx(pThis->hProcess, pvLdrInitThunk, abBackup, sizeof(abBackup), pThis->pErrInfo);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync if (RT_FAILURE(rc))
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync return rc;
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync return VINF_SUCCESS;
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync#if 0
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardenedWinScratchChildMemory(HANDLE hProcess, void *pv, size_t cb, const char *pszWhat, PRTERRINFO pErrInfo)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUP_DPRINTF(("supR3HardenedWinScratchChildMemory: %p %#x\n", pv, cb));
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync PVOID pvCopy = pv;
edde275acba04aca58db4172a163741e3abadfbcvboxsync SIZE_T cbCopy = cb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtProtectVirtualMemory/%s (%p LB %#zx) failed: %#x",
edde275acba04aca58db4172a163741e3abadfbcvboxsync pszWhat, pv, cb, rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync return VINF_SUCCESS;
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync#endif
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardNtPuChSanitizePeb(PSUPR3HARDNTPUCH pThis)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Make a copy of the pre-execution PEB.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PEB Peb = pThis->Peb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync#if 0
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * There should not be any activation context, so if there is, we scratch the memory associated with it.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync int rc = 0;
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.pShimData && !((uintptr_t)Peb.pShimData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.pShimData, PAGE_SIZE, "pShimData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.ActivationContextData && !((uintptr_t)Peb.ActivationContextData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ActivationContextData, PAGE_SIZE, "ActivationContextData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.ProcessAssemblyStorageMap && !((uintptr_t)Peb.ProcessAssemblyStorageMap & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "ProcessAssemblyStorageMap", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.SystemDefaultActivationContextData && !((uintptr_t)Peb.SystemDefaultActivationContextData & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.ProcessAssemblyStorageMap, PAGE_SIZE, "SystemDefaultActivationContextData", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc) && Peb.SystemAssemblyStorageMap && !((uintptr_t)Peb.SystemAssemblyStorageMap & PAGE_OFFSET_MASK))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardenedWinScratchChildMemory(hProcess, Peb.SystemAssemblyStorageMap, PAGE_SIZE, "SystemAssemblyStorageMap", pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_FAILURE(rc))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return rc;
edde275acba04aca58db4172a163741e3abadfbcvboxsync#endif
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Clear compatibility and activation related fields.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.AppCompatFlags.QuadPart = 0;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.AppCompatFlagsUser.QuadPart = 0;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.pShimData = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.AppCompatInfo = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync#if 0
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.ActivationContextData = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.ProcessAssemblyStorageMap = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.SystemDefaultActivationContextData = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync Peb.SystemAssemblyStorageMap = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*Peb.Diff0.W6.IsProtectedProcess = 1;*/
edde275acba04aca58db4172a163741e3abadfbcvboxsync#endif
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Write back the PEB.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SIZE_T cbActualMem = pThis->cbPeb;
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync return VINF_SUCCESS;
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsyncstatic void supR3HardNtPuChFindNtdll(PSUPR3HARDNTPUCH pThis)
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync{
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /*
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync * Find NTDLL in this process first and take that as a starting point.
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync pThis->uNtDllParentAddr = (uintptr_t)GetModuleHandleW(L"ntdll.dll");
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync SUPR3HARDENED_ASSERT(pThis->uNtDllParentAddr != 0 && !(pThis->uNtDllParentAddr & PAGE_OFFSET_MASK));
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync pThis->uNtDllAddr = pThis->uNtDllParentAddr;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /*
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync * Scan the virtual memory of the child.
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uintptr_t cbAdvance = 0;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uintptr_t uPtrWhere = 0;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync for (uint32_t i = 0; i < 1024; i++)
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /* Query information. */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync SIZE_T cbActual = 0;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync (void const *)uPtrWhere,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync MemoryBasicInformation,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync &MemInfo,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync sizeof(MemInfo),
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync &cbActual);
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync if (!NT_SUCCESS(rcNt))
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync break;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync if ( MemInfo.Type == SEC_IMAGE
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync || MemInfo.Type == SEC_PROTECTED_IMAGE
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync if (MemInfo.BaseAddress == MemInfo.AllocationBase)
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /* Get the image name. */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync union
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync UNICODE_STRING UniStr;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uint8_t abPadding[4096];
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync } uBuf;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync MemInfo.BaseAddress,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync MemorySectionName,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync &uBuf,
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync sizeof(uBuf) - sizeof(WCHAR),
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync &cbActual);
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync if (NT_SUCCESS(rcNt))
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync if (supR3HardNtIsNamedSystem32Dll(&uBuf.UniStr, "ntdll.dll"))
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync {
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync pThis->uNtDllAddr = (uintptr_t)MemInfo.AllocationBase;
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync SUP_DPRINTF(("supR3HardNtPuChFindNtdll: uNtDllParentAddr=%p uNtDllChildAddr=%p\n",
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync pThis->uNtDllParentAddr, pThis->uNtDllAddr));
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync return;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync }
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync }
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync }
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync }
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync /*
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync * Advance.
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync */
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync cbAdvance = MemInfo.RegionSize;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync if (uPtrWhere + cbAdvance <= uPtrWhere)
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync break;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync uPtrWhere += MemInfo.RegionSize;
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync }
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync#ifdef DEBUG
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync supR3HardenedFatal("%s: ntdll.dll not found in child.", __FUNCTION__);
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync#endif
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync}
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardenedWinPurifyChild(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Initialize the purifier instance data.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDNTPUCH This;
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.hProcess = hProcess;
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.hThread = hThread;
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.pErrInfo = pErrInfo;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync ULONG cbActual = 0;
edde275acba04aca58db4172a163741e3abadfbcvboxsync NTSTATUS rcNt = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
edde275acba04aca58db4172a163741e3abadfbcvboxsync &This.BasicInfo, sizeof(This.BasicInfo), &cbActual);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "NtQueryInformationProcess/ProcessBasicInformation failed: %#x", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (g_uNtVerCombined < SUP_NT_VER_W2K3)
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W51;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (g_uNtVerCombined < SUP_NT_VER_VISTA)
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W52;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (g_uNtVerCombined < SUP_NT_VER_W70)
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W6;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (g_uNtVerCombined < SUP_NT_VER_W80)
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W7;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (g_uNtVerCombined < SUP_NT_VER_W81)
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W80;
edde275acba04aca58db4172a163741e3abadfbcvboxsync else
edde275acba04aca58db4172a163741e3abadfbcvboxsync This.cbPeb = PEB_SIZE_W81;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinPurifyChild: PebBaseAddress=%p cbPeb=%#x\n", This.BasicInfo.PebBaseAddress, This.cbPeb));
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync SIZE_T cbActualMem;
edde275acba04aca58db4172a163741e3abadfbcvboxsync RT_ZERO(This.Peb);
edde275acba04aca58db4172a163741e3abadfbcvboxsync rcNt = NtReadVirtualMemory(hProcess, This.BasicInfo.PebBaseAddress, &This.Peb, sizeof(This.Peb), &cbActualMem);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "NtReadVirtualMemory/Peb failed: %#x", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync supR3HardNtPuChFindNtdll(&This);
f3b077ba3204fcb9c310e3929340db83bc9b77cdvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Do the work, the last bit we tag along with the process verfication code.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync int rc = supR3HardNtPuChScrewUpPebForInitialImageEvents(&This);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardNtPuChTriggerInitialImageEvents(&This);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc))
edde275acba04aca58db4172a163741e3abadfbcvboxsync rc = supR3HardNtPuChSanitizePeb(&This);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_SUCCESS(rc))
e352c25b01398e5503235fed02436cb2992f1021vboxsync rc = supHardenedWinVerifyProcess(hProcess, hThread, SUPHARDNTVPKIND_CHILD_PURIFICATION, NULL /*pcFixes*/, pErrInfo);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync return rc;
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Does the actually respawning.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @returns Never, will call exit or raise fatal error.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param iWhich Which respawn we're to check for, 1 being the
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * first one, and 2 the second and final.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync *
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @todo Split up this function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic int supR3HardenedWinDoReSpawn(int iWhich)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NTSTATUS rcNt;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PPEB pPeb = NtCurrentPeb();
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PRTL_USER_PROCESS_PARAMETERS pParentProcParams = pPeb->ProcessParameters;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Set up security descriptors.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SECURITY_ATTRIBUTES ProcessSecAttrs;
edde275acba04aca58db4172a163741e3abadfbcvboxsync MYSECURITYCLEANUP ProcessSecAttrsCleanup;
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync SECURITY_ATTRIBUTES ThreadSecAttrs;
edde275acba04aca58db4172a163741e3abadfbcvboxsync MYSECURITYCLEANUP ThreadSecAttrsCleanup;
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedInitSecAttrs(&ThreadSecAttrs, &ThreadSecAttrsCleanup, false /*fProcess*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync#if 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Configure the startup info and creation flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync DWORD dwCreationFlags = CREATE_SUSPENDED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync STARTUPINFOEXW SiEx;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync suplibHardenedMemSet(&SiEx, 0, sizeof(SiEx));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SiEx.StartupInfo.cb = sizeof(SiEx.StartupInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SiEx.StartupInfo.cb = sizeof(SiEx);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo experiment with protected process stuff later on. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SiEx.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdInput = pParentProcParams->StandardInput;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdOutput = pParentProcParams->StandardOutput;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SiEx.StartupInfo.hStdError = pParentProcParams->StandardError;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct the command line and launch the process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync PRTUTF16 pwszCmdLine = supR3HardenedWinConstructCmdLine(NULL, iWhich);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync supR3HardenedWinEnableThreadCreation();
edde275acba04aca58db4172a163741e3abadfbcvboxsync PROCESS_INFORMATION ProcessInfoW32;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!CreateProcessW(g_wszSupLibHardenedExePath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszCmdLine,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ProcessSecAttrs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ThreadSecAttrs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TRUE /*fInheritHandles*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync dwCreationFlags,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*pwszzEnvironment*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*pwszCurDir*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &SiEx.StartupInfo,
edde275acba04aca58db4172a163741e3abadfbcvboxsync &ProcessInfoW32))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Error relaunching VirtualBox VM process: %u\n"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Command line: '%ls'",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync GetLastError(), pwszCmdLine);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync supR3HardenedWinDisableThreadCreation();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [kernel32].\n",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync iWhich, ProcessInfoW32.dwProcessId, ProcessInfoW32.dwThreadId));
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hProcess = ProcessInfoW32.hProcess;
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hThread = ProcessInfoW32.hThread;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync#else
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Construct the process parameters.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync UNICODE_STRING W32ImageName;
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.Buffer = g_wszSupLibHardenedExePath; /* Yes the windows name for the process parameters. */
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.Length = (USHORT)RTUtf16Len(g_wszSupLibHardenedExePath) * sizeof(WCHAR);
edde275acba04aca58db4172a163741e3abadfbcvboxsync W32ImageName.MaximumLength = W32ImageName.Length + sizeof(WCHAR);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync UNICODE_STRING CmdLine;
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedWinConstructCmdLine(&CmdLine, iWhich);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync PRTL_USER_PROCESS_PARAMETERS pProcParams = NULL;
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateProcessParameters(&pProcParams,
edde275acba04aca58db4172a163741e3abadfbcvboxsync &W32ImageName,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* DllPath - inherit from this process */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* CurrentDirectory - inherit from this process */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync &CmdLine,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* Environment - inherit from this process */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* WindowsTitle - none */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* DesktopTitle - none. */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* ShellInfo - none. */,
edde275acba04aca58db4172a163741e3abadfbcvboxsync NULL /* RuntimeInfo - none (byte array for MSVCRT file info) */)
edde275acba04aca58db4172a163741e3abadfbcvboxsync );
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /** @todo this doesn't work. :-( */
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->ConsoleHandle = pParentProcParams->ConsoleHandle;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->ConsoleFlags = pParentProcParams->ConsoleFlags;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardInput = pParentProcParams->StandardInput;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardOutput = pParentProcParams->StandardOutput;
edde275acba04aca58db4172a163741e3abadfbcvboxsync pProcParams->StandardError = pParentProcParams->StandardError;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync RTL_USER_PROCESS_INFORMATION ProcessInfoNt = { sizeof(ProcessInfoNt) };
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = RtlCreateUserProcess(&g_SupLibHardenedExeNtPath.UniStr,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync OBJ_INHERIT | OBJ_CASE_INSENSITIVE /*Attributes*/,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync pProcParams,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NULL, //&ProcessSecAttrs,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NULL, //&ThreadSecAttrs,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NtCurrentProcess() /* ParentProcess */,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync FALSE /*fInheritHandles*/,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NULL /* DebugPort */,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NULL /* ExceptionPort */,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync &ProcessInfoNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Error relaunching VirtualBox VM process: %#x\n"
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Command line: '%ls'",
edde275acba04aca58db4172a163741e3abadfbcvboxsync rcNt, CmdLine.Buffer);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [ntdll].\n",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync iWhich, ProcessInfo.ClientId.UniqueProcess, ProcessInfo.ClientId.UniqueThread));
edde275acba04aca58db4172a163741e3abadfbcvboxsync RtlDestroyProcessParameters(pProcParams);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hProcess = ProcessInfoNt.ProcessHandle;
edde275acba04aca58db4172a163741e3abadfbcvboxsync HANDLE hThread = ProcessInfoNt.ThreadHandle;
edde275acba04aca58db4172a163741e3abadfbcvboxsync#endif
edde275acba04aca58db4172a163741e3abadfbcvboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Apply anti debugger notification trick to the thread. (Also done in
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * supR3HardenedWinInstallHooks.)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (!NT_SUCCESS(rcNt))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync supR3HardenedError(rcNt, true /*fFatal*/, "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Clean up the process.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync int rc = supR3HardenedWinPurifyChild(hProcess, hThread, RTErrInfoInitStatic(&g_ErrInfoStatic));
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (RT_FAILURE(rc))
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Start the process execution.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync ULONG cSuspendCount = 0;
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtResumeThread(hThread, &cSuspendCount));
edde275acba04aca58db4172a163741e3abadfbcvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Close the unrestricted access handles. Since we need to wait on the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * child process, we'll reopen the process with limited access before doing
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * away with the process handle returned by CreateProcess.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hThread));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync PROCESS_BASIC_INFORMATION BasicInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hProcWait;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync ULONG fRights = SYNCHRONIZE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync fRights |= PROCESS_QUERY_LIMITED_INFORMATION;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync fRights |= PROCESS_QUERY_INFORMATION;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NtCurrentProcess(), &hProcWait,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync fRights, 0 /*HandleAttributes*/, 0);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (rcNt == STATUS_ACCESS_DENIED)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NtCurrentProcess(), &hProcWait,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SYNCHRONIZE, 0 /*HandleAttributes*/, 0);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync /* Failure is unacceptable, kill the process. */
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NtTerminateProcess(hProcess, RTEXITCODE_FAILURE);
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync supR3HardenedError(rcNt, false /*fFatal*/, "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!fExitOk)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NTSTATUS rcNtWait;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD dwStartTick = GetTickCount();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync LARGE_INTEGER Timeout;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync Timeout.QuadPart = -20000000; /* 2 second */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while ( !fExitOk
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync && ( rcNtWait == STATUS_TIMEOUT
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNtWait == STATUS_USER_APC
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNtWait == STATUS_ALERTED)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && GetTickCount() - dwStartTick < 60 * 1000);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fExitOk)
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync supR3HardenedError(rcNt, false /*fFatal*/,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync "NtDuplicateObject failed and we failed to kill child: rcNt=%u rcNtWait=%u hProcess=%p\n",
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt, rcNtWait, hProcess);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, VERR_INVALID_NAME,
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hProcess));
edde275acba04aca58db4172a163741e3abadfbcvboxsync hProcess = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync /*
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync * Ditch the loader cache so we don't sit on too much memory while waiting.
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync */
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync supR3HardenedWinFlushLoaderCache();
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync HeapCompact(GetProcessHeap(), 0 /*dwFlags*/);
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * If this is the middle process, wait for both parent and child to quit.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync HANDLE hParent = NULL;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (iWhich > 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (NT_SUCCESS(rcNt))
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync OBJECT_ATTRIBUTES ObjAttr;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync CLIENT_ID ClientId;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync ClientId.UniqueProcess = (HANDLE)BasicInfo.InheritedFromUniqueProcessId;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync ClientId.UniqueThread = NULL;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtOpenProcess(&hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync#ifdef DEBUG
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(rcNt);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if (hParent != NULL)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync for (;;)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync HANDLE ahHandles[2] = { hProcWait, hParent };
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtWaitForMultipleObjects(2, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*pTimeout*/);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if ( rcNt == STATUS_WAIT_0
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNt == STATUS_WAIT_0 + 1
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNt == STATUS_ABANDONED_WAIT_0
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNt == STATUS_ABANDONED_WAIT_0 + 1)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync break;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if ( rcNt != STATUS_TIMEOUT
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync && rcNt != STATUS_USER_APC
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync && rcNt != STATUS_ALERTED)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync supR3HardenedFatal("NtWaitForMultipleObjects returned %#x\n", rcNt);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync NtClose(hParent);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync else
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync /*
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Wait for the process to terminate.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync for (;;)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync {
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync rcNt = NtWaitForSingleObject(hProcWait, TRUE /*Alertable*/, NULL /*pTimeout*/);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if ( rcNt == STATUS_WAIT_0
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || rcNt == STATUS_ABANDONED_WAIT_0)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync break;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync if ( rcNt != STATUS_TIMEOUT
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync && rcNt != STATUS_USER_APC
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync && rcNt != STATUS_ALERTED)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync supR3HardenedFatal("NtWaitForSingleObject returned %#x\n", rcNt);
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync }
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync /*
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * Proxy the termination code of the child, if it exited already.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync */
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync NTSTATUS rcNt2 = NtQueryInformationProcess(hProcWait, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync if ( !NT_SUCCESS(rcNt2)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync || BasicInfo.ExitStatus == STATUS_PENDING)
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync BasicInfo.ExitStatus = RTEXITCODE_FAILURE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtClose(hProcWait);
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): Quitting: ExitCode=%#x rcNt=%#x\n", iWhich, BasicInfo.ExitStatus, rcNt));
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync/**
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Checks if the driver exists.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * This checks whether the driver is present in the /Driver object directory.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Drivers being initialized or terminated will have an object there
edde275acba04aca58db4172a163741e3abadfbcvboxsync * before/after their devices nodes are created/deleted.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns true if it exists, false if not.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param pszDriver The driver name.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsyncstatic bool supR3HardenedWinDriverExists(const char *pszDriver)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync{
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /*
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Open the driver object directory.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync */
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync OBJECT_ATTRIBUTES ObjAttr;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync HANDLE hDir;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync#ifdef VBOX_STRICT
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(rcNt);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync#endif
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (!NT_SUCCESS(rcNt))
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync return true;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /*
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Enumerate it, looking for the driver.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync bool fFound = true;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync ULONG uObjDirCtx = 0;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync do
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync {
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync uint32_t abBuffer[_64K + _1K];
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync ULONG cbActual;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync rcNt = NtQueryDirectoryObject(hDir,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync abBuffer,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FALSE /*ReturnSingleEntry */,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FALSE /*RestartScan*/,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync &uObjDirCtx,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync &cbActual);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync while (pObjDir->Name.Length != 0)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync {
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = '\0';
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if ( pObjDir->Name.Length > 1
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync && RTUtf16ICmpAscii(pObjDir->Name.Buffer, pszDriver) == 0)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync {
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync fFound = true;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync }
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /* Next directory entry. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync pObjDir++;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync }
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync } while (!fFound);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync /*
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync * Clean up and return.
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NtClose(hDir);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync return fFound;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync}
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Open the stub device before the 2nd respawn.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncstatic void supR3HardenedWinOpenStubDevice(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszName[] = L"\\Device\\VBoxDrvStub";
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync DWORD const uStartTick = GetTickCount();
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NTSTATUS rcNt;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync uint32_t iTry;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync for (iTry = 0;; iTry++)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync {
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync UNICODE_STRING NtName;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NtName.Buffer = (PWSTR)s_wszName;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NtName.Length = sizeof(s_wszName) - sizeof(WCHAR);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NtName.MaximumLength = sizeof(s_wszName);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync OBJECT_ATTRIBUTES ObjAttr;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync rcNt = NtCreateFile(&hFile,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync GENERIC_READ | GENERIC_WRITE,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync &ObjAttr,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync &Ios,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NULL /* Allocation Size*/,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FILE_ATTRIBUTE_NORMAL,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FILE_OPEN,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync FILE_NON_DIRECTORY_FILE,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NULL /*EaBuffer*/,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync 0 /*EaLength*/);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (NT_SUCCESS(rcNt))
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync rcNt = Ios.Status;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
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 (rcNt != STATUS_NO_SUCH_DEVICE)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (iTry > 0 && GetTickCount() - uStartTick > 5000) /* 5 sec, at least two tries */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (!supR3HardenedWinDriverExists("VBoxDrv"))
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync {
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 break;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync }
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync LARGE_INTEGER Time;
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync if (iTry < 8)
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync Time.QuadPart = -1000000 / 100; /* 1ms in 100ns units, relative time. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync else
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync Time.QuadPart = -32000000 / 100; /* 32ms in 100ns units, relative time. */
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync NtDelayExecution(TRUE, &Time);
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync }
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
40839c441cb305d84420565f7ca25403d8177413vboxsync int rc = VERR_OPEN_FAILED;
40839c441cb305d84420565f7ca25403d8177413vboxsync if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
40839c441cb305d84420565f7ca25403d8177413vboxsync rc = SUP_NT_STATUS_TO_VBOX(rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync {
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync const char *pszDefine;
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync switch (rcNt)
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync {
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_NO_SUCH_DEVICE: pszDefine = " STATUS_NO_SUCH_DEVICE"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_OBJECT_NAME_NOT_FOUND: pszDefine = " STATUS_OBJECT_NAME_NOT_FOUND"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_ACCESS_DENIED: pszDefine = " STATUS_ACCESS_DENIED"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync case STATUS_TRUST_FAILURE: pszDefine = " STATUS_TRUST_FAILURE"; break;
485f31dd3495c289f625c9c5b900cf0b95838ed6vboxsync default: pszDefine = ""; break;
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n", s_wszName, rcNt, pszDefine, iTry);
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync }
40839c441cb305d84420565f7ca25403d8177413vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, rc,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync/**
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Called by the main code if supR3HardenedWinIsReSpawnNeeded returns @c true.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @returns Program exit code.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncDECLHIDDEN(int) supR3HardenedWinReSpawn(int iWhich)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Before the 2nd respawn we set up a child protection deal with the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * support driver via /Devices/VBoxDrvStub.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (iWhich == 2)
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedWinOpenStubDevice();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Respawn the process with kernel protection for the new process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync return supR3HardenedWinDoReSpawn(iWhich);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Checks if re-spawning is required, replacing the respawn argument if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if required, false if not. In the latter case, the first
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * argument in the vector is replaced.
edde275acba04aca58db4172a163741e3abadfbcvboxsync * @param iWhich Which respawn we're to check for, 1 being the
edde275acba04aca58db4172a163741e3abadfbcvboxsync * first one, and 2 the second and final.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cArgs The number of arguments.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param papszArgs Pointer to the argument vector.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsyncDECLHIDDEN(bool) supR3HardenedWinIsReSpawnNeeded(int iWhich, int cArgs, char **papszArgs)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(g_cSuplibHardenedWindowsMainCalls == 1);
edde275acba04aca58db4172a163741e3abadfbcvboxsync SUPR3HARDENED_ASSERT(iWhich == 1 || iWhich == 2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cArgs < 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (iWhich > 1)
edde275acba04aca58db4172a163741e3abadfbcvboxsync return true;
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync else if (suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (iWhich < 2)
edde275acba04aca58db4172a163741e3abadfbcvboxsync return false;
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Replace the argument. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync papszArgs[0] = g_szSupLibHardenedExePath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initializes the windows verficiation bits.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags The main flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoInitStatic(&g_ErrInfoStatic);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardenedWinInitImageVerifier(&g_ErrInfoStatic.Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rc,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supHardenedWinInitImageVerifier failed: %s", g_ErrInfoStatic.szMsg);
693b87e00c4a89605b2f8d8ab443414186aeaa06vboxsync
693b87e00c4a89605b2f8d8ab443414186aeaa06vboxsync if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync /*
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * Do a self purification to cure avast's weird NtOpenFile write-thru
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * change in GetBinaryTypeW change in kernel32. Unfortunately, avast
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * uses a system thread to perform the process modifications, which
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * means it's hard to make sure it had the chance to make them...
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync *
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * We have to resort to kludge doing yield and sleep fudging for a
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * number of milliseconds and schedulings before we can hope that avast
e352c25b01398e5503235fed02436cb2992f1021vboxsync * and similar products have done what they need to do. If we do any
e352c25b01398e5503235fed02436cb2992f1021vboxsync * fixes, we wait for a while again and redo it until we're clean.
e352c25b01398e5503235fed02436cb2992f1021vboxsync *
e352c25b01398e5503235fed02436cb2992f1021vboxsync * This is unfortunately kind of fragile.
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync */
e352c25b01398e5503235fed02436cb2992f1021vboxsync uint32_t iLoop = 0;
e352c25b01398e5503235fed02436cb2992f1021vboxsync uint32_t cFixes;
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync do
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync {
e352c25b01398e5503235fed02436cb2992f1021vboxsync uint32_t cSleeps = 0;
e352c25b01398e5503235fed02436cb2992f1021vboxsync DWORD dwStart = GetTickCount();
e352c25b01398e5503235fed02436cb2992f1021vboxsync do
e352c25b01398e5503235fed02436cb2992f1021vboxsync {
e352c25b01398e5503235fed02436cb2992f1021vboxsync NtYieldExecution();
e352c25b01398e5503235fed02436cb2992f1021vboxsync LARGE_INTEGER Time;
e352c25b01398e5503235fed02436cb2992f1021vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
e352c25b01398e5503235fed02436cb2992f1021vboxsync NtDelayExecution(FALSE, &Time);
e352c25b01398e5503235fed02436cb2992f1021vboxsync cSleeps++;
e352c25b01398e5503235fed02436cb2992f1021vboxsync } while ( GetTickCount() - dwStart <= 80
e352c25b01398e5503235fed02436cb2992f1021vboxsync || cSleeps < 8);
e352c25b01398e5503235fed02436cb2992f1021vboxsync SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n",
e352c25b01398e5503235fed02436cb2992f1021vboxsync iLoop, GetTickCount() - dwStart, cSleeps));
e352c25b01398e5503235fed02436cb2992f1021vboxsync
e352c25b01398e5503235fed02436cb2992f1021vboxsync cFixes = 0;
e352c25b01398e5503235fed02436cb2992f1021vboxsync rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION,
e352c25b01398e5503235fed02436cb2992f1021vboxsync &cFixes, NULL /*pErrInfo*/);
e352c25b01398e5503235fed02436cb2992f1021vboxsync } while ( RT_SUCCESS(rc)
e352c25b01398e5503235fed02436cb2992f1021vboxsync && cFixes > 0
e352c25b01398e5503235fed02436cb2992f1021vboxsync && ++iLoop < 8);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync /*
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync * Install the hooks.
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync */
693b87e00c4a89605b2f8d8ab443414186aeaa06vboxsync supR3HardenedWinInstallHooks();
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef VBOX_WITH_VISTA_NO_SP
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Complain about Vista w/o service pack if we're launching a VM.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_uNtVerCombined >= SUP_NT_VER_VISTA
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#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Converts the Windows command line string (UTF-16) to an array of UTF-8
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * arguments suitable for passing to main().
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Pointer to the argument array.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param pawcCmdLine The UTF-16 windows command line to parse.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync * @param cwcCmdLine The length of the command line.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pcArgs Where to return the number of arguments.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsyncstatic char **suplibCommandLineToArgvWStub(PCRTUTF16 pawcCmdLine, size_t cwcCmdLine, int *pcArgs)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the command line string to UTF-8.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync char *pszCmdLine = NULL;
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync SUPR3HARDENED_ASSERT(RT_SUCCESS(RTUtf16ToUtf8Ex(pawcCmdLine, cwcCmdLine, &pszCmdLine, 0, NULL)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Parse the command line, carving argument strings out of it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int cArgs = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int cArgsAllocated = 4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char **papszArgs = (char **)suplibHardenedAllocZ(sizeof(char *) * cArgsAllocated);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *pszSrc = pszCmdLine;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* skip leading blanks. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char ch = *pszSrc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (suplibCommandLineIsArgSeparator(ch))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *++pszSrc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!ch)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Add argument to the vector. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cArgs + 2 >= cArgsAllocated)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cArgsAllocated *= 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync papszArgs = (char **)suplibHardenedReAlloc(papszArgs, sizeof(char *) * cArgsAllocated);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync papszArgs[cArgs++] = pszSrc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync papszArgs[cArgs] = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Unquote and unescape the string. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *pszDst = pszSrc++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fQuoted = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (ch == '"')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fQuoted = !fQuoted;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (ch != '\\' || (*pszSrc != '\\' && *pszSrc != '"'))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszDst++ = ch;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync unsigned cSlashes = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((ch = *pszSrc++) == '\\')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cSlashes++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (ch == '"')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cSlashes >= 2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cSlashes -= 2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszDst++ = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cSlashes)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszDst++ = '"';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fQuoted = !fQuoted;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszSrc--;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cSlashes-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszDst++ = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ch = *pszSrc++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (ch != '\0' && (fQuoted || !suplibCommandLineIsArgSeparator(ch)));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Terminate the argument. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pszDst = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!ch)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pcArgs = cArgs;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return papszArgs;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncextern "C" int main(int argc, char **argv, char **envp);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The executable entry point.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This is normally taken care of by the C runtime library, but we don't want to
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * get involved with anything as complicated like the CRT in this setup. So, we
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * it everything ourselves, including parameter parsing.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncextern "C" void __stdcall suplibHardenedWindowsMain(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync RTEXITCODE rcExit = RTEXITCODE_FAILURE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_cSuplibHardenedWindowsMainCalls++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /*
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Initialize the NTDLL API wrappers. This aims at bypassing patched NTDLL
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * in all the processes leading up the VM process.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync supR3HardenedWinInitImports();
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * After having resolved imports we patch the LdrInitializeThunk code so
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * that it's more difficult to invade our privacy by CreateRemoteThread.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync * We'll re-enable this after opening the driver or temporarily while respawning.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync supR3HardenedWinDisableThreadCreation();
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Init g_uNtVerCombined. (The code is shared with SUPR3.lib and lives in
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * SUPHardenedVerfiyImage-win.cpp.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedWinInitVersion();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync /*
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * Convert the arguments to UTF-8 and open the log file if specified.
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * This must be done as early as possible since the code below may fail.
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync */
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync PUNICODE_STRING pCmdLineStr = &NtCurrentPeb()->ProcessParameters->CommandLine;
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync int cArgs;
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync char **papszArgs = suplibCommandLineToArgvWStub(pCmdLineStr->Buffer, pCmdLineStr->Length / sizeof(WCHAR), &cArgs);
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync supR3HardenedOpenLog(&cArgs, papszArgs);
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the executable name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync DWORD cwcExecName = GetModuleFileNameW(GetModuleHandleW(NULL), g_wszSupLibHardenedExePath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ELEMENTS(g_wszSupLibHardenedExePath));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwcExecName >= RT_ELEMENTS(g_wszSupLibHardenedExePath))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, VERR_BUFFER_OVERFLOW,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "The executable path is too long.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The NT version. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFile = CreateFileW(g_wszSupLibHardenedExePath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromWin32(GetLastError()),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Error opening the executable: %u (%ls).", GetLastError());
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(g_SupLibHardenedExeNtPath);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbIgn;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryObject(hFile, ObjectNameInformation, &g_SupLibHardenedExeNtPath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbIgn);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromNtStatus(rcNt),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtQueryObject -> %#x (on %ls)\n", rcNt, g_wszSupLibHardenedExePath);
edde275acba04aca58db4172a163741e3abadfbcvboxsync NtClose(hFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The NT executable name offset / dir path length. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ( g_offSupLibHardenedExeNtName > 1
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_offSupLibHardenedExeNtName--;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync * Call the C/C++ main function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("Calling main()\n"));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcExit = (RTEXITCODE)main(cArgs, papszArgs, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Exit the process (never return).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("Terminating the normal way: rcExit=%d\n", rcExit));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync suplibHardenedExit(rcExit);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync