SUPR3HardenedMain-win.cpp revision 09af8164395ce22610792b5097e2b6ba3a63ac78
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) \
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("%s: %s -> %#x\n", __FUNCTION__, #a_Expr, RtlGetLastWin32Error()); \
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
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child requests.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsynctypedef enum SUPR3WINCHILDREQ
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Perform child purification and close full access handles (must be zero). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync kSupR3WinChildReq_PurifyChildAndCloseHandles = 0,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Close the events, we're good on our own from here on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync kSupR3WinChildReq_CloseEvents,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Reporting error. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync kSupR3WinChildReq_Error,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** End of valid requests. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync kSupR3WinChildReq_End
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync} SUPR3WINCHILDREQ;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child process parameters.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsynctypedef struct SUPR3WINPROCPARAMS
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync{
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The event semaphore the child will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtChild;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The event semaphore the parent will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtParent;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of the NTDLL. This is only valid during the very early
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * initialization as we abuse for thread creation protection. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uNtDllAddr;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The requested operation (set by the child). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3WINCHILDREQ enmRequest;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** The last status. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int32_t rc;
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync /** The init operation the error relates to if message, kSupInitOp_Invalid if
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * not message. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPINITOP enmWhat;
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync /** Where if message. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync char szWhere[80];
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /** Error message / path name string space. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync char szErrorMsg[4096];
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync} SUPR3WINPROCPARAMS;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Child process data structure for use during child process init setup and
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * purification.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsynctypedef struct SUPR3HARDNTCHILD
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Process handle. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hProcess;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Primary thread handle. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hThread;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Handle to the parent process, if we're the middle (stub) process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The event semaphore the child will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtChild;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The event semaphore the parent will be waiting on. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of NTDLL in the child. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uNtDllAddr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The address of NTDLL in this process. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uNtDllParentAddr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** Which respawn number this is (1 = stub, 2 = VM). */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int iWhich;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The basic process info. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PROCESS_BASIC_INFORMATION BasicInfo;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The probable size of the PEB. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync size_t cbPeb;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The pristine process environment block. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PEB Peb;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /** The child process parameters. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3WINPROCPARAMS ProcParams;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync} SUPR3HARDNTCHILD;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** Pointer to a child process data structure. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsynctypedef SUPR3HARDNTCHILD *PSUPR3HARDNTCHILD;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/** Process parameters. Specified by parent if VM process, see
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * supR3HardenedVmProcessInit. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic SUPR3WINPROCPARAMS g_ProcParams = { NULL, NULL, 0, (SUPR3WINCHILDREQ)0, 0 };
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** Set if supR3HardenedEarlyProcessInit was invoked. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncbool g_fSupEarlyProcessInit = false;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** Set if the stub device has been opened (stub process only). */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncbool g_fSupStubOpened = false;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
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/** 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);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Pointer to the NtCreateSection function in NtDll (for patching purposes). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic uint8_t *g_pbNtCreateSection;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The patched NtCreateSection bytes (for restoring). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic uint8_t g_abNtCreateSectionPatch[16];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Pointer to the bit of assembly code that will perform the original
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * LdrLoadDll operation. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic NTSTATUS (NTAPI * g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Pointer to the LdrLoadDll function in NtDll (for patching purposes). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic uint8_t *g_pbLdrLoadDll;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The patched LdrLoadDll bytes (for restoring). */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic uint8_t g_abLdrLoadDllPatch[16];
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The hash table of verifier cache . */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_apVerifierCache[128];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs WinVerifyTrust to check them. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEENTRY volatile g_pVerifierCacheTodoWvt = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync/** Queue of cached images which needs their imports checked. */
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsyncstatic PVERIFIERCACHEIMPORT volatile g_pVerifierCacheTodoImports = NULL;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync/** The windows path to dir \\SystemRoot\\System32 directory (technically
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * this whatever \KnownDlls\KnownDllPath points to). */
9f997e760f610c92e3a365be21ead6972bc46130vboxsyncSUPSYSROOTDIRBUF g_System32WinPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** Positive if the DLL notification callback has been registered, counts
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * registration attempts as negative. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic int g_cDllNotificationRegistered = 0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/** The registration cookie of the DLL notification callback. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic PVOID g_pvDllNotificationCookie = NULL;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
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
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Mask of adversaries that we've detected (SUPHARDNT_ADVERSARY_XXX). */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsyncstatic uint32_t g_fSupAdversaries = 0;
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** @name SUPHARDNT_ADVERSARY_XXX - Adversaries
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * @{ */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Symantec endpoint protection or similar including SysPlant.sys. */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT RT_BIT_32(0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Symantec Norton 360. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_SYMANTEC_N360 RT_BIT_32(1)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Avast! */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_AVAST RT_BIT_32(2)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** TrendMicro OfficeScan and probably others. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_TRENDMICRO RT_BIT_32(3)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** McAfee. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_MCAFEE RT_BIT_32(4)
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync/** Kaspersky or OEMs of it. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_KASPERSKY RT_BIT_32(5)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Malwarebytes Anti-Malware (MBAM). */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_MBAM RT_BIT_32(6)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** AVG Internet Security. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_AVG RT_BIT_32(7)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Panda Security. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_PANDA RT_BIT_32(8)
100b161379af7255c69e27587cc746e5f76ff050vboxsync/** Microsoft Security Essentials. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define SUPHARDNT_ADVERSARY_MSE RT_BIT_32(9)
a6c871653045073d6ef74d0589de345ae62b607dvboxsync/** Comodo. */
a6c871653045073d6ef74d0589de345ae62b607dvboxsync#define SUPHARDNT_ADVERSARY_COMODO RT_BIT_32(10)
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync/** Check Point's Zone Alarm (may include Kaspersky). */
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync#define SUPHARDNT_ADVERSARY_ZONE_ALARM RT_BIT_32(11)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** Unknown adversary detected while waiting on child. */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync#define SUPHARDNT_ADVERSARY_UNKNOWN RT_BIT_32(31)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/** @} */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
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);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncstatic void supR3HardenedWinRegisterDllNotificationCallback(void);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncstatic void supR3HardenedWinReInstallHooks(bool fFirst);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsyncDECLASM(void) supR3HardenedEarlyProcessInitThunk(void);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
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
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/**
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Our version of GetTickCount.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * @returns Millisecond timestamp.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncstatic uint64_t supR3HardenedWinGetMilliTS(void)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync{
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync PKUSER_SHARED_DATA pUserSharedData = (PKUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync /* use interrupt time */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync LARGE_INTEGER Time;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync do
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync {
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync Time.HighPart = pUserSharedData->InterruptTime.High1Time;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync Time.LowPart = pUserSharedData->InterruptTime.LowPart;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync return (uint64_t)Time.QuadPart / 10000;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync}
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
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)
30f07af559efcbd967e801903746fc21f81ee533vboxsync && RtlGetLastWin32Error() == 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 {
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync wcLeft = wcLeft != '/' ? RT_C_TO_LOWER(wcLeft) : '\\';
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync wcRight = 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 */
30f07af559efcbd967e801903746fc21f81ee533vboxsync PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)RTMemAllocZ(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). */
30f07af559efcbd967e801903746fc21f81ee533vboxsync RTMemFree(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);
30f07af559efcbd967e801903746fc21f81ee533vboxsync PVERIFIERCACHEIMPORT pImport = (PVERIFIERCACHEIMPORT)RTMemAllocZ(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;
100b161379af7255c69e27587cc746e5f76ff050vboxsync NTSTATUS rcNtRedir = 0x22222222;
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
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNtRedir = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &UniStrName,
100b161379af7255c69e27587cc746e5f76ff050vboxsync (PUNICODE_STRING)&s_DefaultSuffix,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &UniStrStatic,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &UniStrDynamic,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &pUniStrResult,
100b161379af7255c69e27587cc746e5f76ff050vboxsync NULL /*pNewFlags*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync NULL /*pcbFilename*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync NULL /*pcbNeeded*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNtRedir))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync 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;
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync /* For accurate logging. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcCopy = RT_MIN(pUniStrResult->Length / sizeof(RTUTF16), RT_ELEMENTS(wszPath) - 1);
100b161379af7255c69e27587cc746e5f76ff050vboxsync memcpy(wszPath, pUniStrResult->Buffer, cwcCopy * sizeof(RTUTF16));
100b161379af7255c69e27587cc746e5f76ff050vboxsync wszPath[cwcCopy] = '\0';
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
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 {
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' -> '%ls' [rcNtRedir=%#x]\n",
100b161379af7255c69e27587cc746e5f76ff050vboxsync pCur->szName, wszPath, rcNtRedir));
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
30f07af559efcbd967e801903746fc21f81ee533vboxsync RTMemFree(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;
efdc3bd872b77b5ec7d19d77504264de24b0582bvboxsync 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)
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust, fFlags);
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 {
30f07af559efcbd967e801903746fc21f81ee533vboxsync DWORD dwSavedLastError = RtlGetLastWin32Error();
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
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(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
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync/**
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * Helper for supR3HardenedMonitor_LdrLoadDll.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync *
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @returns NT status code.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pwszPath The path destination buffer.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param cwcPath The size of the path buffer.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pUniStrResult The result string.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pOrgName The orignal name (for errors).
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync * @param pcwc Where to return the actual length.
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync */
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsyncstatic NTSTATUS supR3HardenedCopyRedirectionResult(WCHAR *pwszPath, size_t cwcPath, PUNICODE_STRING pUniStrResult,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync PUNICODE_STRING pOrgName, UINT *pcwc)
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync{
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UINT cwc;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync *pcwc = cwc = pUniStrResult->Length / sizeof(WCHAR);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync if (pUniStrResult->Buffer == pwszPath)
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pwszPath[cwc] = '\0';
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync else
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync if (cwc > cwcPath - 1)
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync supR3HardenedError(VINF_SUCCESS, false,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync "supR3HardenedMonitor_LdrLoadDll: Name too long: %.*ls -> %.*ls (RtlDosApplyFileIoslationRedirection_Ustr)\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pOrgName->Length / sizeof(WCHAR), pOrgName->Buffer,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pUniStrResult->Length / sizeof(WCHAR), pUniStrResult->Buffer);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync return STATUS_NAME_TOO_LONG;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync }
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync memcpy(&pwszPath[0], pUniStrResult->Buffer, pUniStrResult->Length);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pwszPath[cwc] = '\0';
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync }
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync return STATUS_SUCCESS;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync}
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync
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{
30f07af559efcbd967e801903746fc21f81ee533vboxsync DWORD dwSavedLastError = RtlGetLastWin32Error();
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync NTSTATUS rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Make sure the DLL notification callback is registered. If we could, we
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * would've done this during early process init, but due to lack of heap
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * and uninitialized loader lock, it's not possible that early on.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * The callback protects our NtDll hooks from getting unhooked by
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * "friendly" fire from the AV crowd.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinRegisterDllNotificationCallback();
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
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");
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x (pName=%p)\n", STATUS_INVALID_PARAMETER, pName));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return STATUS_INVALID_PARAMETER;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync /*SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls\n",
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));*/
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
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));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return STATUS_NAME_TOO_LONG;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Absolute path?
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fSkipValidation = false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync WCHAR wszPath[260];
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UNICODE_STRING UniStrStatic = { 0, (USHORT)sizeof(wszPath) - sizeof(WCHAR), wszPath };
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UNICODE_STRING UniStrDynamic = { 0, 0, NULL };
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync PUNICODE_STRING pUniStrResult = NULL;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UNICODE_STRING ResolvedName;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync
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 {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = RtlDosApplyFileIsolationRedirection_Ustr(1 /*fFlags*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pName,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync (PUNICODE_STRING)&s_DefaultSuffix,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync &UniStrStatic,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync &UniStrDynamic,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync &pUniStrResult,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync NULL /*pNewFlags*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync NULL /*pcbFilename*/,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync NULL /*pcbNeeded*/);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync if (NT_SUCCESS(rcNt))
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UINT cwc;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync RtlFreeUnicodeString(&UniStrDynamic);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync if (!NT_SUCCESS(rcNt))
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync return rcNt;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync }
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.Buffer = wszPath;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls' [redir]\n",
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer, rcNt));
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync pName = &ResolvedName;
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync }
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync else
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync memcpy(wszPath, pName->Buffer, pName->Length);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync wszPath[pName->Length / sizeof(WCHAR)] = '\0';
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync }
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));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
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 */
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync UINT cwc;
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 {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync rcNt = supR3HardenedCopyRedirectionResult(wszPath, RT_ELEMENTS(wszPath), pUniStrResult, pName, &cwc);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync RtlFreeUnicodeString(&UniStrDynamic);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync if (!NT_SUCCESS(rcNt))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", rcNt));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
28a2653de6f80a4b1f000cfc52e1a04492d4c151vboxsync return rcNt;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
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 */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync AssertCompile(sizeof(g_System32WinPath.awcBuffer) <= sizeof(wszPath));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync cwc = g_System32WinPath.UniStr.Length / sizeof(RTUTF16); Assert(cwc > 2);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync {
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));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return STATUS_NAME_TOO_LONG;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync }
9f997e760f610c92e3a365be21ead6972bc46130vboxsync memcpy(wszPath, g_System32WinPath.UniStr.Buffer, cwc * sizeof(RTUTF16));
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 */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync HANDLE hRootDir;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync UNICODE_STRING NtPathUniStr;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, wszPath, RTSTR_MAX);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_FAILURE(rc))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync {
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedError(rc, false,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supR3HardenedMonitor_LdrLoadDll: RTNtPathFromWinUtf16Ex failed on '%ls': %Rrc\n", wszPath, rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x\n", STATUS_OBJECT_NAME_INVALID));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync return STATUS_OBJECT_NAME_INVALID;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync }
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync OBJECT_ATTRIBUTES ObjAttr;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = NtCreateFile(&hFile,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync &ObjAttr,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync &Ios,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync NULL /* Allocation Size*/,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_ATTRIBUTE_NORMAL,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_SHARE_READ,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_OPEN,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync NULL /*EaBuffer*/,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync 0 /*EaLength*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (NT_SUCCESS(rcNt))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = Ios.Status;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (NT_SUCCESS(rcNt))
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 }
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinVerifyCacheProcessImportTodos();
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
30f07af559efcbd967e801903746fc21f81ee533vboxsync DWORD dwErr = RtlGetLastWin32Error();
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u (NtPath=%.*ls)\n",
9f997e760f610c92e3a365be21ead6972bc46130vboxsync wszPath, dwErr, NtPathUniStr.Length / sizeof(RTUTF16), NtPathUniStr.Buffer));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
9f997e760f610c92e3a365be21ead6972bc46130vboxsync RTNtPathFree(&NtPathUniStr, &hRootDir);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Screened successfully enough. Call the real thing.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%p:%ls [calling]\n",
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath,
680c2aff33be2ee9340c8763a3cb5c218c352bcfvboxsync !((uintptr_t)pwszSearchPath & 1) && (uintptr_t)pwszSearchPath >= 0x2000U ? pwszSearchPath : L"<flags>"));
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rcNt = g_pfnLdrLoadDllReal(pwszSearchPath, pfFlags, pName, phMod);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync /*
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * Log the result and process pending WinVerifyTrust work if we can.
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync */
30f07af559efcbd967e801903746fc21f81ee533vboxsync dwSavedLastError = RtlGetLastWin32Error();
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));
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync
93e05ea894cefd56ca308d72372b4dd8045bd1eevboxsync supR3HardenedWinVerifyCacheProcessWvtTodos();
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlRestoreLastWin32Error(dwSavedLastError);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync return rcNt;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/**
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * DLL load and unload notification callback.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This is a safety against our LdrLoadDll hook being replaced by protection
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * software. Though, we prefer the LdrLoadDll hook to this one as it allows us
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * to call WinVerifyTrust more freely.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param ulReason The reason we're called, see
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * LDR_DLL_NOTIFICATION_REASON_XXX.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pData Reason specific data. (Format is currently the same for
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * both load and unload.)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @param pvUser User parameter (ignored).
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks Vista and later.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * @remarks The loader lock is held when we're called, at least on Windows 7.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic VOID CALLBACK supR3HardenedDllNotificationCallback(ULONG ulReason, PCLDR_DLL_NOTIFICATION_DATA pData, PVOID pvUser)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync{
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NOREF(pvUser);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Screen the image on load. We will normally get a verification cache
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * hit here because of the LdrLoadDll and NtCreateSection hooks, so it
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * should be relatively cheap to recheck. In case our NtDll patches
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * got re
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * This ASSUMES that we get informed after the fact as indicated by the
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * available documentation.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (ulReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: load %p LB %#010x %.*ls [fFlags=%#x]\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.DllBase, pData->Loaded.SizeOfImage,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.Flags));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Convert the windows path to an NT path and open it. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync HANDLE hRootDir;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync UNICODE_STRING NtPathUniStr;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (RT_FAILURE(rc))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: RTNtPathFromWinUtf16Ex failed on '%.*ls': %Rrc\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, rc);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync return;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync OBJECT_ATTRIBUTES ObjAttr;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync &ObjAttr,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync &Ios,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NULL /* Allocation Size*/,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_ATTRIBUTE_NORMAL,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_SHARE_READ,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_OPEN,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NULL /*EaBuffer*/,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync 0 /*EaLength*/);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (NT_SUCCESS(rcNt))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = Ios.Status;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (!NT_SUCCESS(rcNt))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: NtCreateFile failed on '%.*ls' / '%.*ls': %#x\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTNtPathFree(&NtPathUniStr, &hRootDir);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync return;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Do the screening. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ULONG fAccess = 0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ULONG fProtect = 0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync bool fCallRealApi = false;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync bool fQuietFailure = false;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "LdrLoadDll", true /*fAvoidWinVerifyTrust*/, &fQuietFailure);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtClose(hFile);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (!NT_SUCCESS(rcNt))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatal("supR3HardenedDllNotificationCallback: supR3HardenedScreenImage failed on '%.*ls' / '%.*ls': %#x\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTNtPathFree(&NtPathUniStr, &hRootDir);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync return;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTNtPathFree(&NtPathUniStr, &hRootDir);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Log the unload call.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else if (ulReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: Unload %p LB %#010x %.*ls [flags=%#x]\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Unloaded.DllBase, pData->Unloaded.SizeOfImage,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Unloaded.FullDllName->Length / sizeof(WCHAR), pData->Unloaded.FullDllName->Buffer,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync pData->Unloaded.Flags));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Just log things we don't know and then return without caching anything.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync static uint32_t s_cLogEntries = 0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (s_cLogEntries++ < 32)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedDllNotificationCallback: ulReason=%u pData=%p\n", ulReason, pData));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync return;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Use this opportunity to make sure our NtDll patches are still in place,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * since they may be replaced by indecent protection software solutions.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync}
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/**
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Registers the DLL notification callback if it hasn't already been registered.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinRegisterDllNotificationCallback(void)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync{
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * The notification API was added in Vista, so it's an optional (weak) import.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if ( LdrRegisterDllNotification != NULL
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync && g_cDllNotificationRegistered <= 0
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync && g_cDllNotificationRegistered > -32)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NTSTATUS rcNt = LdrRegisterDllNotification(0, supR3HardenedDllNotificationCallback, NULL, &g_pvDllNotificationCookie);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (NT_SUCCESS(rcNt))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("Registered Dll notification callback with NTDLL.\n"));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_cDllNotificationRegistered = 1;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedError(rcNt, false /*fFatal*/, "LdrRegisterDllNotification failed: %#x\n", rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_cDllNotificationRegistered--;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync}
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
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
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync/**
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Checks if the calling thread is the only one in the process.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync *
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * @returns true if we're positive we're alone, false if not.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync */
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsyncstatic bool supR3HardenedWinAmIAlone(void)
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync{
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync ULONG fAmIAlone = 0;
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync ULONG cbIgn = 0;
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync NTSTATUS rcNt = NtQueryInformationThread(NtCurrentThread(), ThreadAmILastThread, &fAmIAlone, sizeof(fAmIAlone), &cbIgn);
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync Assert(NT_SUCCESS(rcNt));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync return NT_SUCCESS(rcNt) && fAmIAlone != 0;
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync}
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync
30f07af559efcbd967e801903746fc21f81ee533vboxsync/**
30f07af559efcbd967e801903746fc21f81ee533vboxsync * Simplify NtProtectVirtualMemory interface.
30f07af559efcbd967e801903746fc21f81ee533vboxsync *
30f07af559efcbd967e801903746fc21f81ee533vboxsync * Modifies protection for the current process. Caller must know the current
30f07af559efcbd967e801903746fc21f81ee533vboxsync * protection as it's not returned.
30f07af559efcbd967e801903746fc21f81ee533vboxsync *
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @returns NT status code.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param pvMem The memory to change protection for.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param cbMem The amount of memory to change.
30f07af559efcbd967e801903746fc21f81ee533vboxsync * @param fNewProt The new protection.
30f07af559efcbd967e801903746fc21f81ee533vboxsync */
30f07af559efcbd967e801903746fc21f81ee533vboxsyncstatic NTSTATUS supR3HardenedWinProtectMemory(PVOID pvMem, SIZE_T cbMem, ULONG fNewProt)
30f07af559efcbd967e801903746fc21f81ee533vboxsync{
30f07af559efcbd967e801903746fc21f81ee533vboxsync ULONG fOldProt = 0;
30f07af559efcbd967e801903746fc21f81ee533vboxsync return NtProtectVirtualMemory(NtCurrentProcess(), &pvMem, &cbMem, fNewProt, &fOldProt);
30f07af559efcbd967e801903746fc21f81ee533vboxsync}
30f07af559efcbd967e801903746fc21f81ee533vboxsync
30f07af559efcbd967e801903746fc21f81ee533vboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync/**
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Installs or reinstalls the NTDLL patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinReInstallHooks(bool fFirstCall)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync{
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync struct
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync size_t cbPatch;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uint8_t const *pabPatch;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uint8_t **ppbApi;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync const char *pszName;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync } const s_aPatches[] =
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" },
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync { sizeof(g_abLdrLoadDllPatch), g_abLdrLoadDllPatch, &g_pbLdrLoadDll, "LdrLoadDll" },
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync };
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ULONG fAmIAlone = ~(ULONG)0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPatches); i++)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uint8_t *pbApi = *s_aPatches[i].ppbApi;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (memcmp(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch) != 0)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Log the incident if it's not the initial call.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync static uint32_t volatile s_cTimes = 0;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (!fFirstCall && s_cTimes < 128)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync s_cTimes++;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUP_DPRINTF(("supR3HardenedWinReInstallHooks: Reinstalling %s (%p: %.*Rhxs).\n",
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync s_aPatches[i].pszName, pbApi, s_aPatches[i].cbPatch, pbApi));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync Assert(s_aPatches[i].cbPatch >= 4);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READWRITE));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * If we're alone, just memcpy the patch in.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (fAmIAlone == ~(ULONG)0)
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync fAmIAlone = supR3HardenedWinAmIAlone();
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (fAmIAlone)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync else
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Not alone. Start by injecting a JMP $-2, then waste some
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * CPU cycles to get the other threads a good chance of getting
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * out of the code before we replace it.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTUINT32U uJmpDollarMinus;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uJmpDollarMinus.au8[0] = 0xeb;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uJmpDollarMinus.au8[1] = 0xfe;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uJmpDollarMinus.au8[2] = pbApi[2];
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync uJmpDollarMinus.au8[3] = pbApi[3];
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ASMAtomicXchgU32((uint32_t volatile *)pbApi, uJmpDollarMinus.u);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtYieldExecution();
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync NtYieldExecution();
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Copy in the tail bytes of the patch, then xchg the jmp $-2. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (s_aPatches[i].cbPatch > 4)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(&pbApi[4], &s_aPatches[i].pabPatch[4], s_aPatches[i].cbPatch - 4);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync ASMAtomicXchgU32((uint32_t volatile *)pbApi, *(uint32_t *)s_aPatches[i].pabPatch);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READ));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync}
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
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 */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsyncstatic void supR3HardenedWinInstallHooks(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync NTSTATUS rcNt;
751a35d04fb11f94562583ad77bc0a1382957f49vboxsync
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 */
a6c871653045073d6ef74d0589de345ae62b607dvboxsync PFNRT pfnNtCreateSection = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "NtCreateSection");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPR3HARDENED_ASSERT(pfnNtCreateSection != NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a6c871653045073d6ef74d0589de345ae62b607dvboxsync PFNRT pfnLdrLoadDll = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "LdrLoadDll");
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUPR3HARDENED_ASSERT(pfnLdrLoadDll != NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * Exec page setup & management.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync uint32_t offExecPage = 0;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
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;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_pbNtCreateSection = pbNtCreateSection;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abNtCreateSectionPatch, pbNtCreateSection, sizeof(g_abNtCreateSectionPatch));
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_pfnNtCreateSectionReal = NtCreateSection; /* our direct syscall */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 64-bit hosts.
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 */
30f07af559efcbd967e801903746fc21f81ee533vboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[0] = 0x48; /* mov rax, qword */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[1] = 0xb8;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync *(uint64_t *)&g_abNtCreateSectionPatch[2] = (uint64_t)supR3HardenedMonitor_NtCreateSection;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[10] = 0xff; /* jmp rax */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[11] = 0xe0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Patch 32-bit hosts.
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
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync The variable bit is the value loaded into eax: W81=154h */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abNtCreateSectionPatch[0] = 0xe9; /* jmp rel32 */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync - (uintptr_t)&pbNtCreateSection[1+4];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync#endif
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
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;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_pbLdrLoadDll = pbLdrLoadDll;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync DISSTATE Dis;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync uint32_t cbInstr;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync uint32_t offJmpBack = 0;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef RT_ARCH_AMD64
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 64-bit hosts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /* Just use the disassembler to skip 12 bytes or more. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync while (offJmpBack < 12)
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
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
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the LdrLoadDll patch. */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync Assert(offJmpBack >= 12);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abLdrLoadDllPatch[0] = 0x48; /* mov rax, qword */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abLdrLoadDllPatch[1] = 0xb8;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync *(uint64_t *)&g_abLdrLoadDllPatch[2] = (uint64_t)supR3HardenedMonitor_LdrLoadDll;
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abLdrLoadDllPatch[10] = 0xff; /* jmp rax */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abLdrLoadDllPatch[11] = 0xe0;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Patch 32-bit hosts.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /* Just use the disassembler to skip 5 bytes or more. */
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
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; /* jmp rel32 */
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
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /* Assemble the LdrLoadDll patch. */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync Assert(offJmpBack >= 5);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync g_abLdrLoadDllPatch[0] = 0xe9;
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *(uint32_t *)&g_abLdrLoadDllPatch[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Seal the rwx page.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
30f07af559efcbd967e801903746fc21f81ee533vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(g_abSupHardReadWriteExecPage, PAGE_SIZE, PAGE_EXECUTE_READ));
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install the patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(true /*fFirstCall*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * T h r e a d c r e a t i o n c o n t r o l
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Common code used for child and parent to make new threads exit immediately.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This patches the LdrInitializeThunk code to call NtTerminateThread with
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * STATUS_SUCCESS instead of doing the NTDLL initialization.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns VBox status code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process to do this to.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * override.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvNtTerminateThread The address of the NtTerminateThread function in
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the NTDLL instance we're patching. (Must be +/-
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * 2GB from the thunk code.)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pabBackup Where to back up the original instruction bytes
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * at pvLdrInitThunk.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pErrInfo Where to return extended error information.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtDisableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, void *pvNtTerminateThread,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint8_t *pabBackup, size_t cbBackup, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtDisableThreadCreation: pvLdrInitThunk=%p pvNtTerminateThread=%p\n", pvLdrInitThunk, pvNtTerminateThread));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(cbBackup == 16);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(RT_ABS((intptr_t)pvLdrInitThunk - (intptr_t)pvNtTerminateThread) < 16*_1M);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Back up the thunk code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbIgnored;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtReadVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreation: NtReadVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Cook up replacement code that calls NtTerminateThread.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint8_t abReplacement[16];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(abReplacement, pabBackup, sizeof(abReplacement));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#ifdef RT_ARCH_AMD64
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[0] = 0x31; /* xor ecx, ecx */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[1] = 0xc9;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[2] = 0x31; /* xor edx, edx */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[3] = 0xd2;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[9] = 0xcc; /* int3 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#elif defined(RT_ARCH_X86)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[0] = 0x6a; /* push 0 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[1] = 0x00;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[2] = 0x6a; /* push 0 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[3] = 0x00;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[4] = 0xe8; /* call near NtTerminateThread */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *(int32_t *)&abReplacement[5] = (int32_t)((uintptr_t)pvNtTerminateThread - ((uintptr_t)pvLdrInitThunk + 9));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync abReplacement[9] = 0xcc; /* int3 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync# error "Unsupported arch."
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Install the replacment code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PVOID pvProt = pvLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbProt = cbBackup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fOldProt = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, abReplacement, sizeof(abReplacement), &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pvProt = pvLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cbProt = cbBackup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk/2 failed: %#x", rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return VINF_SUCCESS;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Undo the effects of supR3HardNtDisableThreadCreationEx.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns VBox status code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process to do this to.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pvLdrInitThunk The address of the LdrInitializeThunk code to
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * override.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pabBackup Where to back up the original instruction bytes
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * at pvLdrInitThunk.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbBackup The size of the backup area. Must be 16 bytes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pErrInfo Where to return extended error information.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Optional.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic int supR3HardNtEnableThreadCreationEx(HANDLE hProcess, void *pvLdrInitThunk, uint8_t const *pabBackup, size_t cbBackup,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PRTERRINFO pErrInfo)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtEnableThreadCreation:\n"));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(cbBackup == 16);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PVOID pvProt = pvLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbProt = cbBackup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fOldProt = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtDisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbIgnored;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, pabBackup, cbBackup, &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtEnableThreadCreation: NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pvProt = pvLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cbProt = cbBackup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardNtEnableThreadCreation: NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return VINF_SUCCESS;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Disable thread creation for the current process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @remarks Doesn't really disables it, just makes the threads exit immediately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * without executing any real code.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardenedWinDisableThreadCreation(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Cannot use the imported NtTerminateThread as it's pointing to our own
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync syscall assembly code. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync static PFNRT s_pfnNtTerminateThread = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (s_pfnNtTerminateThread == NULL)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync s_pfnNtTerminateThread = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "NtTerminateThread");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(s_pfnNtTerminateThread);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardNtDisableThreadCreationEx(NtCurrentProcess(),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync (void *)(uintptr_t)&LdrInitializeThunk,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync (void *)(uintptr_t)s_pfnNtTerminateThread,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NULL /* pErrInfo*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_fSupInitThunkSelfPatched = RT_SUCCESS(rc);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Undoes the effects of supR3HardenedWinDisableThreadCreation.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncDECLHIDDEN(void) supR3HardenedWinEnableThreadCreation(void)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_fSupInitThunkSelfPatched)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supR3HardNtEnableThreadCreationEx(NtCurrentProcess(),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync (void *)(uintptr_t)&LdrInitializeThunk,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_abLdrInitThunkSelfBackup, sizeof(g_abLdrInitThunkSelfBackup),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RTErrInfoInitStatic(&g_ErrInfoStatic));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (RT_FAILURE(rc))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rc, true /*fFatal*/, "%s", g_ErrInfoStatic.szMsg);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_fSupInitThunkSelfPatched = false;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * R e s p a w n
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Gets the SID of the user associated with the process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns @c true if we've got a login SID, @c false if not.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSidUser Where to return the user SID.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbSidUser The size of the user SID buffer.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSidLogin Where to return the login SID.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cbSidLogin The size of the login SID buffer.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic bool supR3HardNtChildGetUserAndLogSids(PSID pSidUser, ULONG cbSidUser, PSID pSidLogin, ULONG cbSidLogin)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hToken;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync union
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync TOKEN_USER UserInfo;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync TOKEN_GROUPS Groups;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint8_t abPadding[4096];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync } uBuf;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG cbRet = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtQueryInformationToken(hToken, TokenUser, &uBuf, sizeof(uBuf), &cbRet));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidUser, pSidUser, uBuf.UserInfo.User.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fLoginSid = false;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryInformationToken(hToken, TokenLogonSid, &uBuf, sizeof(uBuf), &cbRet);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync for (DWORD i = 0; i < uBuf.Groups.GroupCount; i++)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ((uBuf.Groups.Groups[i].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCopySid(cbSidLogin, pSidLogin, uBuf.Groups.Groups[i].Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fLoginSid = true;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync break;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtClose(hToken));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return fLoginSid;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Build security attributes for the process or the primary thread (@a fProcess)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process DACLs can be bypassed using the SeDebugPrivilege (generally available
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * to admins, i.e. normal windows users), or by taking ownership and/or
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * modifying the DACL. However, it restricts
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pSecAttrs Where to return the security attributes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pCleanup Cleanup record.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param fProcess Set if it's for the process, clear if it's for
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the primary thread.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildInitSecAttrs(PSECURITY_ATTRIBUTES pSecAttrs, PMYSECURITYCLEANUP pCleanup, bool fProcess)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Safe return values.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync suplibHardenedMemSet(pCleanup, 0, sizeof(*pCleanup));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pSecAttrs->nLength = sizeof(*pSecAttrs);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pSecAttrs->bInheritHandle = FALSE;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pSecAttrs->lpSecurityDescriptor = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/** @todo This isn't at all complete, just sketches... */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Create an ACL detailing the access of the above groups.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlCreateAcl(&pCleanup->Acl.AclHdr, sizeof(pCleanup->Acl), ACL_REVISION));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fDeny = DELETE | WRITE_DAC | WRITE_OWNER;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fAllow = SYNCHRONIZE | READ_CONTROL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fAllowLogin = SYNCHRONIZE | READ_CONTROL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (fProcess)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= PROCESS_CREATE_THREAD | PROCESS_SET_SESSIONID | PROCESS_VM_OPERATION | PROCESS_VM_WRITE
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_SET_QUOTA
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= PROCESS_QUERY_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= PROCESS_QUERY_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)) /* Introduced in Windows 8.1. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= PROCESS_SET_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= THREAD_SUSPEND_RESUME | THREAD_SET_CONTEXT | THREAD_SET_INFORMATION | THREAD_SET_THREAD_TOKEN
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync | THREAD_IMPERSONATE | THREAD_DIRECT_IMPERSONATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow |= THREAD_QUERY_LIMITED_INFORMATION | THREAD_SET_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllowLogin |= THREAD_QUERY_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny |= ~fAllow & (SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Deny everyone access to bad bits. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#if 1
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Everyone.Sid, &SIDAuthWorld, 1));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *RtlSubAuthoritySid(&pCleanup->Everyone.Sid, 0) = SECURITY_WORLD_RID;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny, &pCleanup->Everyone.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#endif
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#if 0
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Grant some access to the owner - doesn't work. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SID_IDENTIFIER_AUTHORITY SIDAuthCreator = SECURITY_CREATOR_SID_AUTHORITY;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlInitializeSid(&pCleanup->Owner.Sid, &SIDAuthCreator, 1));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *RtlSubAuthoritySid(&pCleanup->Owner.Sid, 0) = SECURITY_CREATOR_OWNER_RID;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny, &pCleanup->Owner.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fAllow, &pCleanup->Owner.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#endif
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#if 1
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fHasLoginSid = supR3HardNtChildGetUserAndLogSids(&pCleanup->User.Sid, sizeof(pCleanup->User),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &pCleanup->Login.Sid, sizeof(pCleanup->Login));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync# if 1
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Grant minimal access to the user. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessDeniedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fDeny, &pCleanup->User.Sid));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(RtlAddAccessAllowedAce(&pCleanup->Acl.AclHdr, ACL_REVISION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync 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 */
30f07af559efcbd967e801903746fc21f81ee533vboxsync PSECURITY_DESCRIPTOR pSecDesc = (PSECURITY_DESCRIPTOR)RTMemAllocZ(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 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic PRTUTF16 supR3HardNtChildConstructCmdLine(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)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardNtChildConstructCmdLine", kSupInitOp_Misc, VERR_OUT_OF_RANGE,
edde275acba04aca58db4172a163741e3abadfbcvboxsync "Command line is too long (%u chars)!", cwcCmdLine);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
30f07af559efcbd967e801903746fc21f81ee533vboxsync PRTUTF16 pwszCmdLine = (PRTUTF16)RTMemAlloc((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/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Terminates the child process.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param hProcess The process handle.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhere Who's having child rasing troubles.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param rc The status code to report.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszFormat The message format string.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param ... Message format arguments.
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardenedWinKillChild(HANDLE hProcess, const char *pszWhere, int rc, const char *pszFormat, ...)
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Terminate the process ASAP and display error.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(hProcess, RTEXITCODE_FAILURE);
dca3cdd56f38abf4257b94ff13268323ea52e0a7vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync va_list va;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync va_start(va, pszFormat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedErrorV(rc, false /*fFatal*/, pszFormat, va);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync va_end(va);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the process to really go away.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PROCESS_BASIC_INFORMATION BasicInfo;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync bool fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!fExitOk)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNtWait;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync do
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync LARGE_INTEGER Timeout;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = -20000000; /* 2 second */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForSingleObject(hProcess, TRUE /*Alertable*/, &Timeout);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtExit = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fExitOk = NT_SUCCESS(rcNtExit) && BasicInfo.ExitStatus != STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync } while ( !fExitOk
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && ( rcNtWait == STATUS_TIMEOUT
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || rcNtWait == STATUS_USER_APC
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || rcNtWait == STATUS_ALERTED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && supR3HardenedWinGetMilliTS() - uMsTsStart < 60 * 1000);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (fExitOk)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rc, false /*fFatal*/,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtDuplicateObject failed and we failed to kill child: rc=%u (%#x) rcNtWait=%#x hProcess=%p\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc, rc, rcNtWait, hProcess);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Final error message.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync va_start(va, pszFormat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsgV(pszWhere, kSupInitOp_Misc, rc, pszFormat, va);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync va_end(va);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync}
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Checks the child process when hEvtParent is signalled.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This will read the request data from the child and check it against expected
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * request. If an error is signalled, we'll raise it and make sure the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * terminates before terminating the calling process.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param enmExpectedRequest The expected child request.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhat What we're waiting for.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildProcessRequest(PSUPR3HARDNTCHILD pThis, SUPR3WINCHILDREQ enmExpectedRequest, const char *pszWhat)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Read the process parameters from the child.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uChildAddr = (uintptr_t)pThis->Peb.ImageBaseAddress
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbIgnored = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RT_ZERO(pThis->ProcParams);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtReadVirtualMemory(pThis->hProcess, (PVOID)uChildAddr,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &pThis->ProcParams, sizeof(pThis->ProcParams), &cbIgnored);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildProcessRequest", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtReadVirtualMemory(,%p,) failed reading child process status: %#x\n", uChildAddr, rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Is it the expected request?
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmRequest == enmExpectedRequest)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * No, not the expected request. If it's an error request, tell the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * to terminate itself, otherwise we'll have to terminate it.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szErrorMsg[sizeof(pThis->ProcParams.szErrorMsg) - 1] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szWhere[sizeof(pThis->ProcParams.szWhere) - 1] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedWinCheckChild: enmRequest=%d rc=%d enmWhat=%d %s: %s\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest, pThis->ProcParams.rc, pThis->ProcParams.enmWhat,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.szWhere, pThis->ProcParams.szErrorMsg));
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmRequest != kSupR3WinChildReq_Error)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinCheckChild", VERR_INVALID_PARAMETER,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Unexpected child request #%d. Was expecting #%d (%s).\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest, enmExpectedRequest, pszWhat);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtSetEvent(pThis->hEvtChild, NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildProcessRequest", rcNt, "NtSetEvent failed: %#x\n", rcNt);
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Wait for it to terminate. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync LARGE_INTEGER Timeout;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = -50000000; /* 5 seconds */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWaitForSingleObject(pThis->hProcess, FALSE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNt != STATUS_WAIT_0)
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildProcessRequest: Child is taking too long to quit (rcWait=%#x), killing it...\n", rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateProcess(pThis->hProcess, DBG_TERMINATE_PROCESS);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Report the error in the same way as it occured in the guest.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->ProcParams.enmWhat == kSupInitOp_Invalid)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg("supR3HardenedWinCheckChild", kSupInitOp_Misc, pThis->ProcParams.rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "%s", pThis->ProcParams.szErrorMsg);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedFatalMsg(pThis->ProcParams.szWhere, pThis->ProcParams.enmWhat, pThis->ProcParams.rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "%s", pThis->ProcParams.szErrorMsg);
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync}
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Waits for the child to make a certain request or terminate.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The stub process will also wait on it's parent to terminate.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This call will only return if the child made the expected request.
edde275acba04aca58db4172a163741e3abadfbcvboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param enmExpectedRequest The child request to wait for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param cMsTimeout The number of milliseconds to wait (at least).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszWhat What we're waiting for.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildWaitFor(PSUPR3HARDNTCHILD pThis, SUPR3WINCHILDREQ enmExpectedRequest, RTMSINTERVAL cMsTimeout,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync const char *pszWhat)
edde275acba04aca58db4172a163741e3abadfbcvboxsync{
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The wait loop.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Will return when the expected request arrives.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Will break out when one of the processes terminates.
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNtWait;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync LARGE_INTEGER Timeout;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint64_t cMsElapsed = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync for (;;)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Assemble handles to wait for.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG cHandles = 1;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE ahHandles[3];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ahHandles[0] = pThis->hProcess;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->hEvtParent)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ahHandles[cHandles++] = pThis->hEvtParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->hParent)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ahHandles[cHandles++] = pThis->hParent;
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Do the waiting according to the callers wishes.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( enmExpectedRequest == kSupR3WinChildReq_End
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || cMsTimeout == RT_INDEFINITE_WAIT)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*Timeout*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = -(int64_t)(cMsTimeout - cMsElapsed) * 10000;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process child request.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNtWait == STATUS_WAIT_0 + 1 && pThis->hEvtParent != NULL)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildProcessRequest(pThis, enmExpectedRequest, pszWhat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildWaitFor: Found expected request %d (%s) after %llu ms.\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync enmExpectedRequest, pszWhat, supR3HardenedWinGetMilliTS() - uMsTsStart));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return; /* Expected request received. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
1042ff61f0b8de217c7e694021be0b9a5b9b8468vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process termination?
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( (ULONG)rcNtWait - (ULONG)STATUS_WAIT_0 < cHandles
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || (ULONG)rcNtWait - (ULONG)STATUS_ABANDONED_WAIT_0 < cHandles)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync break;
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Check sanity.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( rcNtWait != STATUS_TIMEOUT
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && rcNtWait != STATUS_USER_APC
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && rcNtWait != STATUS_ALERTED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildWaitFor", rcNtWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtWaitForMultipleObjects returned %#x waiting for #%d (%s)\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNtWait, enmExpectedRequest, pszWhat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Calc elapsed time for the next timeout calculation, checking to see
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * if we've timed out already.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cMsElapsed = supR3HardenedWinGetMilliTS() - uMsTsStart;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( cMsElapsed > cMsTimeout
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && cMsTimeout != RT_INDEFINITE_WAIT
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync && enmExpectedRequest != kSupR3WinChildReq_End)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNtWait == STATUS_USER_APC || rcNtWait == STATUS_ALERTED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cMsElapsed = cMsTimeout - 1; /* try again */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* We timed out. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildWaitFor", rcNtWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "Timed out after %llu ms waiting for child request #%d (%s).\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cMsElapsed, enmExpectedRequest, pszWhat);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Proxy the termination code of the child, if it exited already.
04f85536aa01b3e25cece11d2a094e2a362bcbfavboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PROCESS_BASIC_INFORMATION BasicInfo;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt1 = NtQueryInformationProcess(pThis->hProcess, ProcessBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt2 = STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt3 = STATUS_PENDING;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( !NT_SUCCESS(rcNt1)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || BasicInfo.ExitStatus == STATUS_PENDING)
edde275acba04aca58db4172a163741e3abadfbcvboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt2 = NtTerminateProcess(pThis->hProcess, RTEXITCODE_FAILURE);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = NT_SUCCESS(rcNt2) ? -20000000 /* 2 sec */ : -1280000 /* 128 ms */;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt3 = NtWaitForSingleObject(pThis->hProcess, FALSE /*Alertable*/, NULL /*Timeout*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync BasicInfo.ExitStatus = RTEXITCODE_FAILURE;
edde275acba04aca58db4172a163741e3abadfbcvboxsync }
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildWaitFor[%d]: Quitting: ExitCode=%#x (rcNtWait=%#x, rcNt1=%#x, rcNt2=%#x, rcNt3=%#x, %llu ms, %s);\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->iWhich, BasicInfo.ExitStatus, rcNtWait, rcNt1, rcNt2, rcNt3,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinGetMilliTS() - uMsTsStart, pszWhat));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync suplibHardenedExit((RTEXITCODE)BasicInfo.ExitStatus);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Closes full access child thread and process handles, making a harmless
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * duplicate of the process handle first.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The hProcess member of the child process data structure will be change to the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * harmless handle, while the hThread will be set to NULL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildCloseFullAccessHandles(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The thread handle.
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtClose(pThis->hThread);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", rcNt, "NtClose(hThread) failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->hThread = NULL;
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Duplicate the process handle into a harmless one.
eca3ddadc12f677ac68395c5eab914d41fc8963avboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hProcWait;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_VM_READ;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fRights |= PROCESS_QUERY_LIMITED_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fRights |= PROCESS_QUERY_INFORMATION;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtCurrentProcess(), &hProcWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fRights, 0 /*HandleAttributes*/, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNt == STATUS_ACCESS_DENIED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedError(rcNt, false /*fFatal*/,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supR3HardenedWinDoReSpawn: NtDuplicateObject(,,,,%#x,,) -> %#x, retrying with only %#x...\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync fRights, rcNt, SYNCHRONIZE);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtDuplicateObject(NtCurrentProcess(), pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtCurrentProcess(), &hProcWait,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SYNCHRONIZE, 0 /*HandleAttributes*/, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtDuplicateObject failed on child process handle: %#x\n", rcNt);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Close the process handle and replace it with the harmless one.
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtClose(pThis->hProcess);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->hProcess = hProcWait;
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtClose failed on child process handle: %#x\n", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This restores the child PEB and tweaks a couple of fields before we do the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * child purification and let the process run normally.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildSanitizePeb(PSUPR3HARDNTCHILD 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))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildSanitizePeb", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync}
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Purifies the child process after very early init has been performed.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildPurify(PSUPR3HARDNTCHILD pThis)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync{
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We loop until we no longer make any fixes. This is similar to what
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * we do (or used to do, really) in the fAvastKludge case of
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * supR3HardenedWinInit. We might be up against asynchronous changes,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * which we fudge by waiting a short while before earch purification. This
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * is arguably a fragile technique, but it's currently the best we've got.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Fortunately, most AVs seems to either favor immediate action on initial
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * load events or (much better for us) later events like kernel32.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync uint64_t uMsTsOuterStart = supR3HardenedWinGetMilliTS();
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync uint32_t cMsFudge = g_fSupAdversaries ? 512 : 256;
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync uint32_t cTotalFixes = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint32_t cFixes;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync for (uint32_t iLoop = 0; iLoop < 16; iLoop++)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Delay.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint32_t cSleeps = 0;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
9f997e760f610c92e3a365be21ead6972bc46130vboxsync do
9f997e760f610c92e3a365be21ead6972bc46130vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtYieldExecution();
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync LARGE_INTEGER Time;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtDelayExecution(FALSE, &Time);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cSleeps++;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync } while ( supR3HardenedWinGetMilliTS() - uMsTsStart <= cMsFudge
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || cSleeps < 8);
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: Startup delay kludge #1/%u: %u ms, %u sleeps\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync iLoop, supR3HardenedWinGetMilliTS() - uMsTsStart, cSleeps));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Purify.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cFixes = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync int rc = supHardenedWinVerifyProcess(pThis->hProcess, pThis->hThread, SUPHARDNTVPKIND_CHILD_PURIFICATION,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &cFixes, RTErrInfoInitStatic(&g_ErrInfoStatic));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (RT_FAILURE(rc))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildPurify", rc,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "supHardenedWinVerifyProcess failed with %Rrc: %s", g_ErrInfoStatic.szMsg);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (cFixes == 0)
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync {
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: Done after %llu ms and %u fixes (loop #%u).\n",
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync supR3HardenedWinGetMilliTS() - uMsTsOuterStart, cTotalFixes, iLoop));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return; /* We're probably good. */
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync }
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync cTotalFixes += cFixes;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!g_fSupAdversaries)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_fSupAdversaries |= SUPHARDNT_ADVERSARY_UNKNOWN;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cMsFudge = 512;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Log the KiOpPrefetchPatchCount value if available, hoping it might
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * sched some light on spider38's case.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG cPatchCount = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &cPatchCount, sizeof(cPatchCount), NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (NT_SUCCESS(rcNt))
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cFixes, g_fSupAdversaries, cPatchCount));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync SUP_DPRINTF(("supR3HardNtChildPurify: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync }
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We've given up fixing the child process. Probably fighting someone
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * that monitors their patches or/and our activities.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildPurify", VERR_TRY_AGAIN,
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync "Unable to purify child process! After 16 tries over %llu ms, we still %u fix(es) in the last pass.",
bc6740610771ba30b63f58af903b4824c33f5b51vboxsync supR3HardenedWinGetMilliTS() - uMsTsOuterStart, cFixes);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync}
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Sets up the early process init.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildSetUpChildInit(PSUPR3HARDNTCHILD pThis)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t const uChildExeAddr = (uintptr_t)pThis->Peb.ImageBaseAddress;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Plant the process parameters. This ASSUMES the handle inheritance is
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * performed when creating the child process.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RT_ZERO(pThis->ProcParams);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.hEvtChild = pThis->hEvtChild;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.hEvtParent = pThis->hEvtParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.uNtDllAddr = pThis->uNtDllAddr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.enmRequest = kSupR3WinChildReq_Error;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->ProcParams.rc = VINF_SUCCESS;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uintptr_t uChildAddr = uChildExeAddr + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SIZE_T cbIgnored;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, (PVOID)uChildAddr, &pThis->ProcParams,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync sizeof(pThis->ProcParams), &cbIgnored);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtWriteVirtualMemory(,%p,) failed writing child process parameters: %#x\n", uChildAddr, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Locate the LdrInitializeThunk address in the child as well as pristine
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * code bits for it.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PSUPHNTLDRCACHEENTRY pLdrEntry;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_FAILURE(rc))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uint8_t *pbChildNtDllBits;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbChildNtDllBits, pThis->uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_FAILURE(rc))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync RTLDRADDR uLdrInitThunk;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbChildNtDllBits, pThis->uNtDllAddr, UINT32_MAX,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "LdrInitializeThunk", &uLdrInitThunk);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_FAILURE(rc))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rc,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedWinSetupChildInit: uLdrInitThunk=%p\n", (uintptr_t)uLdrInitThunk));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Calculate the address of our code in the child process.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uintptr_t uEarlyProcInitEP = uChildExeAddr + ( (uintptr_t)&supR3HardenedEarlyProcessInitThunk
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Compose the LdrInitializeThunk replacement bytes.
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Note! The amount of code we replace here must be less or equal to what
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * the process verification code ignores.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uint8_t abNew[16];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(abNew, pbChildNtDllBits + ((uintptr_t)uLdrInitThunk - pThis->uNtDllAddr), sizeof(abNew));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync#ifdef RT_ARCH_AMD64
9f997e760f610c92e3a365be21ead6972bc46130vboxsync abNew[0] = 0xff;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync abNew[1] = 0x25;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync *(uint32_t *)&abNew[2] = 0;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync *(uint64_t *)&abNew[6] = uEarlyProcInitEP;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync#elif defined(RT_ARCH_X86)
9f997e760f610c92e3a365be21ead6972bc46130vboxsync abNew[0] = 0xe9;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync *(uint32_t *)&abNew[1] = uEarlyProcInitEP - ((uint32_t)uLdrInitThunk + 5);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync#else
9f997e760f610c92e3a365be21ead6972bc46130vboxsync# error "Unsupported arch."
9f997e760f610c92e3a365be21ead6972bc46130vboxsync#endif
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Install the LdrInitializeThunk replacement code in the child process.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PVOID pvProt = pvLdrInitThunk;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SIZE_T cbProt = sizeof(abNew);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync ULONG fOldProt;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtWriteVirtualMemory(pThis->hProcess, pvLdrInitThunk, abNew, sizeof(abNew), &cbIgnored);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync pvProt = pvLdrInitThunk;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync cbProt = sizeof(abNew);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardenedWinSetupChildInit", rcNt,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync "NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /* Caller starts child execution. */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedWinSetupChildInit: Start child.\n"));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync}
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * This messes with the child PEB before we trigger the initial image events.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildScrewUpPebForInitialImageEvents(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Not sure if any of the cracker software uses the PEB at this point, but
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * just in case they do make some of the PEB fields a little less useful.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PEB Peb = pThis->Peb;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Make ImageBaseAddress useless. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress ^ UINT32_C(0x5f139000));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#ifdef RT_ARCH_AMD64
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Peb.ImageBaseAddress = (PVOID)((uintptr_t)Peb.ImageBaseAddress | UINT64_C(0x0313000000000000));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#endif
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Write the PEB.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbActualMem = pThis->cbPeb;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtWriteVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &Peb, pThis->cbPeb, &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildScrewUpPebForInitialImageEvents", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtWriteVirtualMemory/Peb failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Check if the zero terminated NT unicode string is the path to the given
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * system32 DLL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @returns true if it is, false if not.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pUniStr The zero terminated NT unicode string path.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pszName The name of the system32 DLL.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic bool supR3HardNtIsNamedSystem32Dll(PUNICODE_STRING pUniStr, const char *pszName)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pUniStr->Length > g_System32NtPath.UniStr.Length)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (memcmp(pUniStr->Buffer, g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length) == 0)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR)] == '\\')
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (RTUtf16ICmpAscii(&pUniStr->Buffer[g_System32NtPath.UniStr.Length / sizeof(WCHAR) + 1], pszName) == 0)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return true;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return false;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Worker for supR3HardNtChildGatherData that locates NTDLL in the child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * process.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param pThis The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildFindNtdll(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Find NTDLL in this process first and take that as a starting point.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllParentAddr = (uintptr_t)GetModuleHandleW(L"ntdll.dll");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(pThis->uNtDllParentAddr != 0 && !(pThis->uNtDllParentAddr & PAGE_OFFSET_MASK));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllAddr = pThis->uNtDllParentAddr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Scan the virtual memory of the child.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t cbAdvance = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uPtrWhere = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync for (uint32_t i = 0; i < 1024; i++)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Query information. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbActual = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync (void const *)uPtrWhere,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync MemoryBasicInformation,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &MemInfo,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync sizeof(MemInfo),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &cbActual);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync break;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( MemInfo.Type == SEC_IMAGE
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || MemInfo.Type == SEC_PROTECTED_IMAGE
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (MemInfo.BaseAddress == MemInfo.AllocationBase)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Get the image name. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync union
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync UNICODE_STRING UniStr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uint8_t abPadding[4096];
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync } uBuf;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync MemInfo.BaseAddress,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync MemorySectionName,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &uBuf,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync sizeof(uBuf) - sizeof(WCHAR),
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &cbActual);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (supR3HardNtIsNamedSystem32Dll(&uBuf.UniStr, "ntdll.dll"))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllAddr = (uintptr_t)MemInfo.AllocationBase;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtPuChFindNtdll: uNtDllParentAddr=%p uNtDllChildAddr=%p\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->uNtDllParentAddr, pThis->uNtDllAddr));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Advance.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync cbAdvance = MemInfo.RegionSize;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (uPtrWhere + cbAdvance <= uPtrWhere)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync break;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uPtrWhere += MemInfo.RegionSize;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildFindNtdll", VERR_MODULE_NOT_FOUND, "ntdll.dll not found in child process.");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync/**
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Gather child data.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * @param This The child process data structure.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void supR3HardNtChildGatherData(PSUPR3HARDNTCHILD pThis)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync{
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Basic info.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG cbActual = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = NtQueryInformationProcess(pThis->hProcess, ProcessBasicInformation,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync &pThis->BasicInfo, sizeof(pThis->BasicInfo), &cbActual);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildGatherData", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtQueryInformationProcess/ProcessBasicInformation failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * If this is the middle (stub) process, we wish to wait for both child
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * and parent. So open the parent process. Not fatal if we cannnot.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (pThis->iWhich > 1)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync OBJECT_ATTRIBUTES ObjAttr;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync CLIENT_ID ClientId;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ClientId.UniqueProcess = (HANDLE)pThis->BasicInfo.InheritedFromUniqueProcessId;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ClientId.UniqueThread = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtOpenProcess(&pThis->hParent, SYNCHRONIZE | PROCESS_QUERY_INFORMATION, &ObjAttr, &ClientId);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#ifdef DEBUG
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync#endif
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->hParent = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildGatherData: Failed to open parent process (%#p): %#x\n", ClientId.UniqueProcess, rcNt));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Process environment block.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_uNtVerCombined < SUP_NT_VER_W2K3)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W51;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else if (g_uNtVerCombined < SUP_NT_VER_VISTA)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W52;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else if (g_uNtVerCombined < SUP_NT_VER_W70)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W6;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else if (g_uNtVerCombined < SUP_NT_VER_W80)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W7;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else if (g_uNtVerCombined < SUP_NT_VER_W81)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W80;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync else
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->cbPeb = PEB_SIZE_W81;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardNtChildGatherData: PebBaseAddress=%p cbPeb=%#x\n",
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync pThis->BasicInfo.PebBaseAddress, pThis->cbPeb));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SIZE_T cbActualMem;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RT_ZERO(pThis->Peb);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtReadVirtualMemory(pThis->hProcess, pThis->BasicInfo.PebBaseAddress, &pThis->Peb, sizeof(pThis->Peb), &cbActualMem);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(pThis, "supR3HardNtChildGatherData", rcNt,
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync "NtReadVirtualMemory/Peb failed: %#x", rcNt);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Locate NtDll.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildFindNtdll(pThis);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync}
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsyncstatic void 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
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Init the child process data structure, creating the child communication
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * event sempahores.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDNTCHILD This;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RT_ZERO(This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.iWhich = iWhich;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync OBJECT_ATTRIBUTES ObjAttrs;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hEvtChild = NULL;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&This.hEvtChild, EVENT_ALL_ACCESS, &ObjAttrs, SynchronizationEvent, FALSE));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hEvtParent = NULL;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&This.hEvtParent, EVENT_ALL_ACCESS, &ObjAttrs, SynchronizationEvent, FALSE));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
edde275acba04aca58db4172a163741e3abadfbcvboxsync * Set up security descriptors.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync SECURITY_ATTRIBUTES ProcessSecAttrs;
edde275acba04aca58db4172a163741e3abadfbcvboxsync MYSECURITYCLEANUP ProcessSecAttrsCleanup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildInitSecAttrs(&ProcessSecAttrs, &ProcessSecAttrsCleanup, true /*fProcess*/);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync SECURITY_ATTRIBUTES ThreadSecAttrs;
edde275acba04aca58db4172a163741e3abadfbcvboxsync MYSECURITYCLEANUP ThreadSecAttrsCleanup;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildInitSecAttrs(&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
a505d18eaecf5f7faff58cc7c05397f8adaf6d71vboxsync SiEx.StartupInfo.dwFlags |= pParentProcParams->WindowFlags & STARTF_USESHOWWINDOW;
0aab9cd857ec35928a0e61c68d3f27a5b4d88a95vboxsync SiEx.StartupInfo.wShowWindow = (WORD)pParentProcParams->ShowWindowFlags;
0aab9cd857ec35928a0e61c68d3f27a5b4d88a95vboxsync
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 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PRTUTF16 pwszCmdLine = supR3HardNtChildConstructCmdLine(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'",
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlGetLastWin32Error(), pwszCmdLine);
8302394f164acb4adb187954f6ac8ef7a9efa629vboxsync supR3HardenedWinDisableThreadCreation();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync SUP_DPRINTF(("supR3HardenedWinDoReSpawn(%d): New child %x.%x [kernel32].\n",
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync iWhich, ProcessInfoW32.dwProcessId, ProcessInfoW32.dwThreadId));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hProcess = ProcessInfoW32.hProcess;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.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;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildConstructCmdLine(&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
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hProcess = ProcessInfoNt.ProcessHandle;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.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
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync * supR3HardenedWinInit.) This may fail with STATUS_ACCESS_DENIED and
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync * maybe other errors.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtSetInformationThread(This.hThread, ThreadHideFromDebugger, NULL, 0);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (!NT_SUCCESS(rcNt))
09af8164395ce22610792b5097e2b6ba3a63ac78vboxsync SUP_DPRINTF(("supR3HardenedWinReSpawn: NtSetInformationThread/ThreadHideFromDebugger failed: %#x (harmless)\n", rcNt);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
b2560fc359a998cb1002e5de6eba0ef716d48803vboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Perform very early child initialization.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildGatherData(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildScrewUpPebForInitialImageEvents(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildSetUpChildInit(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync ULONG cSuspendCount = 0;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtResumeThread(This.hThread, &cSuspendCount);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(&This, "supR3HardenedWinDoReSpawn", rcNt, "NtResumeThread failed: %#x", rcNt);
edde275acba04aca58db4172a163741e3abadfbcvboxsync
edde275acba04aca58db4172a163741e3abadfbcvboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Santizie the pre-NTDLL child when it's ready.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * AV software and other things injecting themselves into the embryonic
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * and budding process to intercept API calls and what not. Unfortunately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * this is also the behavior of viruses, malware and other unfriendly
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * software, so we won't stand for it. AV software can scan our image
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * as they are loaded via kernel hooks, that's sufficient. No need for
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * patching half of NTDLL or messing with the import table of the
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * process executable.
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_PurifyChildAndCloseHandles, 2000 /*ms*/, "PurifyChildAndCloseHandles");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildPurify(&This);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildSanitizePeb(&This);
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 */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildCloseFullAccessHandles(&This);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Signal the child that we've closed the unrestricted handles and it can
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * safely try open the driver.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = NtSetEvent(This.hEvtChild, NULL);
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (!NT_SUCCESS(rcNt))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinKillChild(&This, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync "NtSetEvent failed on child process handle: %#x\n", rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync /*
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync * Ditch the loader cache so we don't sit on too much memory while waiting.
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync */
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync supR3HardenedWinFlushLoaderCache();
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync supR3HardenedWinCompactHeaps();
bfc39c8324b2a90c8cb3fedf883495d1ed92e724vboxsync
71e448b6623e801f76cb68355a28500169de5695vboxsync /*
71e448b6623e801f76cb68355a28500169de5695vboxsync * Enable thread creation at this point so Ctrl-C and Ctrl-Break can be processed.
71e448b6623e801f76cb68355a28500169de5695vboxsync */
71e448b6623e801f76cb68355a28500169de5695vboxsync supR3HardenedWinEnableThreadCreation();
71e448b6623e801f76cb68355a28500169de5695vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the child to get to suplibHardenedWindowsMain so we can close the handles.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_CloseEvents, 60000 /*ms*/, "CloseEvents");
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtClose(This.hEvtChild);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtClose(This.hEvtParent);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hEvtChild = NULL;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync This.hEvtParent = NULL;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Wait for the process to terminate.
3c520cf6887d9039d9aa7cf3bbe81fd7de1ffd4cvboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardNtChildWaitFor(&This, kSupR3WinChildReq_End, RT_INDEFINITE_WAIT, "the end");
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(false); /* We're not supposed to get here! */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync/**
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Logs the content of the given object directory.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync *
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @returns true if it exists, false if not.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * @param pszDir The path of the directory to log (ASCII).
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsyncstatic void supR3HardenedWinLogObjDir(const char *pszDir)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync{
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Open the driver object directory.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync RTUTF16 wszDir[128];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync int rc = RTUtf16CopyAscii(wszDir, RT_ELEMENTS(wszDir), pszDir);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (RT_FAILURE(rc))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: RTUtf16CopyAscii -> %Rrc on '%s'\n", rc, pszDir));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync return;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync UNICODE_STRING NtDirName;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtDirName.Buffer = (WCHAR *)wszDir;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtDirName.Length = (USHORT)(RTUtf16Len(wszDir) * sizeof(WCHAR));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtDirName.MaximumLength = NtDirName.Length + sizeof(WCHAR);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync OBJECT_ATTRIBUTES ObjAttr;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync HANDLE hDir;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: %ls => %#x\n", wszDir, rcNt));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (!NT_SUCCESS(rcNt))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync return;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Enumerate it, looking for the driver.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync ULONG uObjDirCtx = 0;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync for (;;)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync uint32_t abBuffer[_64K + _1K];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync ULONG cbActual;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync rcNt = NtQueryDirectoryObject(hDir,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync abBuffer,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync FALSE /*ReturnSingleEntry */,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync FALSE /*RestartScan*/,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync &uObjDirCtx,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync &cbActual);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("supR3HardenedWinLogObjDir: NtQueryDirectoryObject => rcNt=%#x cbActual=%#x\n", rcNt, cbActual));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync break;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync while (pObjDir->Name.Length != 0)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF((" %.*ls %.*ls\n",
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->TypeName.Length / sizeof(WCHAR), pObjDir->TypeName.Buffer,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir->Name.Length / sizeof(WCHAR), pObjDir->Name.Buffer));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Next directory entry. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync pObjDir++;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Clean up and return.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync NtClose(hDir);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync}
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
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{
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (g_fSupStubOpened)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync return;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync
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";
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t const uMsTsStart = supR3HardenedWinGetMilliTS();
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;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (iTry > 0 && supR3HardenedWinGetMilliTS() - uMsTsStart > 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
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (NT_SUCCESS(rcNt))
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync g_fSupStubOpened = true;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Report trouble (fatal). For some errors codes we try gather some
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * extra information that goes into VBoxStartup.log so that we stand a
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * better chance resolving the issue.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
40839c441cb305d84420565f7ca25403d8177413vboxsync int rc = VERR_OPEN_FAILED;
40839c441cb305d84420565f7ca25403d8177413vboxsync if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
40839c441cb305d84420565f7ca25403d8177413vboxsync rc = SUP_NT_STATUS_TO_VBOX(rcNt);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * \Windows\ApiPort open trouble. So far only
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * STATUS_OBJECT_TYPE_MISMATCH has been observed.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (rc == VERR_SUPDRV_APIPORT_OPEN_ERROR)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync uint32_t uSessionId = NtCurrentPeb()->SessionId;
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF((" SessionID=%#x\n", uSessionId));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync char szDir[64];
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (uSessionId == 0)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync RTStrCopy(szDir, sizeof(szDir), "\\Windows");
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync else
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync RTStrPrintf(szDir, sizeof(szDir), "\\Sessions\\%u\\Windows", uSessionId);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedWinLogObjDir(szDir);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedWinLogObjDir("\\Windows");
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedWinLogObjDir("\\Sessions");
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Misc, rc,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: VERR_SUPDRV_APIPORT_OPEN_ERROR\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Error getting %s\\ApiPort in the driver from vboxdrv.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Could be due to security software is redirecting access to it, so please include full "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "details of such software in a bug report. VBoxStartup.log may contain details important "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "to resolving the issue."
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync , s_wszName, szDir);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Generic VBox failure message.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, rc,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %Rrc (rcNt=%#x)\n", s_wszName, rc, rcNt);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
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 }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /*
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * Problems opening the device is generally due to driver load/
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * unload issues. Check whether the driver is loaded and make
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync * suggestions accordingly.
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync/** @todo don't fail during early init, wait till later and try load the driver if missing or at least query the service manager for additional information. */
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if ( rcNt == STATUS_NO_SUCH_DEVICE
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync || rcNt == STATUS_OBJECT_NAME_NOT_FOUND)
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync {
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync SUP_DPRINTF(("Error opening VBoxDrvStub: %s\n", pszDefine));
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync if (supR3HardenedWinDriverExists("VBoxDrv"))
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Driver is probably stuck stopping/starting. Try 'sc.exe query vboxdrv' to get more "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "information about its state. Rebooting may actually help.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync , s_wszName, rcNt, pszDefine, iTry);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync else
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "Driver is does not appear to be loaded. Try 'sc.exe start vboxdrv', reinstall "
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync "VirtualBox or reboot.\n"
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync , s_wszName, rcNt, pszDefine, iTry);
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync }
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync
681f9c8332e6b5a57c59e898d1edcc150423223dvboxsync /* Generic NT failure message. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Driver, VERR_OPEN_FAILED,
4221c34ed2180fbc3a82504145c4a66c589e9e6avboxsync "NtCreateFile(%ls) failed: %#x%s (%u retries)\n", s_wszName, rcNt, pszDefine, iTry);
b4ac1123bab63c58a3323bc1eb96dc7fde868aafvboxsync }
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
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * support driver via /Devices/VBoxDrvStub. (We tried to do this
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * during the early init, but in case we had trouble accessing vboxdrv we
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * retry it here where we have kernel32.dll and others to pull in for
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * better diagnostics.)
edde275acba04aca58db4172a163741e3abadfbcvboxsync */
edde275acba04aca58db4172a163741e3abadfbcvboxsync if (iWhich == 2)
edde275acba04aca58db4172a163741e3abadfbcvboxsync supR3HardenedWinOpenStubDevice();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync /*
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * Make sure we're alone in the stub process before creating the VM process
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync * and that there isn't any debuggers attached.
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync */
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync if (iWhich == 2)
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync {
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync int rc = supHardNtVpDebugger(NtCurrentProcess(), RTErrInfoInitStatic(&g_ErrInfoStatic));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync if (RT_SUCCESS(rc))
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync rc = supHardNtVpThread(NtCurrentProcess(), NtCurrentThread(), RTErrInfoInitStatic(&g_ErrInfoStatic));
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync if (RT_FAILURE(rc))
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync supR3HardenedFatalMsg("supR3HardenedWinReSpawn", kSupInitOp_Integrity, rc, "%s", g_ErrInfoStatic.szMsg);
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync }
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync
5b6c1ebab7273734a475e2e3b850b16ccbdf788cvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Respawn the process with kernel protection for the new process.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinDoReSpawn(iWhich);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUPR3HARDENED_ASSERT(false); /* We're not supposed to get here! */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return RTEXITCODE_FAILURE;
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/**
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Initializes the windows verficiation bits and other things we're better off
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * doing after main() has passed on it's data.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags The main flags.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param fAvastKludge Whether to apply the avast kludge.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsyncDECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
96d40ac897d5f0fd08ee7112800b4beab249179evboxsync NTSTATUS rcNt;
96d40ac897d5f0fd08ee7112800b4beab249179evboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Install a anti debugging hack before we continue. This prevents most
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * notifications from ending up in the debugger. (Also applied to the
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * child process when respawning.)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (!NT_SUCCESS(rcNt))
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync#endif
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Init the verifier.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
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
9f997e760f610c92e3a365be21ead6972bc46130vboxsync /*
9f997e760f610c92e3a365be21ead6972bc46130vboxsync * Get the windows system directory from the KnownDlls dir.
9f997e760f610c92e3a365be21ead6972bc46130vboxsync */
9f997e760f610c92e3a365be21ead6972bc46130vboxsync HANDLE hSymlink = INVALID_HANDLE_VALUE;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync UNICODE_STRING UniStr = RTNT_CONSTANT_UNISTR(L"\\KnownDlls\\KnownDllPath");
9f997e760f610c92e3a365be21ead6972bc46130vboxsync OBJECT_ATTRIBUTES ObjAttrs;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync InitializeObjectAttributes(&ObjAttrs, &UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
96d40ac897d5f0fd08ee7112800b4beab249179evboxsync rcNt = NtOpenSymbolicLinkObject(&hSymlink, SYMBOLIC_LINK_QUERY, &ObjAttrs);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error opening '%ls': %#x", UniStr.Buffer, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.Buffer = g_System32WinPath.awcBuffer;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.Length = 0;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.MaximumLength = sizeof(g_System32WinPath.awcBuffer) - sizeof(RTUTF16);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = NtQuerySymbolicLinkObject(hSymlink, &g_System32WinPath.UniStr, NULL);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (!NT_SUCCESS(rcNt))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, rcNt, "Error querying '%ls': %#x", UniStr.Buffer, rcNt);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync g_System32WinPath.UniStr.Buffer[g_System32WinPath.UniStr.Length / sizeof(RTUTF16)] = '\0';
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync SUP_DPRINTF(("KnownDllPath: %ls\n", g_System32WinPath.UniStr.Buffer));
9f997e760f610c92e3a365be21ead6972bc46130vboxsync NtClose(hSymlink);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
693b87e00c4a89605b2f8d8ab443414186aeaa06vboxsync if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (fAvastKludge)
5de281ea9954eecffbd1ba604603cc8e8347e700vboxsync {
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Do a self purification to cure avast's weird NtOpenFile write-thru
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * change in GetBinaryTypeW change in kernel32. Unfortunately, avast
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * uses a system thread to perform the process modifications, which
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * means it's hard to make sure it had the chance to make them...
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync *
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * We have to resort to kludge doing yield and sleep fudging for a
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * number of milliseconds and schedulings before we can hope that avast
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * and similar products have done what they need to do. If we do any
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * fixes, we wait for a while again and redo it until we're clean.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync *
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * This is unfortunately kind of fragile.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync uint32_t cMsFudge = g_fSupAdversaries ? 512 : 128;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync uint32_t cFixes;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync for (uint32_t iLoop = 0; iLoop < 16; iLoop++)
e352c25b01398e5503235fed02436cb2992f1021vboxsync {
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint32_t cSleeps = 0;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync do
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync {
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtYieldExecution();
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync LARGE_INTEGER Time;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtDelayExecution(FALSE, &Time);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync cSleeps++;
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync } while ( supR3HardenedWinGetMilliTS() - uMsTsStart <= cMsFudge
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync || cSleeps < 8);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n",
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync iLoop, supR3HardenedWinGetMilliTS() - uMsTsStart, cSleeps));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync cFixes = 0;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync &cFixes, NULL /*pErrInfo*/);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (RT_FAILURE(rc) || cFixes == 0)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync break;
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (!g_fSupAdversaries)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_fSupAdversaries |= SUPHARDNT_ADVERSARY_UNKNOWN;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync cMsFudge = 512;
85f99ad10a7b126cf312171061d363fe56302bdavboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /* Log the KiOpPrefetchPatchCount value if available, hoping it might sched some light on spider38's case. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync ULONG cPatchCount = 0;
9f997e760f610c92e3a365be21ead6972bc46130vboxsync rcNt = NtQuerySystemInformation(SystemInformation_KiOpPrefetchPatchCount,
9f997e760f610c92e3a365be21ead6972bc46130vboxsync &cPatchCount, sizeof(cPatchCount), NULL);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (NT_SUCCESS(rcNt))
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x cPatchCount=%#u\n",
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync cFixes, g_fSupAdversaries, cPatchCount));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync else
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUP_DPRINTF(("supR3HardenedWinInit: cFixes=%u g_fSupAdversaries=%#x\n", cFixes, g_fSupAdversaries));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync }
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync }
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;
30f07af559efcbd967e801903746fc21f81ee533vboxsync char **papszArgs = (char **)RTMemAllocZ(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;
30f07af559efcbd967e801903746fc21f81ee533vboxsync papszArgs = (char **)RTMemRealloc(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
100b161379af7255c69e27587cc746e5f76ff050vboxsync/**
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Logs information about a file from a protection product or from Windows.
100b161379af7255c69e27587cc746e5f76ff050vboxsync *
100b161379af7255c69e27587cc746e5f76ff050vboxsync * The purpose here is to better see which version of the product is installed
100b161379af7255c69e27587cc746e5f76ff050vboxsync * and not needing to depend on the user supplying the correct information.
100b161379af7255c69e27587cc746e5f76ff050vboxsync *
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @param pwszFile The NT path to the file.
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * @param fAdversarial Set if from a protection product, false if
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * system file.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
85f99ad10a7b126cf312171061d363fe56302bdavboxsyncstatic void supR3HardenedLogFileInfo(PCRTUTF16 pwszFile, bool fAdversarial)
100b161379af7255c69e27587cc746e5f76ff050vboxsync{
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Open the file.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UNICODE_STRING UniStrName;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Buffer = (WCHAR *)pwszFile;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Length = (USHORT)(RTUtf16Len(pwszFile) * sizeof(WCHAR));
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
100b161379af7255c69e27587cc746e5f76ff050vboxsync OBJECT_ATTRIBUTES ObjAttr;
100b161379af7255c69e27587cc746e5f76ff050vboxsync InitializeObjectAttributes(&ObjAttr, &UniStrName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
100b161379af7255c69e27587cc746e5f76ff050vboxsync GENERIC_READ,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &ObjAttr,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &Ios,
100b161379af7255c69e27587cc746e5f76ff050vboxsync NULL /* Allocation Size*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_ATTRIBUTE_NORMAL,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_SHARE_READ,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_OPEN,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_NON_DIRECTORY_FILE,
100b161379af7255c69e27587cc746e5f76ff050vboxsync NULL /*EaBuffer*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync 0 /*EaLength*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt))
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = Ios.Status;
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("%ls:\n", pwszFile));
100b161379af7255c69e27587cc746e5f76ff050vboxsync union
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint64_t u64AlignmentInsurance;
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_BASIC_INFORMATION BasicInfo;
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_STANDARD_INFORMATION StdInfo;
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint8_t abBuf[32768];
100b161379af7255c69e27587cc746e5f76ff050vboxsync RTUTF16 awcBuf[16384];
100b161379af7255c69e27587cc746e5f76ff050vboxsync IMAGE_DOS_HEADER MzHdr;
100b161379af7255c69e27587cc746e5f76ff050vboxsync } u;
100b161379af7255c69e27587cc746e5f76ff050vboxsync RTTIMESPEC TimeSpec;
100b161379af7255c69e27587cc746e5f76ff050vboxsync char szTmp[64];
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Print basic file information available via NtQueryInformationFile.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.BasicInfo, sizeof(u.BasicInfo), FileBasicInformation);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" CreationTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.CreationTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*SUP_DPRINTF((" LastAccessTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastAccessTime.QuadPart), szTmp, sizeof(szTmp))));*/
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" LastWriteTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.LastWriteTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" ChangeTime: %s\n", RTTimeSpecToString(RTTimeSpecSetNtTime(&TimeSpec, u.BasicInfo.ChangeTime.QuadPart), szTmp, sizeof(szTmp))));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileAttributes: %#x\n", u.BasicInfo.FileAttributes));
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileBasicInformation -> %#x %#x\n", rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &u.StdInfo, sizeof(u.StdInfo), FileStandardInformation);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Size: %#llx\n", u.StdInfo.EndOfFile.QuadPart));
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" FileStandardInformation -> %#x %#x\n", rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Read the image header and extract the timestamp and other useful info.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync RT_ZERO(u);
100b161379af7255c69e27587cc746e5f76ff050vboxsync LARGE_INTEGER offRead;
100b161379af7255c69e27587cc746e5f76ff050vboxsync offRead.QuadPart = 0;
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &u, (ULONG)sizeof(u), &offRead, NULL);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint32_t offNtHdrs = 0;
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (u.MzHdr.e_magic == IMAGE_DOS_SIGNATURE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync offNtHdrs = u.MzHdr.e_lfanew;
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (offNtHdrs < sizeof(u) - sizeof(IMAGE_NT_HEADERS))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_NT_HEADERS64 pNtHdrs64 = (PIMAGE_NT_HEADERS64)&u.abBuf[offNtHdrs];
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_NT_HEADERS32 pNtHdrs32 = (PIMAGE_NT_HEADERS32)&u.abBuf[offNtHdrs];
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (pNtHdrs64->Signature == IMAGE_NT_SIGNATURE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" NT Headers: %#x\n", offNtHdrs));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Machine: %#x%s\n", pNtHdrs64->FileHeader.Machine,
100b161379af7255c69e27587cc746e5f76ff050vboxsync pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ? " - i386"
100b161379af7255c69e27587cc746e5f76ff050vboxsync : pNtHdrs64->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ? " - amd64" : ""));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Timestamp: %#x\n", pNtHdrs64->FileHeader.TimeDateStamp));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Image Version: %u.%u\n",
100b161379af7255c69e27587cc746e5f76ff050vboxsync pNtHdrs64->OptionalHeader.MajorImageVersion, pNtHdrs64->OptionalHeader.MinorImageVersion));
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" SizeOfImage: %#x (%u)\n", pNtHdrs64->OptionalHeader.SizeOfImage, pNtHdrs64->OptionalHeader.SizeOfImage));
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Very crude way to extract info from the file version resource.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync PIMAGE_SECTION_HEADER paSectHdrs = (PIMAGE_SECTION_HEADER)( (uintptr_t)&pNtHdrs64->OptionalHeader
100b161379af7255c69e27587cc746e5f76ff050vboxsync + pNtHdrs64->FileHeader.SizeOfOptionalHeader);
100b161379af7255c69e27587cc746e5f76ff050vboxsync IMAGE_DATA_DIRECTORY RsrcDir = { 0, 0 };
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)
100b161379af7255c69e27587cc746e5f76ff050vboxsync && pNtHdrs64->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync RsrcDir = pNtHdrs64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
100b161379af7255c69e27587cc746e5f76ff050vboxsync else if ( pNtHdrs64->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
100b161379af7255c69e27587cc746e5f76ff050vboxsync && pNtHdrs32->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE)
100b161379af7255c69e27587cc746e5f76ff050vboxsync RsrcDir = pNtHdrs32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Resource Dir: %#x LB %#x\n", RsrcDir.VirtualAddress, RsrcDir.Size));
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( RsrcDir.VirtualAddress > offNtHdrs
100b161379af7255c69e27587cc746e5f76ff050vboxsync && RsrcDir.Size > 0
100b161379af7255c69e27587cc746e5f76ff050vboxsync && (uintptr_t)&u + sizeof(u) - (uintptr_t)paSectHdrs
100b161379af7255c69e27587cc746e5f76ff050vboxsync >= pNtHdrs64->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) )
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync offRead.QuadPart = 0;
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < pNtHdrs64->FileHeader.NumberOfSections; i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress < paSectHdrs[i].SizeOfRawData
100b161379af7255c69e27587cc746e5f76ff050vboxsync && paSectHdrs[i].PointerToRawData > offNtHdrs)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync offRead.QuadPart = paSectHdrs[i].PointerToRawData
100b161379af7255c69e27587cc746e5f76ff050vboxsync + (paSectHdrs[i].VirtualAddress - RsrcDir.VirtualAddress);
100b161379af7255c69e27587cc746e5f76ff050vboxsync break;
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (offRead.QuadPart > 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync RT_ZERO(u);
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtReadFile(hFile, NULL /*hEvent*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, &Ios,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &u, (ULONG)sizeof(u), &offRead, NULL);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct { PCRTUTF16 pwsz; size_t cb; } s_abFields[] =
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync#define MY_WIDE_STR_TUPLE(a_sz) { L ## a_sz, sizeof(L ## a_sz) - sizeof(RTUTF16) }
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("ProductName"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("ProductVersion"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("FileVersion"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("SpecialBuild"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("PrivateBuild"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync MY_WIDE_STR_TUPLE("FileDescription"),
100b161379af7255c69e27587cc746e5f76ff050vboxsync#undef MY_WIDE_STR_TUPLE
100b161379af7255c69e27587cc746e5f76ff050vboxsync };
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_abFields); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcLeft = (sizeof(u) - s_abFields[i].cb - 10) / sizeof(RTUTF16);
100b161379af7255c69e27587cc746e5f76ff050vboxsync PCRTUTF16 pwc = u.awcBuf;
100b161379af7255c69e27587cc746e5f76ff050vboxsync RTUTF16 const wcFirst = *s_abFields[i].pwsz;
100b161379af7255c69e27587cc746e5f76ff050vboxsync while (cwcLeft-- > 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync if ( pwc[0] == 1 /* wType == text */
100b161379af7255c69e27587cc746e5f76ff050vboxsync && pwc[1] == wcFirst)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (memcmp(pwc + 1, s_abFields[i].pwsz, s_abFields[i].cb + sizeof(RTUTF16)) == 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync size_t cwcField = s_abFields[i].cb / sizeof(RTUTF16);
100b161379af7255c69e27587cc746e5f76ff050vboxsync pwc += cwcField + 2;
100b161379af7255c69e27587cc746e5f76ff050vboxsync cwcLeft -= cwcField + 2;
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t iPadding = 0; iPadding < 3; iPadding++, pwc++, cwcLeft--)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (*pwc)
100b161379af7255c69e27587cc746e5f76ff050vboxsync break;
100b161379af7255c69e27587cc746e5f76ff050vboxsync int rc = RTUtf16ValidateEncodingEx(pwc, cwcLeft,
100b161379af7255c69e27587cc746e5f76ff050vboxsync RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (RT_SUCCESS(rc))
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" %ls:%*s %ls",
100b161379af7255c69e27587cc746e5f76ff050vboxsync s_abFields[i].pwsz, cwcField < 15 ? 15 - cwcField : 0, "", pwc));
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" %ls:%*s rc=%Rrc",
100b161379af7255c69e27587cc746e5f76ff050vboxsync s_abFields[i].pwsz, cwcField < 15 ? 15 - cwcField : 0, "", rc));
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync break;
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync pwc++;
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" NtReadFile @%#llx -> %#x %#x\n", offRead.QuadPart, rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Resource section not found.\n"));
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Nt Headers @%#x: Invalid signature\n", offNtHdrs));
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" Nt Headers @%#x: out side buffer\n", offNtHdrs));
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF((" NtReadFile @0 -> %#x %#x\n", rcNt, Ios.Status));
100b161379af7255c69e27587cc746e5f76ff050vboxsync NtClose(hFile);
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync}
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync/**
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * Scans the Driver directory for drivers which may invade our processes.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync *
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * @returns Mask of SUPHARDNT_ADVERSARY_XXX flags.
100b161379af7255c69e27587cc746e5f76ff050vboxsync *
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @remarks The enumeration of \Driver normally requires administrator
100b161379af7255c69e27587cc746e5f76ff050vboxsync * privileges. So, the detection we're doing here isn't always gonna
100b161379af7255c69e27587cc746e5f76ff050vboxsync * work just based on that.
100b161379af7255c69e27587cc746e5f76ff050vboxsync *
100b161379af7255c69e27587cc746e5f76ff050vboxsync * @todo Find drivers in \FileSystems as well, then we could detect VrNsdDrv
100b161379af7255c69e27587cc746e5f76ff050vboxsync * from ViRobot APT Shield 2.0.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsyncstatic uint32_t supR3HardenedWinFindAdversaries(void)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync{
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint32_t fAdversary;
100b161379af7255c69e27587cc746e5f76ff050vboxsync const char *pszDriver;
100b161379af7255c69e27587cc746e5f76ff050vboxsync } s_aDrivers[] =
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, "SRTSPX" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, "SymDS" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, "SymEvent" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, "SymIRON" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, "SymNetS" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswHwid" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswMonFlt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswRdr2" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswRvrt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswSnx" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswsp" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswStm" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, "aswVmm" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmcomm" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmactmon" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmevtmgr" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmtdi" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmebc64" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmeevw" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, "tmciesc" }, /* Titanium internet security, not officescan. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "cfwids" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "McPvDrv" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfeapfk" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfeavfk" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfefirek" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfehidk" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfencbdc" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, "mfewfpk" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "kl1" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "klflt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "klif" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "KLIM6" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "klkbdflt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "klmouflt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "kltdi" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, "kneps" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "MBAMWebAccessControl" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "mbam" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "mbamchameleon" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "mwav" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, "mbamswissarmy" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, "avgfwfd" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, "avgtdia" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINAflt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINFile" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINKNC" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINProc" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINProt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSINReg" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "PSKMAD" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSAlpc" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSHttp" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNShttps" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSIds" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSNAHSL" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSpicc" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSPihsw" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSPop3" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSProt" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSPrv" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSSmtp" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNSStrm" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, "NNStlsc" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MSE, "NisDrv" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync
a6c871653045073d6ef74d0589de345ae62b607dvboxsync /*{ SUPHARDNT_ADVERSARY_COMODO, "cmdguard" }, file system */
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, "inspect" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, "cmdHlp" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync };
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync static const struct
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint32_t fAdversary;
100b161379af7255c69e27587cc746e5f76ff050vboxsync PCRTUTF16 pwszFile;
100b161379af7255c69e27587cc746e5f76ff050vboxsync } s_aFiles[] =
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\SysPlant.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\sysfer.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\sysferThunk.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\ccsetx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\ironx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\srtsp64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\srtspx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symds64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symefa64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symelam.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\N360x64\\1505000.013\\symnets.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_SYMANTEC_N360, L"\\SystemRoot\\System32\\drivers\\symevent64x86.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswHwid.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswMonFlt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswRdr2.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswRvrt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswSnx.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswsp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswStm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVAST, L"\\SystemRoot\\System32\\drivers\\aswVmm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmcomm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmactmon.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmevtmgr.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmtdi.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmebc64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmeevw.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_TRENDMICRO, L"\\SystemRoot\\System32\\drivers\\tmciesc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\cfwids.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\McPvDrv.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfeapfk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfeavfk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfefirek.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfehidk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfencbdc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MCAFEE, L"\\SystemRoot\\System32\\drivers\\mfewfpk.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kl1.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klif.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klim6.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klkbdflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\klmouflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kltdi.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\drivers\\kneps.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_KASPERSKY, L"\\SystemRoot\\System32\\klfphc.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\MBAMSwissArmy.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mwac.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mbamchameleon.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MBAM, L"\\SystemRoot\\System32\\drivers\\mbam.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgrkx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgmfx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsdrivera.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgidsha.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgtdia.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgloga.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgldx64.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_AVG, L"\\SystemRoot\\System32\\drivers\\avgdiska.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINAflt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINFile.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINKNC.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINProc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINProt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSINReg.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\PSKMAD.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSAlpc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSHttp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNShttps.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSIds.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSNAHSL.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSpicc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPihsw.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPop3.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSProt.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSPrv.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSSmtp.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNSStrm.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_PANDA, L"\\SystemRoot\\System32\\drivers\\NNStlsc.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MSE, L"\\SystemRoot\\System32\\drivers\\MpFilter.sys" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync { SUPHARDNT_ADVERSARY_MSE, L"\\SystemRoot\\System32\\drivers\\NisDrvWFP.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdguard.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmderd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\inspect.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cmdhlp.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\cfrmd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\drivers\\hmd.sys" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\guard64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdvrt64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdkbd64.dll" },
a6c871653045073d6ef74d0589de345ae62b607dvboxsync { SUPHARDNT_ADVERSARY_COMODO, L"\\SystemRoot\\System32\\cmdcsr.dll" },
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync { SUPHARDNT_ADVERSARY_ZONE_ALARM, L"\\SystemRoot\\System32\\drivers\\vsdatant.sys" },
55f0ad00baf08057a3d6087ca698d4fd86e7b4a7vboxsync { SUPHARDNT_ADVERSARY_ZONE_ALARM, L"\\SystemRoot\\System32\\AntiTheftCredentialProvider.dll" },
100b161379af7255c69e27587cc746e5f76ff050vboxsync };
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint32_t fFound = 0;
100b161379af7255c69e27587cc746e5f76ff050vboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync /*
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync * Open the driver object directory.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync UNICODE_STRING NtDirName = RTNT_CONSTANT_UNISTR(L"\\Driver");
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync OBJECT_ATTRIBUTES ObjAttr;
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync HANDLE hDir;
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | FILE_LIST_DIRECTORY, &ObjAttr);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync#ifdef VBOX_STRICT
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(rcNt);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync#endif
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt))
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Enumerate it, looking for the driver.
100b161379af7255c69e27587cc746e5f76ff050vboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync ULONG uObjDirCtx = 0;
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (;;)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync uint32_t abBuffer[_64K + _1K];
100b161379af7255c69e27587cc746e5f76ff050vboxsync ULONG cbActual;
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtQueryDirectoryObject(hDir,
100b161379af7255c69e27587cc746e5f76ff050vboxsync abBuffer,
100b161379af7255c69e27587cc746e5f76ff050vboxsync sizeof(abBuffer) - 4, /* minus four for string terminator space. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync FALSE /*ReturnSingleEntry */,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FALSE /*RestartScan*/,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &uObjDirCtx,
100b161379af7255c69e27587cc746e5f76ff050vboxsync &cbActual);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (!NT_SUCCESS(rcNt) || cbActual < sizeof(OBJECT_DIRECTORY_INFORMATION))
100b161379af7255c69e27587cc746e5f76ff050vboxsync break;
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)abBuffer;
100b161379af7255c69e27587cc746e5f76ff050vboxsync while (pObjDir->Name.Length != 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync WCHAR wcSaved = pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)];
100b161379af7255c69e27587cc746e5f76ff050vboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = '\0';
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aDrivers); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (RTUtf16ICmpAscii(pObjDir->Name.Buffer, s_aDrivers[i].pszDriver) == 0)
100b161379af7255c69e27587cc746e5f76ff050vboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync fFound |= s_aDrivers[i].fAdversary;
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("Found driver %s (%#x)\n", s_aDrivers[i].pszDriver, s_aDrivers[i].fAdversary));
100b161379af7255c69e27587cc746e5f76ff050vboxsync break;
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync pObjDir->Name.Buffer[pObjDir->Name.Length / sizeof(WCHAR)] = wcSaved;
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync /* Next directory entry. */
100b161379af7255c69e27587cc746e5f76ff050vboxsync pObjDir++;
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync
100b161379af7255c69e27587cc746e5f76ff050vboxsync NtClose(hDir);
100b161379af7255c69e27587cc746e5f76ff050vboxsync }
100b161379af7255c69e27587cc746e5f76ff050vboxsync else
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("NtOpenDirectoryObject failed on \\Driver: %#x\n", rcNt));
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Look for files.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aFiles); i++)
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
100b161379af7255c69e27587cc746e5f76ff050vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UNICODE_STRING UniStrName;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Buffer = (WCHAR *)s_aFiles[i].pwszFile;
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.Length = (USHORT)(RTUtf16Len(s_aFiles[i].pwszFile) * sizeof(WCHAR));
100b161379af7255c69e27587cc746e5f76ff050vboxsync UniStrName.MaximumLength = UniStrName.Length + sizeof(WCHAR);
100b161379af7255c69e27587cc746e5f76ff050vboxsync InitializeObjectAttributes(&ObjAttr, &UniStrName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync rcNt = NtCreateFile(&hFile, GENERIC_READ, &ObjAttr, &Ios, NULL /* Allocation Size*/, FILE_ATTRIBUTE_NORMAL,
100b161379af7255c69e27587cc746e5f76ff050vboxsync FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL /*EaBuffer*/, 0 /*EaLength*/);
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync {
100b161379af7255c69e27587cc746e5f76ff050vboxsync fFound |= s_aFiles[i].fAdversary;
100b161379af7255c69e27587cc746e5f76ff050vboxsync NtClose(hFile);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync }
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync }
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync /*
100b161379af7255c69e27587cc746e5f76ff050vboxsync * Log details.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync */
100b161379af7255c69e27587cc746e5f76ff050vboxsync SUP_DPRINTF(("supR3HardenedWinFindAdversaries: %#x\n", fFound));
100b161379af7255c69e27587cc746e5f76ff050vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aFiles); i++)
100b161379af7255c69e27587cc746e5f76ff050vboxsync if (fFound & s_aFiles[i].fAdversary)
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(s_aFiles[i].pwszFile, true /* fAdversarial */);
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync return fFound;
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync}
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
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++;
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED;
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();
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_IMPORTS_RESOLVED;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Notify the parent process that we're probably capable of reporting our
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * own errors.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (g_ProcParams.hEvtParent || g_ProcParams.hEvtChild)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync {
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUPR3HARDENED_ASSERT(g_fSupEarlyProcessInit);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_CloseEvents;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtSetEvent(g_ProcParams.hEvtParent, NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtClose(g_ProcParams.hEvtParent);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtClose(g_ProcParams.hEvtChild);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_ProcParams.hEvtParent = NULL;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_ProcParams.hEvtChild = NULL;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync }
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync else
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUPR3HARDENED_ASSERT(!g_fSupEarlyProcessInit);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
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();
79a6b20f984859d9cc49305172355d6c3901f1c5vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_VERSION_INITIALIZED;
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
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync /*
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Log information about important system files.
85f99ad10a7b126cf312171061d363fe56302bdavboxsync */
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\ntdll.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\kernel32.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\KernelBase.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync supR3HardenedLogFileInfo(L"\\SystemRoot\\System32\\apisetschema.dll", false /* fAdversarial */);
85f99ad10a7b126cf312171061d363fe56302bdavboxsync
85f99ad10a7b126cf312171061d363fe56302bdavboxsync /*
85f99ad10a7b126cf312171061d363fe56302bdavboxsync * Scan the system for adversaries, logging information about them.
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync */
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync g_fSupAdversaries = supR3HardenedWinFindAdversaries();
beed5fc4d17b85d6d05516ae63e6308af82ad96fvboxsync
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)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatalMsg("suplibHardenedWindowsMain", kSupInitOp_Integrity, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "Error opening the executable: %u (%ls).", RtlGetLastWin32Error());
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
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * If we've done early init already, register the DLL load notification
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * callback and reinstall the NtDll patches.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync if (g_fSupEarlyProcessInit)
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync {
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinRegisterDllNotificationCallback();
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync }
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
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
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/**
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Reports an error to the parent process via the process parameter structure.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync *
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * @param pszWhere Where this error occured, if fatal message. NULL
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * if not message.
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * @param enmWhat Which init operation went wrong if fatal
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync * message. kSupInitOp_Invalid if not message.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param rc The status code to report.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param pszFormat The format string.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * @param va The format arguments.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
88d7b87c38cc3800f532139696785e8c96bfd531vboxsyncDECLHIDDEN(void) supR3HardenedWinReportErrorToParent(const char *pszWhere, SUPINITOP enmWhat, int rc,
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync const char *pszFormat, va_list va)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync{
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync if (pszWhere)
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync RTStrCopy(g_ProcParams.szWhere, sizeof(g_ProcParams.szWhere), pszWhere);
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync else
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync g_ProcParams.szWhere[0] = '\0';
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync RTStrPrintfV(g_ProcParams.szErrorMsg, sizeof(g_ProcParams.szErrorMsg), pszFormat, va);
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync g_ProcParams.enmWhat = enmWhat;
88d7b87c38cc3800f532139696785e8c96bfd531vboxsync g_ProcParams.rc = RT_SUCCESS(rc) ? VERR_INTERNAL_ERROR_2 : rc;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_Error;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtClearEvent(g_ProcParams.hEvtChild);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NTSTATUS rcNt = NtSetEvent(g_ProcParams.hEvtParent, NULL);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (NT_SUCCESS(rcNt))
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync {
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync LARGE_INTEGER Timeout;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync Timeout.QuadPart = -300000000; /* 30 second */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NTSTATUS rcNt = NtWaitForSingleObject(g_ProcParams.hEvtChild, FALSE /*Alertable*/, &Timeout);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync }
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync}
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync/**
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * Routine called by the supR3HardenedEarlyProcessInitThunk assembly routine
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * when LdrInitializeThunk is executed in during process initialization.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync *
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * This initializes the Stub and VM processes, hooking NTDLL APIs and opening
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * the device driver before any other DLLs gets loaded into the process. This
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * greately reduces and controls the trusted code base of the process compared
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * to opening the driver from SUPR3HardenedMain. It also avoids issues with so
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * call protection software that is in the habit of patching half of the ntdll
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * and kernel32 APIs in the process, making it almost indistinguishable from
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * software that is up to no good. Once we've opened vboxdrv, the process
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * should be locked down so thighly that only kernel software and csrss can mess
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync * with the process.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsyncDECLASM(uintptr_t) supR3HardenedEarlyProcessInit(void)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync{
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * When the first thread gets here we wait for the parent to continue with
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * the process purifications. The primary thread must execute for image
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * load notifications to trigger, at least in more recent windows versions.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * The old trick of starting a different thread that terminates immediately
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * thus doesn't work.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync *
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We are not allowed to modify any data at this point because it will be
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * reset by the child process purification the parent does when we stop. To
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * sabotage thread creation during purification, and to avoid unnecessary
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * work for the parent, we reset g_ProcParams before signalling the parent
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * here.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (g_enmSupR3HardenedMainState != SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateThread(0, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return 0x22; /* crash */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Retrieve the data we need. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync uintptr_t uNtDllAddr = ASMAtomicXchgPtrT(&g_ProcParams.uNtDllAddr, 0, uintptr_t);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (!RT_VALID_PTR(uNtDllAddr))
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync {
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NtTerminateThread(0, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return 0x23; /* crash */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtChild = g_ProcParams.hEvtChild;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync HANDLE hEvtParent = g_ProcParams.hEvtParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if ( hEvtChild == NULL
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || hEvtChild == RTNT_INVALID_HANDLE_VALUE
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || hEvtParent == NULL
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync || hEvtParent == RTNT_INVALID_HANDLE_VALUE)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync {
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync NtTerminateThread(0, 0);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return 0x24; /* crash */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync }
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Resolve the APIs we need. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PFNNTWAITFORSINGLEOBJECT pfnNtWaitForSingleObject;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync PFNNTSETEVENT pfnNtSetEvent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinGetVeryEarlyImports(uNtDllAddr, &pfnNtWaitForSingleObject, &pfnNtSetEvent);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Signal the parent that we're ready for purification. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync RT_ZERO(g_ProcParams);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_PurifyChildAndCloseHandles;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync NTSTATUS rcNt = pfnNtSetEvent(hEvtParent, NULL);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNt != STATUS_SUCCESS)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return 0x33; /* crash */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /* Wait up to 2 mins for the parent to exorcise evil. */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync LARGE_INTEGER Timeout;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync Timeout.QuadPart = -1200000000; /* 120 second */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rcNt = pfnNtWaitForSingleObject(hEvtChild, FALSE /*Alertable*/, &Timeout);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync if (rcNt != STATUS_SUCCESS)
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync return 0x34; /* crash */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync /*
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * We're good to go, work global state and restore process parameters.
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * Note that we will not restore uNtDllAddr since that is our first defence
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync * against unwanted threads (see above).
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_INIT_CALLED;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_fSupEarlyProcessInit = true;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.hEvtChild = hEvtChild;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.hEvtParent = hEvtParent;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.enmRequest = kSupR3WinChildReq_Error;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync g_ProcParams.rc = VINF_SUCCESS;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Initialize the NTDLL imports that we consider usable before the
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * process has been initialized.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync supR3HardenedWinInitImportsEarly(uNtDllAddr);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_IMPORTS_RESOLVED;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Init g_uNtVerCombined as well as we can at this point.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedWinInitVersion();
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Convert the arguments to UTF-8 so we can open the log file if specified.
b106d14b607bb92c526257461d740a274dce64c9vboxsync * We may have to normalize the pointer on older windows version (not w7/64 +).
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Note! This leaks memory at present.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
b106d14b607bb92c526257461d740a274dce64c9vboxsync PRTL_USER_PROCESS_PARAMETERS pUserProcParams = NtCurrentPeb()->ProcessParameters;
b106d14b607bb92c526257461d740a274dce64c9vboxsync UNICODE_STRING CmdLineStr = pUserProcParams->CommandLine;
b106d14b607bb92c526257461d740a274dce64c9vboxsync if ( CmdLineStr.Buffer != NULL
b106d14b607bb92c526257461d740a274dce64c9vboxsync && !(pUserProcParams->Flags & RTL_USER_PROCESS_PARAMS_FLAG_NORMALIZED) )
b106d14b607bb92c526257461d740a274dce64c9vboxsync CmdLineStr.Buffer = (WCHAR *)((uintptr_t)CmdLineStr.Buffer + (uintptr_t)pUserProcParams);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync int cArgs;
b106d14b607bb92c526257461d740a274dce64c9vboxsync char **papszArgs = suplibCommandLineToArgvWStub(CmdLineStr.Buffer, CmdLineStr.Length / sizeof(WCHAR), &cArgs);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedOpenLog(&cArgs, papszArgs);
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: uNtDllAddr=%p\n", uNtDllAddr));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync /*
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync * Set up the direct system calls so we can more easily hook NtCreateSection.
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync */
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync supR3HardenedWinInitSyscalls(true /*fReportErrors*/);
f81115e612ee8fa2bc082db9d4c8879e33babc5avboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Determine the executable path and name. Will NOT determine the windows style
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * executable path here as we don't need it.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SIZE_T cbActual = 0;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync rcNt = NtQueryVirtualMemory(NtCurrentProcess(), &g_ProcParams, MemorySectionName, &g_SupLibHardenedExeNtPath,
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync sizeof(g_SupLibHardenedExeNtPath) - sizeof(WCHAR), &cbActual);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if ( !NT_SUCCESS(rcNt)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync || g_SupLibHardenedExeNtPath.UniStr.Length == 0
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync || g_SupLibHardenedExeNtPath.UniStr.Length & 1)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("NtQueryVirtualMemory/MemorySectionName failed in supR3HardenedVmProcessInit: %#x\n", rcNt);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /* The NT executable name offset / dir path length. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_offSupLibHardenedExeNtName = g_SupLibHardenedExeNtPath.UniStr.Length / sizeof(WCHAR);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync while ( g_offSupLibHardenedExeNtName > 1
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync && g_SupLibHardenedExeNtPath.UniStr.Buffer[g_offSupLibHardenedExeNtName - 1] != '\\' )
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_offSupLibHardenedExeNtName--;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Initialize the image verification stuff (hooks LdrLoadDll and NtCreateSection).
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedWinInit(0, false /*fAvastKludge*/);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Open the driver.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync {
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv stub...\n"));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync supR3HardenedWinOpenStubDevice();
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync }
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync else if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync {
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n"));
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync supR3HardenedMainOpenDevice();
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync }
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync else
4db69c2a1302fa56bc5dd7181377b9f47cfd875evboxsync supR3HardenedFatal("Unexpected first argument '%s'!\n", papszArgs[0]);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync /*
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * Reinstall the NtDll patches since there is a slight possibility that
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync * someone undid them while we where busy opening the device.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync */
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync supR3HardenedWinReInstallHooks(false /*fFirstCall */);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync /*
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * Restore the LdrInitializeThunk code so we can initialize the process
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync * normally when we return.
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync */
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Restoring LdrInitializeThunk...\n"));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync PSUPHNTLDRCACHEENTRY pLdrEntry;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (RT_FAILURE(rc))
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync uint8_t *pbBits;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbBits, uNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync if (RT_FAILURE(rc))
9f997e760f610c92e3a365be21ead6972bc46130vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
9f997e760f610c92e3a365be21ead6972bc46130vboxsync
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync RTLDRADDR uValue;
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync rc = RTLdrGetSymbolEx(pLdrEntry->hLdrMod, pbBits, uNtDllAddr, UINT32_MAX, "LdrInitializeThunk", &uValue);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync if (RT_FAILURE(rc))
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync supR3HardenedFatal("supR3HardenedVmProcessInit: Failed to find LdrInitializeThunk (%Rrc).\n", rc);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
9f997e760f610c92e3a365be21ead6972bc46130vboxsync PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uValue;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READWRITE));
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync memcpy(pvLdrInitThunk, pbBits + ((uintptr_t)uValue - uNtDllAddr), 16);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pvLdrInitThunk, 16, PAGE_EXECUTE_READ));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync
f20463d06f9bf3f81e2c049c697dcd20a0b0c435vboxsync SUP_DPRINTF(("supR3HardenedVmProcessInit: Returning to LdrInitializeThunk...\n"));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync return (uintptr_t)pvLdrInitThunk;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync}
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync