SUPHardenedVerifyImage-win.cpp revision ad8dba2ed364f757ee03a355a1deee56b9f8066e
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/* $Id$ */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @file
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox Support Library/Driver - Hardened Image Verification, Windows.
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#ifdef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define IPRT_NT_MAP_TO_ZW
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include <iprt/nt/nt.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include <ntimage.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include <iprt/nt/nt-and-windows.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "Wintrust.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "Softpub.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "mscat.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBox/sup.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <VBox/err.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/ctype.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/ldr.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/log.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/path.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/crypto/pkcs7.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/crypto/store.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "SUPDrvInternal.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# include "SUPLibInternal.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include "win/SUPHardenedVerify-win.h"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Defined Constants And Macros *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The size of static hash (output) buffers.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Avoids dynamic allocations and cleanups for of small buffers as well as extra
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * calls for getting the appropriate buffer size. The largest digest in regular
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * use by current windows version is SHA-512, we double this and hope it's
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * enough a good while. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define SUPHARDNTVI_MAX_CAT_HASH_SIZE 128
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(VBOX_PERMIT_EVEN_MORE) && !defined(VBOX_PERMIT_MORE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# error "VBOX_PERMIT_EVEN_MORE without VBOX_PERMIT_MORE!"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Structures and Typedefs *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef LONG (WINAPI * PFNWINVERIFYTRUST)(HWND hwnd, GUID const *pgActionID, PVOID pWVTData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATADMINACQUIRECONTEXT)(HCATADMIN *phCatAdmin, const GUID *pGuidSubsystem, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATADMINACQUIRECONTEXT2)(HCATADMIN *phCatAdmin, const GUID *pGuidSubsystem, PCWSTR pwszHashAlgorithm,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync struct _CERT_STRONG_SIGN_PARA const *pStrongHashPolicy, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE)(HANDLE hFile, DWORD *pcbHash, BYTE *pbHash, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2)(HCATADMIN hCatAdmin, HANDLE hFile, DWORD *pcbHash,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync BYTE *pbHash, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef HCATINFO (WINAPI *PFNCRYPTCATADMINENUMCATALOGFROMHASH)(HCATADMIN hCatAdmin, BYTE *pbHash, DWORD cbHash,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD dwFlags, HCATINFO *phPrevCatInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATADMINRELEASECATALOGCONTEXT)(HCATADMIN hCatAdmin, HCATINFO hCatInfo, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATDADMINRELEASECONTEXT)(HCATADMIN hCatAdmin, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI * PFNCRYPTCATCATALOGINFOFROMCONTEXT)(HCATINFO hCatInfo, CATALOG_INFO *psCatInfo, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef HCERTSTORE (WINAPI *PFNCERTOPENSTORE)(PCSTR pszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD dwFlags, const void *pvParam);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI *PFNCERTCLOSESTORE)(HCERTSTORE hCertStore, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef PCCERT_CONTEXT (WINAPI *PFNCERTENUMCERTIFICATESINSTORE)(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The build certificate. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRX509CERTIFICATE g_BuildX509Cert;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store for root software publisher certificates. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRSTORE g_hSpcRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store for root NT kernel certificates. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRSTORE g_hNtKernelRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store containing SPC, NT kernel signing, and timestamp root certificates. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRSTORE g_hSpcAndNtKernelRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store for supplemental certificates for use with
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * g_hSpcAndNtKernelRootStore. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRSTORE g_hSpcAndNtKernelSuppStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The full \\SystemRoot\\System32 path. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncSUPSYSROOTDIRBUF g_System32NtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The full \\SystemRoot\\WinSxS path. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncSUPSYSROOTDIRBUF g_WinSxSNtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The full 'Program Files' path. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncSUPSYSROOTDIRBUF g_ProgramFilesNtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The full 'Program Files (x86)' path. */
396186df506c303aa6137c1707423855981eb0c2vboxsyncSUPSYSROOTDIRBUF g_ProgramFilesX86NtPath;
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync# endif
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync/** The full 'Common Files' path. */
396186df506c303aa6137c1707423855981eb0c2vboxsyncSUPSYSROOTDIRBUF g_CommonFilesNtPath;
396186df506c303aa6137c1707423855981eb0c2vboxsync# ifdef RT_ARCH_AMD64
396186df506c303aa6137c1707423855981eb0c2vboxsync/** The full 'Common Files (x86)' path. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncSUPSYSROOTDIRBUF g_CommonFilesX86NtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_MORE*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SID Sid;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abPadding[SECURITY_MAX_SID_SIZE];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The TrustedInstaller SID (Vista+). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_TrustedInstallerSid,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Local system ID (S-1-5-21). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_LocalSystemSid,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Builtin Administrators group alias (S-1-5-32-544). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_AdminsGroupSid;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Set after we've retrived other SPC root certificates from the system. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool g_fHaveOtherRoots = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(IN_RING3) && !defined(IN_SUP_HARDENED_R3)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Combined windows NT version number. See SUP_MAKE_NT_VER_COMBINED and
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * SUP_MAKE_NT_VER_SIMPLE. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncuint32_t g_uNtVerCombined;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Timestamp hack working around issues with old DLLs that we ship.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * See supHardenedWinVerifyImageByHandle() for details. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint64_t g_uBuildTimestampHack = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to WinVerifyTrust. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNWINVERIFYTRUST g_pfnWinVerifyTrust;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminAcquireContext. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINACQUIRECONTEXT g_pfnCryptCATAdminAcquireContext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminAcquireContext2 if available. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINACQUIRECONTEXT2 g_pfnCryptCATAdminAcquireContext2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminCalcHashFromFileHandle. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINCALCHASHFROMFILEHANDLE g_pfnCryptCATAdminCalcHashFromFileHandle;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminCalcHashFromFileHandle2. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2 g_pfnCryptCATAdminCalcHashFromFileHandle2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminEnumCatalogFromHash. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINENUMCATALOGFROMHASH g_pfnCryptCATAdminEnumCatalogFromHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminReleaseCatalogContext. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATADMINRELEASECATALOGCONTEXT g_pfnCryptCATAdminReleaseCatalogContext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATAdminReleaseContext. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATDADMINRELEASECONTEXT g_pfnCryptCATAdminReleaseContext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to CryptCATCatalogInfoFromContext. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncPFNCRYPTCATCATALOGINFOFROMCONTEXT g_pfnCryptCATCatalogInfoFromContext;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Where we store the TLS entry for detecting WinVerifyTrustRecursion. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t g_iTlsWinVerifyTrustRecursion = UINT32_MAX;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Fallback WinVerifyTrust recursion protection. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t volatile g_idActiveThread = UINT32_MAX;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrustCatFile(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnRead */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ((ULONG)cb != cb)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_OUT_OF_RANGE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * For some reason I'm getting occational read error in an XP VM with
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * STATUS_FAILED_DRIVER_ENTRY. Redoing the call again works in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * debugger, so try do that automatically.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t iTry = 0;; iTry++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LARGE_INTEGER offNt;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync offNt.QuadPart = off;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtReadFile(pNtViRdr->hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*hEvent*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*ApcRoutine*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*ApcContext*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &Ios,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvBuf,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync (ULONG)cb,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &offNt,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = Ios.Status;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (Ios.Information == cb)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->off = off + cb;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedError(VERR_READ_ERROR, false,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supHardNtViRdrRead: Only got %#zx bytes when requesting %#zx bytes at %#llx in '%s'.\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Ios.Information, off, cb, pNtViRdr->szFilename);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->off = -1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_READ_ERROR;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Delay a little before we retry?
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iTry == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtYieldExecution();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (iTry >= 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync LARGE_INTEGER Time;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Time.QuadPart = -1000000 / 100; /* 1ms in 100ns units, relative time. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtDelayExecution(TRUE, &Time);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Before we give up, we'll try split up the request in case the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * kernel is low on memory or similar. For simplicity reasons, we do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * this in a recursion fashion.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iTry >= 2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cb >= _8K)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t const cbBlock = RT_ALIGN_Z(cb / 4, 512);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cb > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cbThisRead = RT_MIN(cb, cbBlock);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardNtViRdrRead(&pNtViRdr->Core, pvBuf, cbThisRead, off);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync off += cbThisRead;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cb -= cbThisRead;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvBuf = (uint8_t *)pvBuf + cbThisRead;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedError(VERR_READ_ERROR, false, "supHardNtViRdrRead: Error %#x reading %#zx bytes at %#llx in '%s'.\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt, off, cb, pNtViRdr->szFilename);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->off = -1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_READ_ERROR;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnTell */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(RTFOFF) supHardNtViRdrTell(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pNtViRdr->off;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnSize */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(RTFOFF) supHardNtViRdrSize(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pNtViRdr->cbFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnLogName */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(const char *) supHardNtViRdrLogName(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return pNtViRdr->szFilename;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnMap */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrMap(PRTLDRREADER pReader, const void **ppvBits)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_NOT_SUPPORTED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnUnmap */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrUnmap(PRTLDRREADER pReader, const void *pvBits)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_NOT_SUPPORTED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnDestroy */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrDestroy(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pReader;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.uMagic = ~RTLDRREADER_MAGIC;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->hFile = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTMemFree(pNtViRdr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Creates a loader reader instance for the given NT file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns iprt status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile Native NT file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName Optional file name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags Flags, SUPHNTVI_F_XXX.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param ppNtViRdr Where to store the reader instance on success.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Try determine the size of the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_STANDARD_INFORMATION StdInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryInformationFile(hFile, &Ios, &StdInfo, sizeof(StdInfo), FileStandardInformation);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt) || !NT_SUCCESS(Ios.Status))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_LDRVI_FILE_LENGTH_ERROR;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calc the file name length and allocate memory for the reader instance.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cchFilename = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pwszName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchFilename = RTUtf16CalcUtf8Len(pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = VERR_NO_MEMORY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)RTMemAllocZ(sizeof(*pNtViRdr) + cchFilename);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pNtViRdr)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_NO_MEMORY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize the structure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cchFilename)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char *pszName = &pNtViRdr->szFilename[0];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTUtf16ToUtf8Ex(pwszName, RTSTR_MAX, &pszName, cchFilename + 1, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertStmt(RT_SUCCESS(rc), pNtViRdr->szFilename[0] = '\0');
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->szFilename[0] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.uMagic = RTLDRREADER_MAGIC;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnRead = supHardNtViRdrRead;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnTell = supHardNtViRdrTell;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnSize = supHardNtViRdrSize;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnLogName = supHardNtViRdrLogName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnMap = supHardNtViRdrMap;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnUnmap = supHardNtViRdrUnmap;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->Core.pfnDestroy = supHardNtViRdrDestroy;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->hFile = hFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->off = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->cbFile = StdInfo.EndOfFile.QuadPart;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->fFlags = fFlags;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *ppNtViRdr = pNtViRdr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Checks if the file is owned by TrustedInstaller (Vista+) or similar.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if owned by TrustedInstaller of pre-Vista, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The handle to the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName The name of the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(HANDLE hFile, PCRTUTF16 pwszName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined < SUP_NT_VER_VISTA)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the ownership information.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SECURITY_DESCRIPTOR_RELATIVE Rel;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SECURITY_DESCRIPTOR Abs;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abView[256];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } uBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbActual;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQuerySecurityObject(hFile, OWNER_SECURITY_INFORMATION, &uBuf.Abs, sizeof(uBuf), &cbActual);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("NtQuerySecurityObject failed with rcNt=%#x on '%ls'\n", rcNt, pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check the owner.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initially we wished to only allow TrustedInstaller. But a Windows CAPI
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * plugin "Program Files\Tumbleweed\Desktop Validator\tmwdcapiclient.dll"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * turned up owned by the local system user, and we cannot operate without
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the plugin loaded once it's installed (WinVerityTrust fails).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We'd like to avoid allowing Builtin\Administrators here since it's the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * default owner of anything an admin user creates (at least when elevated).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Seems windows update or someone ends up installing or modifying system
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * DLL ownership to this group, so for system32 and winsxs it's unavoidable.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * And, not surprise, a bunch of products, including AV, firewalls and similar
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * ends up with their files installed with this group as owner. For instance
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * if we wish to have NAT continue working, we need to allow this.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Hopefully, we can limit the allowed files to these owners though, so
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * we won't be subject to ordinary (non-admin, or not elevated) users
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * downloading or be tricked into putting evil DLLs around the place...
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSID pOwner = uBuf.Rel.Control & SE_SELF_RELATIVE ? &uBuf.abView[uBuf.Rel.Owner] : uBuf.Abs.Owner;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert((uintptr_t)pOwner - (uintptr_t)&uBuf < sizeof(uBuf) - sizeof(SID));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RtlEqualSid(pOwner, &g_TrustedInstallerSid))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RtlEqualSid(pOwner, &g_LocalSystemSid))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RtlEqualSid(pOwner, &g_AdminsGroupSid))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%ls: Owner is administrators group.\n", pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%ls: Owner is not trusted installer (%.*Rhxs)\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszName, ((uint8_t *)pOwner)[1] /*SubAuthorityCount*/ * sizeof(ULONG) + 8, pOwner));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII path compare.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if equal, false if not.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @param pawcLeft The UTF-16 path string, not necessarily null
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * terminated.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @param cwcLeft The number of chars in the left string,
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * RTSTR_MAX if unknown but terminated.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @param pszRight The ascii string.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsyncDECLHIDDEN(bool) supHardViUtf16PathIsEqualEx(PCRTUTF16 pawcLeft, size_t cwcLeft, const char *pszRight)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync{
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync for (;;)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync RTUTF16 wc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (cwcLeft-- > 0)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc =*pawcLeft++;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync else
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc = 0;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync uint8_t b = *pszRight++;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (b != wc)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc >= 0x80)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc = RT_C_TO_LOWER(wc);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc != b)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync b = RT_C_TO_LOWER(b);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc != b)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc == '/')
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII path compare.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if equal, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszLeft The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszRight The ascii string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supHardViUtf16PathIsEqual(PCRTUTF16 pwszLeft, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return supHardViUtf16PathIsEqualEx(pwszLeft, RTSTR_MAX, pszRight);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII ends-with path predicate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if equal, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszSuffix The ascii suffix string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supHardViUtf16PathEndsWith(PCRTUTF16 pwsz, const char *pszSuffix)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cwc = RTUtf16Len(pwsz);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cchSuffix = strlen(pszSuffix);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwc >= cchSuffix)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return supHardViUtf16PathIsEqual(pwsz + cwc - cchSuffix, pszSuffix);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII starts-with path predicate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if starts with given string, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszPrefix The ascii prefix string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supHardViUtf16PathStartsWithAscii(PCRTUTF16 pwszLeft, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wc = *pwszLeft++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t b = *pszRight++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b != wc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc >= 0x80 || wc == 0)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc = RT_C_TO_LOWER(wc);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc != b)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync b = RT_C_TO_LOWER(b);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc != b)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc == '/')
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync wc = '\\';
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (b == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
76bd4ec6d277af265850cc522ad5c9e89626b259vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if starts with given string, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszLeft The path to check.
76bd4ec6d277af265850cc522ad5c9e89626b259vboxsync * @param cwcLeft The length of @a pwszLeft
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszRight The starts-with path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cwcRight The length of @a pwszRight.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fCheckSlash Check for a slash following the prefix.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(bool) supHardViUtf16PathStartsWithEx(PCRTUTF16 pwszLeft, uint32_t cwcLeft,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTUTF16 pwszRight, uint32_t cwcRight, bool fCheckSlash)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cwcLeft < cwcRight || !cwcRight || !pwszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* See if we can get away with a case sensitive compare first. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (memcmp(pwszLeft, pwszRight, cwcRight * sizeof(RTUTF16)) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszLeft += cwcRight;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* No luck, do a slow case insensitive comapre. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cLeft = cwcRight;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cLeft-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wcLeft = *pwszLeft++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wcRight = *pwszRight++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wcLeft != wcRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wcLeft = wcLeft < 0x80 ? wcLeft == '/' ? '\\' : RT_C_TO_LOWER(wcLeft) : wcLeft;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wcRight = wcRight < 0x80 ? wcRight == '/' ? '\\' : RT_C_TO_LOWER(wcRight) : wcRight;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wcLeft != wcRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Check for slash following the prefix, if request. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !fCheckSlash
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || *pwszLeft == '\\'
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || *pwszLeft == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if starts with given string, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStrLeft The path to check.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pUniStrRight The starts-with path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fCheckSlash Check for a slash following the prefix.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(bool) supHardViUniStrPathStartsWithUniStr(UNICODE_STRING const *pUniStrLeft, UNICODE_STRING const *pUniStrRight,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fCheckSlash)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return supHardViUtf16PathStartsWithEx(pUniStrLeft->Buffer, pUniStrLeft->Length / sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pUniStrRight->Buffer, pUniStrRight->Length / sizeof(WCHAR), fCheckSlash);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Counts slashes in the given UTF-8 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Number of slashes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t supHardViUtf16PathCountSlashes(PCRTUTF16 pwsz)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cSlashes = 0;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync RTUTF16 wc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync while ((wc = *pwsz++) != '\0')
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (wc == '/' || wc == '\\')
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync cSlashes++;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return cSlashes;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync}
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#ifdef VBOX_PERMIT_MORE
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync/**
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * Checks if the path goes into %windir%\apppatch\.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync *
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @returns true if apppatch, false if not.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @param pwszPath The path to examine.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsyncDECLHIDDEN(bool) supHardViIsAppPatchDir(PCRTUTF16 pwszPath, uint32_t cwcName)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync{
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync uint32_t cwcWinDir = (g_System32NtPath.UniStr.Length - sizeof(L"System32")) / sizeof(WCHAR);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (cwcName <= cwcWinDir + sizeof("AppPatch"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (memcmp(pwszPath, g_System32NtPath.UniStr.Buffer, cwcWinDir * sizeof(WCHAR)))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (!supHardViUtf16PathStartsWithAscii(&pwszPath[cwcWinDir], "\\AppPatch\\"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return g_uNtVerCombined >= SUP_NT_VER_VISTA;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# error should not get here..
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Checks if the unsigned DLL is fine or not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VINF_LDRVI_NOT_SIGNED or @a rc.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hLdrMod The loader module handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName The NT name of the DLL/EXE.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags Flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile The file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param rc The status code..
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCheckIfNotSignedOk(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, uint32_t fFlags, HANDLE hFile, int rc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fFlags & (SUPHNTVI_F_REQUIRE_BUILD_CERT | SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Version macros.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t const uNtVer = g_uNtVerCombined;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_XP() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(5, 1) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(5, 2) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_W2K3() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(5, 2) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(5, 3) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_VISTA() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(6, 0) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 1) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_W70() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(6, 1) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 2) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_W80() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(6, 2) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 3) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define IS_W81() ( uNtVer >= SUP_MAKE_NT_VER_SIMPLE(6, 3) && uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The System32 directory.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * System32 is full of unsigned DLLs shipped by microsoft, graphics
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hardware vendors, input device/method vendors and whatnot else that
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * actually needs to be loaded into a process for it to work correctly.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We have to ASSUME that anything our process attempts to load from
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * System32 is trustworthy and that the Windows system with the help of
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * anti-virus software make sure there is nothing evil lurking in System32
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * or being loaded from it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * A small measure of protection is to list DLLs we know should be signed
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and decline loading unsigned versions of them, assuming they have been
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * replaced by an adversary with evil intentions.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTUTF16 pwsz;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cwcName = (uint32_t)RTUtf16Len(pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwsz = pwszName + cwcOther + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Must be owned by trusted installer. (This test is superfuous, thus no relaxation here.) */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Core DLLs. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "ntdll.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_NT_VER_VISTA ? VINF_LDRVI_NOT_SIGNED : rc;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if (supHardViUtf16PathIsEqual(pwsz, "kernel32.dll"))
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if (supHardViUtf16PathIsEqual(pwsz, "kernelbase.dll"))
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync return IS_W80() || IS_W70() ? VINF_LDRVI_NOT_SIGNED : rc;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if (supHardViUtf16PathIsEqual(pwsz, "apisetschema.dll"))
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync return IS_W70() ? VINF_LDRVI_NOT_SIGNED : rc;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if (supHardViUtf16PathIsEqual(pwsz, "apphelp.dll"))
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync#ifdef VBOX_PERMIT_VERIFIER_DLL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "verifier.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef VBOX_PERMIT_MORE
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uNtVer >= SUP_NT_VER_W70) /* hard limit: user32.dll is unwanted prior to w7. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "sfc.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "sfc_os.dll"))
208b6c2dc45ecf098ded011e80eb380698695ee8vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "user32.dll"))
a5d6536233b36d63d25e3127624f1ddb7b59c52bvboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Check that this DLL isn't supposed to be signed on this windows
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync version. If it should, it's likely to be a fake. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo list of signed dlls for various windows versions. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING0 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The WinSxS white list.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Just like with System32 there are potentially a number of DLLs that
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * could be required from WinSxS.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcOther = g_WinSxSNtPath.UniStr.Length / sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_WinSxSNtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwsz = pwszName + cwcOther + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcName -= cwcOther + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The WinSxS layout means everything worth loading is exactly one level down. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cSlashes = supHardViUtf16PathCountSlashes(pwsz);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (cSlashes != 1)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Must be owned by trusted installer. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* !IN_RING0 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef VBOX_PERMIT_MORE
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * AppPatch whitelist.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViIsAppPatchDir(pwszName, cwcName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR); /* ASSUMES System32 is called System32. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwsz = pwszName + cwcOther + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifndef VBOX_PERMIT_EVEN_MORE
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "acres.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AppPatch64\\AcGenral.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# elif defined(RT_ARCH_X86)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AcGenral.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif /* !VBOX_PERMIT_EVEN_MORE */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* VBOX_PERMIT_MORE */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifndef IN_RING0
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# if defined(VBOX_PERMIT_MORE) && !defined(VBOX_PERMIT_EVEN_MORE)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Program files and common files.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Permit anything that's signed and correctly installed.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( supHardViUtf16PathStartsWithEx(pwszName, cwcName,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync g_ProgramFilesNtPath.UniStr.Buffer, g_ProgramFilesNtPath.UniStr.Length,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync true /*fCheckSlash*/)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync g_CommonFilesNtPath.UniStr.Buffer, g_CommonFilesNtPath.UniStr.Length,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync true /*fCheckSlash*/)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# ifdef RT_ARCH_AMD64
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync g_ProgramFilesX86NtPath.UniStr.Buffer, g_ProgramFilesX86NtPath.UniStr.Length,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync true /*fCheckSlash*/)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync g_CommonFilesX86NtPath.UniStr.Buffer, g_CommonFilesX86NtPath.UniStr.Length,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync true /*fCheckSlash*/)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync )
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return rc;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return VINF_LDRVI_NOT_SIGNED;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# elif defined(VBOX_PERMIT_MORE) && defined(VBOX_PERMIT_EVEN_MORE)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Anything that's owned by the trusted installer.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( (fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync || supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return VINF_LDRVI_NOT_SIGNED;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync# endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif /* !IN_RING0 */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Not permitted.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return rc;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync}
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync/**
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Standard code signing. Use this for Microsoft SPC.}
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsyncstatic DECLCALLBACK(int) supHardNtViCertVerifyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync{
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * If there is no certificate path build & validator associated with this
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * callback, it must be because of the build certificate. We trust the
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * build certificate without any second thoughts.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (hCertPaths == NIL_RTCRX509CERTPATHS)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RTCrX509Certificate_Compare(pCert, &g_BuildX509Cert) == 0) /* healthy paranoia */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return VINF_SUCCESS;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_BUILD_CERT_IPE, "Not valid kernel code signature.");
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Standard code signing capabilites required.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, fFlags, NULL, pErrInfo);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( RT_SUCCESS(rc)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * If kernel signing, a valid certificate path must be anchored by the
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * microsoft kernel signing root certificate.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync uint32_t cPaths = RTCrX509CertPathsGetPathCount(hCertPaths);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync uint32_t cFound = 0;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync uint32_t cValid = 0;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync for (uint32_t iPath = 0; iPath < cPaths; iPath++)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync bool fTrusted;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync PCRTCRX509NAME pSubject;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync PCRTCRX509SUBJECTPUBLICKEYINFO pPublicKeyInfo;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rcVerify;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTCrX509CertPathsQueryPathInfo(hCertPaths, iPath, &fTrusted, NULL /*pcNodes*/, &pSubject, &pPublicKeyInfo,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync NULL, NULL /*pCertCtx*/, &rcVerify);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync AssertRCBreak(rc);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rcVerify))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync Assert(fTrusted);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync cValid++;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Search the kernel signing root store for a matching anchor.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync RTCRSTORECERTSEARCH Search;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280(g_hNtKernelRootStore, pSubject, &Search);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync AssertRCBreak(rc);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync PCRTCRCERTCTX pCertCtx;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync while ((pCertCtx = RTCrStoreCertSearchNext(g_hNtKernelRootStore, &Search)) != NULL)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync PCRTCRX509SUBJECTPUBLICKEYINFO pCertPubKeyInfo = NULL;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (pCertCtx->pCert)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync pCertPubKeyInfo = &pCertCtx->pCert->TbsCertificate.SubjectPublicKeyInfo;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync else if (pCertCtx->pTaInfo)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync pCertPubKeyInfo = &pCertCtx->pTaInfo->PubKey;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync else
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync pCertPubKeyInfo = NULL;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( pCertPubKeyInfo
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && RTCrX509SubjectPublicKeyInfo_Compare(pCertPubKeyInfo, pPublicKeyInfo) == 0)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync cFound++;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync RTCrCertCtxRelease(pCertCtx);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc2 = RTCrStoreCertSearchDestroy(g_hNtKernelRootStore, &Search); AssertRC(rc2);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rc) && cFound == 0)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_VALID_KERNEL_CODE_SIGNATURE, "Not valid kernel code signature.");
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rc) && cValid < 2 && g_fHaveOtherRoots)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_UNEXPECTED_VALID_PATH_COUNT,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "Expected at least %u valid paths, not %u.", 2, cValid);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * More requirements? NT5 build lab?
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync void const *pvSignature, size_t cbSignature,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTERRINFO pErrInfo, void *pvUser)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check out the input.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(cbSignature == sizeof(RTCRPKCS7CONTENTINFO), VERR_INTERNAL_ERROR_5);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTCRPKCS7CONTENTINFO pContentInfo = (PCRTCRPKCS7CONTENTINFO)pvSignature;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(RTCrPkcs7ContentInfo_IsSignedData(pContentInfo), VERR_INTERNAL_ERROR_5);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(pContentInfo->u.pSignedData->SignerInfos.cItems == 1, VERR_INTERNAL_ERROR_5);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTCRPKCS7SIGNERINFO pSignerInfo = &pContentInfo->u.pSignedData->SignerInfos.paItems[0];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * If special certificate requirements, check them out before validating
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * the signature.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!RTCrX509Certificate_MatchIssuerAndSerialNumber(&g_BuildX509Cert,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &pSignerInfo->IssuerAndSerialNumber.Name,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &pSignerInfo->IssuerAndSerialNumber.SerialNumber))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSet(pErrInfo, VERR_SUP_VP_NOT_SIGNED_WITH_BUILD_CERT, "Not signed with the build certificate.");
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify the signature. We instruct the verifier to use the signing time
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * counter signature present when present, falling back on the timestamp
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * planted by the linker when absent. In ring-0 we don't have all the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * necessary timestamp server root certificate info, so we have to allow
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * using counter signatures unverified there. Ditto for the early period
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of ring-3 hardened stub execution.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTTIMESPEC ValidationTime;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_fHaveOtherRoots)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED | RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the given loader image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hLdrMod File handle to the executable file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName Full NT path to the DLL in question, used for
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * dealing with unsigned system dlls as well as for
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * error/logging.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pNtViRdr The reader instance /w flags.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fAvoidWinVerifyTrust Whether to avoid WinVerifyTrust because of
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * deadlock or other loader related dangers.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was used.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fAvoidWinVerifyTrust, bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pfWinVerifyTrust)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *pfWinVerifyTrust = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Check that the caller has performed the necessary library initialization. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!RTCrX509Certificate_IsPresent(&g_BuildX509Cert))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supHardenedWinVerifyImageByHandle: supHardenedWinInitImageVerifier was not called.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check the trusted installer bit first, if requested as it's somewhat
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * cheaper than the rest.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We relax this for system32 and a little for WinSxS, like we used to, as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * there are apparently some systems out there where the user, admin, or
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * someone has changed the ownership of core windows DLLs like user32.dll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and comctl32.dll. Since we need user32.dll and will be checking it's
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * digital signature, it's reasonably safe to let this thru. (The report
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * was of SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * owning user32.dll, see public ticket 13187, VBoxStartup.3.log.)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We've also had problems with graphics driver components like ig75icd64.dll
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and atig6pxx.dll not being owned by TrustedInstaller, with the result
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * that 3D got broken (mod by zero issue in test build 5). These were also
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * In one report by 'thor' the WinSxS resident comctl32.dll was owned by
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS (with 4.3.16).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** @todo Since we're now allowing Builtin\Administrators after all, perhaps we
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * could drop these system32 + winsxs hacks?? */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( (pNtViRdr->fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(pNtViRdr->hFile, pwszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, (uint32_t)RTUtf16Len(pwszName),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length / sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%ls: Relaxing the TrustedInstaller requirement for this DLL (it's in system32).\n", pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (supHardViUtf16PathStartsWithEx(pwszName, (uint32_t)RTUtf16Len(pwszName),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_WinSxSNtPath.UniStr.Buffer, g_WinSxSNtPath.UniStr.Length / sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%ls: Relaxing the TrustedInstaller requirement for this DLL (it's in WinSxS).\n", pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_OWNED_BY_TRUSTED_INSTALLER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "supHardenedWinVerifyImageByHandle: TrustedInstaller is not the owner of '%ls'.", pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The PKCS #7 SignedData signature is checked in the callback. Any
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * signing certificate restrictions are also enforced there.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * For the time being, we use the executable timestamp as the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * certificate validation date. We must query that first to avoid
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * potential issues re-entering the loader code from the callback.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Update: Save the first timestamp we validate with build cert and
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * use this as a minimum timestamp for further build cert
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * validations. This works around issues with old DLLs that
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * we sign against with our certificate (crt, sdl, qt).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3 /* Hack alert! (see above) */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && pNtViRdr->uTimestamp < g_uBuildTimestampHack)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->uTimestamp = g_uBuildTimestampHack;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3 /* Hack alert! (see above) */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_uBuildTimestampHack = pNtViRdr->uTimestamp;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Microsoft doesn't sign a whole bunch of DLLs, so we have to
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * ASSUME that a bunch of system DLLs are fine.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (rc == VERR_LDRVI_NOT_SIGNED)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, pNtViRdr->hFile, rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check for the signature checking enforcement, if requested to do so.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fEnforced = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc2))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwszName, rc2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (!fEnforced)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "The image '%ls' was not linked with /IntegrityCheck.", pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Pass it thru WinVerifyTrust when possible.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!fAvoidWinVerifyTrust)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardenedWinVerifyImageTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, rc, pfWinVerifyTrust, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_SUP_HARDENED_R3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Hook for the LdrLoadDll code to schedule scanning of imports.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedWinVerifyCacheScheduleImports(hLdrMod, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the given executable image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile File handle to the executable file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwszName Full NT path to the DLL in question, used for
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * dealing with unsigned system dlls as well as for
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * error/logging.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags Flags, SUPHNTVI_F_XXX.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fAvoidWinVerifyTrust Whether to avoid WinVerifyTrust because of
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * deadlock or other loader related dangers.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was used.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool fAvoidWinVerifyTrust,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create a reader instance.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardNtViRdrCreate(hFile, pwszName, fFlags, &pNtViRdr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTLDRMOD hLdrMod;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTLDRARCH enmArch = fFlags & SUPHNTVI_F_RC_IMAGE ? RTLDRARCH_X86_32 : RTLDRARCH_HOST;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fFlags & SUPHNTVI_F_RESOURCE_IMAGE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync enmArch = RTLDRARCH_WHATEVER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTLdrOpenWithReader(&pNtViRdr->Core, RTLDR_O_FOR_VALIDATION, enmArch, &hLdrMod, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, fAvoidWinVerifyTrust, pfWinVerifyTrust, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc2 = RTLdrClose(hLdrMod); AssertRC(rc2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supHardNtViRdrDestroy(&pNtViRdr->Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d (%ls)%s\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc, pwszName, pfWinVerifyTrust && *pfWinVerifyTrust ? "WinVerifyTrust" : ""));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * supHardenedWinVerifyImageByHandle version without the name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The name is derived from the handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param hFile File handle to the executable file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param fFlags Flags, SUPHNTVI_F_XXX.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Determine the NT name and call the verification function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING UniStr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abBuffer[(MAX_PATH + 8 + 1) * 2];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } uBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbIgn;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryObject(hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ObjectNameInformation,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &uBuf,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(uBuf) - sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &cbIgn);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uBuf.UniStr.Buffer = (WCHAR *)L"TODO3";
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return supHardenedWinVerifyImageByHandle(hFile, uBuf.UniStr.Buffer, fFlags, false /*fAvoidWinVerifyTrust*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*pfWinVerifyTrust*/, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING3 */
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Retrieves the full official path to the system root or one of it's sub
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directories.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This code is also used by the support driver.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VBox status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pvBuf The output buffer. This will contain a
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * UNICODE_STRING followed (at the kernel's
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * discretion) the string buffer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbBuf The size of the buffer @a pvBuf points to.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param enmDir Which directory under the system root we're
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * interested in.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardNtGetSystemRootDir(void *pvBuf, uint32_t cbBuf, SUPHARDNTSYSROOTDIR enmDir, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING NtName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch (enmDir)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case kSupHardNtSysRootDir_System32:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszNameSystem32[] = L"\\SystemRoot\\System32\\";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Buffer = (PWSTR)s_wszNameSystem32;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = sizeof(s_wszNameSystem32) - sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.MaximumLength = sizeof(s_wszNameSystem32);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync case kSupHardNtSysRootDir_WinSxS:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszNameWinSxS[] = L"\\SystemRoot\\WinSxS\\";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Buffer = (PWSTR)s_wszNameWinSxS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = sizeof(s_wszNameWinSxS) - sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.MaximumLength = sizeof(s_wszNameWinSxS);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync default:
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertFailed();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_INVALID_PARAMETER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OBJECT_ATTRIBUTES ObjAttr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_READ_DATA | SYNCHRONIZE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ObjAttr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &Ios,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /* Allocation Size*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_ATTRIBUTE_NORMAL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_OPEN,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*EaBuffer*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0 /*EaLength*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = Ios.Status;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbIgn;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtQueryObject(hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ObjectNameInformation,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pvBuf,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cbBuf - sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &cbIgn);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtClose(hFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PUNICODE_STRING pUniStr = (PUNICODE_STRING)pvBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pUniStr->Length > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Make sure it's terminated so it can safely be printed.*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pUniStr->Buffer[pUniStr->Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtQueryObject returned an empty path for '%ls'", NtName.Buffer);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH, "NtQueryObject failed on '%ls' dir: %#x", NtName.Buffer, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH, "Failure to open '%ls': %#x", NtName.Buffer, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize one certificate entry.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VBox status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pCert The X.509 certificate representation to init.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pabCert The raw DER encoded certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cbCert The size of the raw certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Where to return extended error info. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszErrorTag Error tag.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertInit(PRTCRX509CERTIFICATE pCert, unsigned char const *pabCert, unsigned cbCert,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTERRINFO pErrInfo, const char *pszErrorTag)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(cbCert > 16 && cbCert < _128K,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_3, "%s: cbCert=%#x out of range", pszErrorTag, cbCert));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(!RTCrX509Certificate_IsPresent(pCert),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoSetF(pErrInfo, VERR_WRONG_ORDER, "%s: Certificate already decoded?", pszErrorTag));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTASN1CURSORPRIMARY PrimaryCursor;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1CursorInitPrimary(&PrimaryCursor, pabCert, cbCert, pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, pCert, pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrX509Certificate_CheckSanity(pCert, 0, pErrInfo, pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertStoreAddArray(RTCRSTORE hStore, PCSUPTAENTRY paCerts, unsigned cCerts, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < cCerts; i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_TAF_DER, paCerts[i].pch, paCerts[i].cb, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize a certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param phStore Where to return the store pointer.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param paCerts1 Pointer to the first certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cCerts1 Entries in the first certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param paCerts2 Pointer to the second certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cCerts2 Entries in the second certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param paCerts3 Pointer to the third certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param cCerts3 Entries in the third certificate table.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Where to return extended error info. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszErrorTag Error tag.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertStoreInit(PRTCRSTORE phStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCSUPTAENTRY paCerts1, unsigned cCerts1,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCSUPTAENTRY paCerts2, unsigned cCerts2,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCSUPTAENTRY paCerts3, unsigned cCerts3,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTERRINFO pErrInfo, const char *pszErrorTag)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(*phStore == NIL_RTCRSTORE, VERR_WRONG_ORDER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrStoreCreateInMem(phStore, cCerts1 + cCerts2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "RTCrStoreCreateMemoryStore failed: %Rrc", rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts1, cCerts1, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts2, cCerts2, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts3, cCerts3, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initializes the windows paths.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic void supHardenedWinInitImageVerifierWinPaths(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Windows paths that we're interested in.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUPSYSROOTDIRBUF *pNtPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WCHAR const *pwszRegValue;
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync const char *pszLogName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } s_aPaths[] =
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync {
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync { &g_ProgramFilesNtPath, L"ProgramFilesDir", "ProgDir" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { &g_CommonFilesNtPath, L"CommonFilesDir", "ComDir" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef RT_ARCH_AMD64
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { &g_ProgramFilesX86NtPath, L"ProgramFilesDir (x86)", "ProgDir32" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { &g_CommonFilesX86NtPath, L"CommonFilesDir (x86)", "ComDir32" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the registry key containing the paths.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING NtName = RTNT_CONSTANT_UNISTR(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OBJECT_ATTRIBUTES ObjAttr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hKey;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjAttr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Loop over the paths and resolve their NT paths.
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync */
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync {
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync /*
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync * Query the value first.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING ValueName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ValueName.Buffer = (WCHAR *)s_aPaths[i].pwszRegValue;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ValueName.Length = (USHORT)(RTUtf16Len(s_aPaths[i].pwszRegValue) * sizeof(WCHAR));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ValueName.MaximumLength = ValueName.Length + sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync union
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t abPadding[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR) * 128];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint64_t uAlign;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } uBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbActual = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR), &cbActual);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Must be a simple string value, terminate it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( uBuf.PartialInfo.Type == REG_EXPAND_SZ
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || uBuf.PartialInfo.Type == REG_SZ)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Expand any environment variable references before opening it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * We use the result buffer as storage for the expaneded path,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * reserving space for the windows name space prefix.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING Src;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Src.Buffer = (WCHAR *)uBuf.PartialInfo.Data;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Src.Length = uBuf.PartialInfo.DataLength;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (Src.Length >= sizeof(WCHAR) && Src.Buffer[Src.Length / sizeof(WCHAR) - 1] == '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Src.Length -= sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Src.MaximumLength = Src.Length + sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Src.Buffer[uBuf.PartialInfo.DataLength / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->awcBuffer[0] = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->awcBuffer[1] = '?';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->awcBuffer[2] = '?';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->awcBuffer[3] = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING Dst;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Buffer = &s_aPaths[i].pNtPath->awcBuffer[4];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.MaximumLength = sizeof(s_aPaths[i].pNtPath->awcBuffer) - sizeof(WCHAR) * 5;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Length = Dst.MaximumLength;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (uBuf.PartialInfo.Type == REG_EXPAND_SZ)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = RtlExpandEnvironmentStrings_U(NULL, &Src, &Dst, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(Dst.Buffer, Src.Buffer, Src.Length);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Length = Src.Length;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Buffer[Dst.Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Include the \\??\\ prefix in the result and open the path.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Buffer -= 4;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.Length += 4 * sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Dst.MaximumLength += 4 * sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &Dst, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFile = INVALID_HANDLE_VALUE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_READ_DATA | SYNCHRONIZE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ObjAttr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &Ios,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /* Allocation Size*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_ATTRIBUTE_NORMAL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_OPEN,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync | FILE_SYNCHRONOUS_IO_NONALERT,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /*EaBuffer*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0 /*EaLength*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = Ios.Status;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Query the real NT name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ULONG cbIgn;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = NtQueryObject(hFile,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync ObjectNameInformation,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync sizeof(*s_aPaths[i].pNtPath) - sizeof(WCHAR),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &cbIgn);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (s_aPaths[i].pNtPath->UniStr.Length > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Make sure it's terminated.*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Buffer[s_aPaths[i].pNtPath->UniStr.Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s:%*s %ls\n", s_aPaths[i].pszLogName, 9 - strlen(s_aPaths[i].pszLogName), "",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Buffer));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: NtQueryObject returned empty string\n", s_aPaths[i].pszLogName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = STATUS_INVALID_PARAMETER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: NtQueryObject failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtClose(hFile);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: NtCreateFile failed: %#x (%ls)\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pszLogName, rcNt, Dst.Buffer));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: RtlExpandEnvironmentStrings_U failed: %#x (%ls)\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pszLogName, rcNt, Src.Buffer));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: type mismatch: %#x\n", s_aPaths[i].pszLogName, uBuf.PartialInfo.Type));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = STATUS_INVALID_PARAMETER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("%s: NtQueryValueKey failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Stub the entry on failure. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Length = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Buffer = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtClose(hKey);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("NtOpenKey(%ls) failed: %#x\n", NtName.Buffer, rcNt));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Stub all the entries on failure. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Length = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync s_aPaths[i].pNtPath->UniStr.Buffer = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_EVEN_MORE */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This initializes the certificates globals so we don't have to reparse them
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * every time we need to verify an image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Where to return extended error info. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinInitImageVerifier(PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(!RTCrX509Certificate_IsPresent(&g_BuildX509Cert), VERR_WRONG_ORDER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the system root paths.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardNtGetSystemRootDir(&g_System32NtPath, sizeof(g_System32NtPath), kSupHardNtSysRootDir_System32, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtGetSystemRootDir(&g_WinSxSNtPath, sizeof(g_WinSxSNtPath), kSupHardNtSysRootDir_WinSxS, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("System32: %ls\n", g_System32NtPath.UniStr.Buffer));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("WinSxS: %ls\n", g_WinSxSNtPath.UniStr.Buffer));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supHardenedWinInitImageVerifierWinPaths();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize it, leaving the cleanup to the termination call.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertInit(&g_BuildX509Cert, g_abSUPBuildCert, g_cbSUPBuildCert, pErrInfo, "BuildCertificate");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcRootStore, g_aSUPSpcRootTAs, g_cSUPSpcRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL, 0, NULL, 0, pErrInfo, "SpcRoot");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hNtKernelRootStore, g_aSUPNtKernelRootTAs, g_cSUPNtKernelRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL, 0, NULL, 0, pErrInfo, "NtKernelRoot");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcAndNtKernelRootStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_aSUPSpcRootTAs, g_cSUPSpcRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_aSUPNtKernelRootTAs, g_cSUPNtKernelRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_aSUPTimestampTAs, g_cSUPTimestampTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pErrInfo, "SpcAndNtKernelRoot");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcAndNtKernelSuppStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL, 0, NULL, 0, NULL, 0,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pErrInfo, "SpcAndNtKernelSupplemental");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#if 0 /* For the time being, always trust the build certificate. It bypasses the timestamp issues of CRT and SDL. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* If the build certificate is a test singing certificate, it must be a
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync trusted root or we'll fail to validate anything. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( RT_SUCCESS(rc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && RTCrX509Name_Compare(&g_BuildX509Cert.TbsCertificate.Subject, &g_BuildX509Cert.TbsCertificate.Issuer) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_abSUPBuildCert, g_cbSUPBuildCert, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Finally initialize known SIDs that we use.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SID_IDENTIFIER_AUTHORITY s_NtAuth = SECURITY_NT_AUTHORITY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = RtlInitializeSid(&g_TrustedInstallerSid, &s_NtAuth, SECURITY_SERVICE_ID_RID_COUNT);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 0) = SECURITY_SERVICE_ID_BASE_RID;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 1) = 956008885;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 2) = 3418522649;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 3) = 1831038044;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 4) = 1853292631;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 5) = 2271478464;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = RtlInitializeSid(&g_LocalSystemSid, &s_NtAuth, 1);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_LocalSystemSid, 0) = SECURITY_LOCAL_SYSTEM_RID;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rcNt = RtlInitializeSid(&g_AdminsGroupSid, &s_NtAuth, 2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (NT_SUCCESS(rcNt))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 1) = DOMAIN_ALIAS_RID_ADMINS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrConvertFromNtStatus(rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supHardenedWinTermImageVerifier();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Releases resources allocated by supHardenedWinInitImageVerifier.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supHardenedWinTermImageVerifier(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Certificate_IsPresent(&g_BuildX509Cert))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1VtDelete(&g_BuildX509Cert.SeqCore.Asn1Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrStoreRelease(g_hSpcAndNtKernelSuppStore);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_hSpcAndNtKernelSuppStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrStoreRelease(g_hSpcAndNtKernelRootStore);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_hSpcAndNtKernelRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrStoreRelease(g_hNtKernelRootStore);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_hNtKernelRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrStoreRelease(g_hSpcRootStore);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_hSpcRootStore = NIL_RTCRSTORE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This is a hardcoded list of certificates we thing we might need.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if wanted, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pCert The certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedWinIsDesiredRootCA(PCRTCRX509CERTIFICATE pCert)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char szSubject[512];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync szSubject[sizeof(szSubject) - 1] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrX509Name_FormatAsString(&pCert->TbsCertificate.Subject, szSubject, sizeof(szSubject) - 1, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check that it's a plausible root certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!RTCrX509Certificate_IsSelfSigned(pCert))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - not-self-signed: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTAsn1Integer_UnsignedCompareWithU32(&pCert->TbsCertificate.T0.Version, 3) > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE) )
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-cert-sign: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pCert->TbsCertificate.T3.pBasicConstraints
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !pCert->TbsCertificate.T3.pBasicConstraints->CA.fValue)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-CA: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits < 256) /* mostly for u64KeyId reading. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - key too small: %u bits %s\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint64_t const u64KeyId = pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.uBits.pu64[1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# if 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Whitelist - Array of names and key clues of the certificates we want.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint64_t u64KeyId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } const s_aWanted[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* SPC */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "L=Internet, O=VeriSign, Inc., OU=VeriSign Commercial Software Publishers CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x491857ead79dde00), "C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* TS */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "O=Microsoft Trust Network, OU=Microsoft Corporation, OU=Microsoft Time Stamping Service Root, OU=Copyright (c) 1997 Microsoft Corp." },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "O=VeriSign Trust Network, OU=VeriSign, Inc., OU=VeriSign Time Stamping Service Root, OU=NO LIABILITY ACCEPTED, (c)97 VeriSign, Inc." },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "C=ZA, ST=Western Cape, L=Durbanville, O=Thawte, OU=Thawte Certification, CN=Thawte Timestamping CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Additional Windows 8.1 list: */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x5ad46780fa5df300), "DC=com, DC=microsoft, CN=Microsoft Root Certificate Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x3be670c1bd02a900), "OU=Copyright (c) 1997 Microsoft Corp., OU=Microsoft Corporation, CN=Microsoft Root Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x4d3835aa4180b200), "C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Root Certificate Authority 2011" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x646e3fe3ba08df00), "C=US, O=MSFT, CN=Microsoft Authenticode(tm) Root Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xece4e4289e08b900), "C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Root Certificate Authority 2010" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x59faf1086271bf00), "C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x3d98ab22bb04a300), "C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x91e3728b8b40d000), "C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x61a3a33f81aace00), "C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Object" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x9e5bc2d78b6a3636), "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA, Email=premium-server@thawte.com" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xf4fd306318ccda00), "C=US, O=GeoTrust Inc., CN=GeoTrust Global CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xa0ee62086758b15d), "C=US, O=Equifax, OU=Equifax Secure Certificate Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x8ff6fc03c1edbd00), "C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xa3ce8d99e60eda00), "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xa671e9fec832b700), "C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xa8de7211e13be200), "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x0ff3891b54348328), "C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.netSecure Server Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x7ae89c50f0b6a00f), "C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xd45980fbf0a0ac00), "C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2006 thawte, Inc. - For authorized use only, CN=thawte Primary Root CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x9e5bc2d78b6a3636), "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA, Email=premium-server@thawte.com" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x7c4fd32ec1b1ce00), "C=PL, O=Unizeto Sp. z o.o., CN=Certum CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xd4fbe673e5ccc600), "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x16e64d2a56ccf200), "C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., OU=http://certificates.starfieldtech.com/repository/, CN=Starfield Services Root Certificate Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x6e2ba21058eedf00), "C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN - DATACorp SGC" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xb28612a94b4dad00), "O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.netCertification Authority (2048)" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x357a29080824af00), "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, Inc. - For authorized use only, CN=VeriSign Class3 Public Primary Certification Authority - G5" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x466cbc09db88c100), "C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x9259c8abe5ca713a), "L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com/, Email=info@valicert.com" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x1f78fc529cbacb00), "C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class3 Public Primary Certification Authority - G3" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x8043e4ce150ead00), "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0x00f2e6331af7b700), "C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root" },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t i = RT_ELEMENTS(s_aWanted);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (i-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( s_aWanted[i].u64KeyId == u64KeyId
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || s_aWanted[i].u64KeyId == UINT64_MAX)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, s_aWanted[i].pszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Blacklist approach.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint64_t u64KeyId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } const s_aUnwanted[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { UINT64_C(0xffffffffffffffff), "C=US, O=U.S. Robots and Mechanical Men, Inc., OU=V.I.K.I." }, /* dummy entry */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t i = RT_ELEMENTS(s_aUnwanted);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (i-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( s_aUnwanted[i].u64KeyId == u64KeyId
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync || s_aUnwanted[i].u64KeyId == UINT64_MAX)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, s_aUnwanted[i].pszName))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - blacklisted: %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Loads a module in the system32 directory.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Module handle on success. Won't return on faliure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszName The name of the DLL to load.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(HMODULE) supR3HardenedWinLoadSystem32Dll(const char *pszName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WCHAR wszName[200+60];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UINT cwcDir = GetSystemDirectoryW(wszName, RT_ELEMENTS(wszName) - 60);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wszName[cwcDir] = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUtf16CopyAscii(&wszName[cwcDir + 1], RT_ELEMENTS(wszName) - cwcDir, pszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD fFlags = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags = LOAD_LIBRARY_SEARCH_SYSTEM32;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HMODULE hMod = LoadLibraryExW(wszName, NULL, fFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( hMod == NULL
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && fFlags
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && RtlGetLastWin32Error() == ERROR_INVALID_PARAMETER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fFlags = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hMod = LoadLibraryExW(wszName, NULL, fFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hMod == NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedFatal("Error loading '%s': %u [%ls]", pszName, RtlGetLastWin32Error(), wszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return hMod;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Called by supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation to
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * import selected root CAs from the system certificate store.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * These certificates permits us to correctly validate third party DLLs.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic void supR3HardenedWinRetrieveTrustedRootCAs(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cAdded = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Load crypt32.dll and resolve the APIs we need.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HMODULE hCrypt32 = supR3HardenedWinLoadSystem32Dll("crypt32.dll");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define RESOLVE_CRYPT32_API(a_Name, a_pfnType) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync a_pfnType pfn##a_Name = (a_pfnType)GetProcAddress(hCrypt32, #a_Name); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pfn##a_Name == NULL) supR3HardenedFatal("Error locating '" #a_Name "' in 'crypt32.dll': %u", RtlGetLastWin32Error())
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT32_API(CertOpenStore, PFNCERTOPENSTORE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT32_API(CertCloseStore, PFNCERTCLOSESTORE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT32_API(CertEnumCertificatesInStore, PFNCERTENUMCERTIFICATESINSTORE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#undef RESOLVE_CRYPT32_API
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the root store and look for the certificates we wish to use.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD fOpenStore = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCERTSTORE hStore = pfnCertOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /* hCryptProv = default */, CERT_SYSTEM_STORE_LOCAL_MACHINE | fOpenStore, L"Root");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!hStore)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hStore = pfnCertOpenStore(CERT_STORE_PROV_SYSTEM_W, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /* hCryptProv = default */, CERT_SYSTEM_STORE_CURRENT_USER | fOpenStore, L"Root");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hStore)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCCERT_CONTEXT pCurCtx = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((pCurCtx = pfnCertEnumCertificatesInStore(hStore, pCurCtx)) != NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pCurCtx->dwCertEncodingType & X509_ASN_ENCODING)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTERRINFOSTATIC StaticErrInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTASN1CURSORPRIMARY PrimaryCursor;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTAsn1CursorInitPrimary(&PrimaryCursor, pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoInitStatic(&StaticErrInfo),
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "CurCtx");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCRX509CERTIFICATE MyCert;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &MyCert, "Cert");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync {
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync if (supR3HardenedWinIsDesiredRootCA(&MyCert))
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync {
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcRootStore, RTCRCERTCTX_F_ENC_X509_DER,
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRC(rc);
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRC(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cAdded++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
RTCrX509Certificate_Delete(&MyCert);
}
/* XP root certificate "C&W HKT SecureNet CA SGC Root" has non-standard validity
timestamps, the UTC formatting isn't Zulu time but specifies timezone offsets.
Ignore these failures and certificates. */
else if (rc != VERR_ASN1_INVALID_UTC_TIME_ENCODING)
AssertMsgFailed(("RTCrX509Certificate_DecodeAsn1 failed: rc=%#x: %s\n", rc, StaticErrInfo.szMsg));
}
}
pfnCertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
g_fHaveOtherRoots = true;
}
SUP_DPRINTF(("supR3HardenedWinRetrieveTrustedRootCAs: cAdded=%u\n", cAdded));
}
/**
* Resolves the WinVerifyTrust API after the process has been verified and
* installs a thread creation hook.
*
* The WinVerifyTrust API is used in addition our own Authenticode verification
* code. If the image has the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag
* set, it will be checked again by the kernel. All our image has this flag set
* and we require all VBox extensions to have it set as well. In effect, the
* authenticode signature will be checked two or three times.
*
* @param pszProgName The program name.
*/
DECLHIDDEN(void) supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(const char *pszProgName)
{
# ifdef IN_SUP_HARDENED_R3
/*
* Load our the support library DLL that does the thread hooking as the
* security API may trigger the creation of COM worker threads (or
* whatever they are).
*
* The thread creation hook makes the threads very slippery to debuggers by
* irreversably disabling most (if not all) debug events for them.
*/
char szPath[RTPATH_MAX];
supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxSupLib.DLL"));
suplibHardenedStrCat(szPath, "/VBoxSupLib.DLL");
HMODULE hSupLibMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, true /*fSystem32Only*/);
if (hSupLibMod == NULL)
supR3HardenedFatal("Error loading '%s': %u", szPath, RtlGetLastWin32Error());
# endif
/*
* Allocate TLS entry for WinVerifyTrust recursion prevention.
*/
DWORD iTls = TlsAlloc();
if (iTls != TLS_OUT_OF_INDEXES)
g_iTlsWinVerifyTrustRecursion = iTls;
else
supR3HardenedError(RtlGetLastWin32Error(), false /*fFatal*/, "TlsAlloc failed");
/*
* Resolve it.
*/
HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll");
#define RESOLVE_CRYPT_API(a_Name, a_pfnType, a_uMinWinVer) \
do { \
g_pfn##a_Name = (a_pfnType)GetProcAddress(hWintrust, #a_Name); \
if (g_pfn##a_Name == NULL && (a_uMinWinVer) < g_uNtVerCombined) \
supR3HardenedFatal("Error locating '" #a_Name "' in 'Wintrust.dll': %u", RtlGetLastWin32Error()); \
} while (0)
PFNWINVERIFYTRUST pfnWinVerifyTrust = (PFNWINVERIFYTRUST)GetProcAddress(hWintrust, "WinVerifyTrust");
if (!pfnWinVerifyTrust)
supR3HardenedFatal("Error locating 'WinVerifyTrust' in 'Wintrust.dll': %u", RtlGetLastWin32Error());
RESOLVE_CRYPT_API(CryptCATAdminAcquireContext, PFNCRYPTCATADMINACQUIRECONTEXT, 0);
RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE, 0);
RESOLVE_CRYPT_API(CryptCATAdminEnumCatalogFromHash, PFNCRYPTCATADMINENUMCATALOGFROMHASH, 0);
RESOLVE_CRYPT_API(CryptCATAdminReleaseCatalogContext, PFNCRYPTCATADMINRELEASECATALOGCONTEXT, 0);
RESOLVE_CRYPT_API(CryptCATAdminReleaseContext, PFNCRYPTCATDADMINRELEASECONTEXT, 0);
RESOLVE_CRYPT_API(CryptCATCatalogInfoFromContext, PFNCRYPTCATCATALOGINFOFROMCONTEXT, 0);
RESOLVE_CRYPT_API(CryptCATAdminAcquireContext2, PFNCRYPTCATADMINACQUIRECONTEXT2, SUP_NT_VER_W80);
RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle2, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2, SUP_NT_VER_W80);
/*
* Call it on ourselves and ntdll to make sure it loads all the providers
* now, we would otherwise geting into recursive trouble in the
* NtCreateSection hook.
*/
# ifdef IN_SUP_HARDENED_R3
RTERRINFOSTATIC ErrInfoStatic;
RTErrInfoInitStatic(&ErrInfoStatic);
int rc = supR3HardNtViCallWinVerifyTrust(NULL, g_SupLibHardenedExeNtPath.UniStr.Buffer, 0,
&ErrInfoStatic.Core, pfnWinVerifyTrust);
if (RT_FAILURE(rc))
supR3HardenedFatalMsg(pszProgName, kSupInitOp_Integrity, rc,
"WinVerifyTrust failed on stub executable: %s", ErrInfoStatic.szMsg);
# endif
if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* ntdll isn't signed on XP, assuming this is the case on W2K3 for now. */
supR3HardNtViCallWinVerifyTrust(NULL, L"\\SystemRoot\\System32\\ntdll.dll", 0, NULL, pfnWinVerifyTrust);
supR3HardNtViCallWinVerifyTrustCatFile(NULL, L"\\SystemRoot\\System32\\ntdll.dll", 0, NULL, pfnWinVerifyTrust);
g_pfnWinVerifyTrust = pfnWinVerifyTrust;
SUP_DPRINTF(("g_pfnWinVerifyTrust=%p\n", pfnWinVerifyTrust));
# ifdef IN_SUP_HARDENED_R3
/*
* Load some problematic DLLs into the verifier cache to prevent
* recursion trouble.
*/
supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\crypt32.dll");
supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\Wintrust.dll");
# endif
/*
* Now, get trusted root CAs so we can verify a broader scope of signatures.
*/
supR3HardenedWinRetrieveTrustedRootCAs();
}
static int supR3HardNtViNtToWinPath(PCRTUTF16 pwszNtName, PCRTUTF16 *ppwszWinPath,
PRTUTF16 pwszWinPathBuf, size_t cwcWinPathBuf)
{
static const RTUTF16 s_wszPrefix[] = L"\\\\.\\GLOBALROOT";
if (*pwszNtName != '\\' && *pwszNtName != '/')
return VERR_PATH_DOES_NOT_START_WITH_ROOT;
size_t cwcNtName = RTUtf16Len(pwszNtName);
if (RT_ELEMENTS(s_wszPrefix) + cwcNtName > cwcWinPathBuf)
return VERR_FILENAME_TOO_LONG;
memcpy(pwszWinPathBuf, s_wszPrefix, sizeof(s_wszPrefix));
memcpy(&pwszWinPathBuf[sizeof(s_wszPrefix) / sizeof(RTUTF16) - 1], pwszNtName, (cwcNtName + 1) * sizeof(RTUTF16));
*ppwszWinPath = pwszWinPathBuf;
return VINF_SUCCESS;
}
/**
* Calls WinVerifyTrust to verify an PE image.
*
* @returns VBox status code.
* @param hFile File handle to the executable file.
* @param pwszName Full NT path to the DLL in question, used for
* dealing with unsigned system dlls as well as for
* error/logging.
* @param fFlags Flags, SUPHNTVI_F_XXX.
* @param pErrInfo Pointer to error info structure. Optional.
* @param pfnWinVerifyTrust Pointer to the API.
*/
static int supR3HardNtViCallWinVerifyTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
PFNWINVERIFYTRUST pfnWinVerifyTrust)
{
/*
* Convert the name into a Windows name.
*/
RTUTF16 wszWinPathBuf[MAX_PATH];
PCRTUTF16 pwszWinPath;
int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
if (RT_FAILURE(rc))
return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrust: rc=%Rrc '%ls'", rc, pwszName);
/*
* Construct input parameters and call the API.
*/
WINTRUST_FILE_INFO FileInfo;
RT_ZERO(FileInfo);
FileInfo.cbStruct = sizeof(FileInfo);
FileInfo.pcwszFilePath = pwszWinPath;
FileInfo.hFile = hFile;
GUID PolicyActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA TrustData;
RT_ZERO(TrustData);
TrustData.cbStruct = sizeof(TrustData);
TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
TrustData.dwStateAction = WTD_STATEACTION_VERIFY;
TrustData.dwUIChoice = WTD_UI_NONE;
TrustData.dwProvFlags = 0;
if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
else
TrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
TrustData.dwUnionChoice = WTD_CHOICE_FILE;
TrustData.pFile = &FileInfo;
HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
if (hrc == S_OK)
rc = VINF_SUCCESS;
else
{
/*
* Failed. Format a nice error message.
*/
# ifdef DEBUG_bird
if (hrc != CERT_E_CHAINING /* Un-updated vistas, XPs, ++ */)
__debugbreak();
# endif
const char *pszErrConst = NULL;
switch (hrc)
{
case TRUST_E_SYSTEM_ERROR: pszErrConst = "TRUST_E_SYSTEM_ERROR"; break;
case TRUST_E_NO_SIGNER_CERT: pszErrConst = "TRUST_E_NO_SIGNER_CERT"; break;
case TRUST_E_COUNTER_SIGNER: pszErrConst = "TRUST_E_COUNTER_SIGNER"; break;
case TRUST_E_CERT_SIGNATURE: pszErrConst = "TRUST_E_CERT_SIGNATURE"; break;
case TRUST_E_TIME_STAMP: pszErrConst = "TRUST_E_TIME_STAMP"; break;
case TRUST_E_BAD_DIGEST: pszErrConst = "TRUST_E_BAD_DIGEST"; break;
case TRUST_E_BASIC_CONSTRAINTS: pszErrConst = "TRUST_E_BASIC_CONSTRAINTS"; break;
case TRUST_E_FINANCIAL_CRITERIA: pszErrConst = "TRUST_E_FINANCIAL_CRITERIA"; break;
case TRUST_E_PROVIDER_UNKNOWN: pszErrConst = "TRUST_E_PROVIDER_UNKNOWN"; break;
case TRUST_E_ACTION_UNKNOWN: pszErrConst = "TRUST_E_ACTION_UNKNOWN"; break;
case TRUST_E_SUBJECT_FORM_UNKNOWN: pszErrConst = "TRUST_E_SUBJECT_FORM_UNKNOWN"; break;
case TRUST_E_SUBJECT_NOT_TRUSTED: pszErrConst = "TRUST_E_SUBJECT_NOT_TRUSTED"; break;
case TRUST_E_NOSIGNATURE: pszErrConst = "TRUST_E_NOSIGNATURE"; break;
case TRUST_E_FAIL: pszErrConst = "TRUST_E_FAIL"; break;
case TRUST_E_EXPLICIT_DISTRUST: pszErrConst = "TRUST_E_EXPLICIT_DISTRUST"; break;
case CERT_E_CHAINING: pszErrConst = "CERT_E_CHAINING"; break;
case CERT_E_REVOCATION_FAILURE: pszErrConst = "CERT_E_REVOCATION_FAILURE"; break;
case CRYPT_E_FILE_ERROR: pszErrConst = "CRYPT_E_FILE_ERROR"; break;
case CRYPT_E_REVOKED: pszErrConst = "CRYPT_E_REVOKED"; break;
}
if (pszErrConst)
rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_UNSUPPORTED_ARCH,
"WinVerifyTrust failed with hrc=%s on '%ls'", pszErrConst, pwszName);
else
rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_UNSUPPORTED_ARCH,
"WinVerifyTrust failed with hrc=%Rhrc on '%ls'", hrc, pwszName);
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrust: WinVerifyTrust failed with %#x (%s) on '%ls'\n",
hrc, pszErrConst, pwszName));
}
/* clean up state data. */
TrustData.dwStateAction = WTD_STATEACTION_CLOSE;
FileInfo.hFile = NULL;
hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
return rc;
}
/**
* Calls WinVerifyTrust to verify an PE image via catalog files.
*
* @returns VBox status code.
* @param hFile File handle to the executable file.
* @param pwszName Full NT path to the DLL in question, used for
* dealing with unsigned system dlls as well as for
* error/logging.
* @param fFlags Flags, SUPHNTVI_F_XXX.
* @param pErrInfo Pointer to error info structure. Optional.
* @param pfnWinVerifyTrust Pointer to the API.
*/
static int supR3HardNtViCallWinVerifyTrustCatFile(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
PFNWINVERIFYTRUST pfnWinVerifyTrust)
{
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hFile=%p pwszName=%ls\n", hFile, pwszName));
/*
* Convert the name into a Windows name.
*/
RTUTF16 wszWinPathBuf[MAX_PATH];
PCRTUTF16 pwszWinPath;
int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
if (RT_FAILURE(rc))
return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrustCatFile: rc=%Rrc '%ls'", rc, pwszName);
/*
* Open the file if we didn't get a handle.
*/
HANDLE hFileClose = NULL;
if (hFile == RTNT_INVALID_HANDLE_VALUE || hFile == NULL)
{
hFile = RTNT_INVALID_HANDLE_VALUE;
IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
UNICODE_STRING NtName;
NtName.Buffer = (PWSTR)pwszName;
NtName.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR));
NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
OBJECT_ATTRIBUTES ObjAttr;
InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
NTSTATUS rcNt = NtCreateFile(&hFile,
FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
&ObjAttr,
&Ios,
NULL /* Allocation Size*/,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL /*EaBuffer*/,
0 /*EaLength*/);
if (NT_SUCCESS(rcNt))
rcNt = Ios.Status;
if (!NT_SUCCESS(rcNt))
return RTErrInfoSetF(pErrInfo, RTErrConvertFromNtStatus(rcNt),
"NtCreateFile returned %#x opening '%ls'.", rcNt, pwszName);
hFileClose = hFile;
}
/*
* On Windows 8.0 and later there are more than one digest choice.
*/
int fNoSignedCatalogFound = -1;
rc = VERR_LDRVI_NOT_SIGNED;
static struct
{
/** The digest algorithm name. */
const WCHAR *pszAlgorithm;
/** Cached catalog admin handle. */
HCATADMIN volatile hCachedCatAdmin;
} s_aHashes[] =
{
{ NULL, NULL },
{ L"SHA256", NULL },
};
for (uint32_t i = 0; i < RT_ELEMENTS(s_aHashes); i++)
{
/*
* Another loop for dealing with different trust provider policies
* required for successfully validating different catalog signatures.
*/
bool fTryNextPolicy;
uint32_t iPolicy = 0;
static const GUID s_aPolicies[] =
{
DRIVER_ACTION_VERIFY, /* Works with microsoft bits. Most frequently used, thus first. */
WINTRUST_ACTION_GENERIC_VERIFY_V2, /* Works with ATI and other SPC kernel-code signed stuff. */
};
do
{
/*
* Create a context.
*/
fTryNextPolicy = false;
bool fFreshContext = false;
BOOL fRc;
HCATADMIN hCatAdmin = ASMAtomicXchgPtr(&s_aHashes[i].hCachedCatAdmin, NULL);
if (hCatAdmin)
{
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Cached context %p\n", hCatAdmin));
fFreshContext = false;
fRc = TRUE;
}
else
{
l_fresh_context:
fFreshContext = true;
if (g_pfnCryptCATAdminAcquireContext2)
fRc = g_pfnCryptCATAdminAcquireContext2(&hCatAdmin, &s_aPolicies[iPolicy], s_aHashes[i].pszAlgorithm,
NULL /*pStrongHashPolicy*/, 0 /*dwFlags*/);
else
fRc = g_pfnCryptCATAdminAcquireContext(&hCatAdmin, &s_aPolicies[iPolicy], 0 /*dwFlags*/);
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: New context %p\n", hCatAdmin));
}
if (fRc)
{
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hCatAdmin=%p\n", hCatAdmin));
/*
* Hash the file.
*/
BYTE abHash[SUPHARDNTVI_MAX_CAT_HASH_SIZE];
DWORD cbHash = sizeof(abHash);
if (g_pfnCryptCATAdminCalcHashFromFileHandle2)
fRc = g_pfnCryptCATAdminCalcHashFromFileHandle2(hCatAdmin, hFile, &cbHash, abHash, 0 /*dwFlags*/);
else
fRc = g_pfnCryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, abHash, 0 /*dwFlags*/);
if (fRc)
{
/* Produce a string version of it that we can pass to WinVerifyTrust. */
RTUTF16 wszDigest[SUPHARDNTVI_MAX_CAT_HASH_SIZE * 2 + 1];
int rc2 = RTUtf16PrintHexBytes(wszDigest, RT_ELEMENTS(wszDigest), abHash, cbHash, RTSTRPRINTHEXBYTES_F_UPPER);
if (RT_SUCCESS(rc2))
{
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: cbHash=%u wszDigest=%ls\n", cbHash, wszDigest));
/*
* Enumerate catalog information that matches the hash.
*/
uint32_t iCat = 0;
HCATINFO hCatInfoPrev = NULL;
do
{
/* Get the next match. */
HCATINFO hCatInfo = g_pfnCryptCATAdminEnumCatalogFromHash(hCatAdmin, abHash, cbHash, 0, &hCatInfoPrev);
if (!hCatInfo)
{
if (!fFreshContext)
{
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Retrying with fresh context (CryptCATAdminEnumCatalogFromHash -> %u; iCat=%#x)\n", RtlGetLastWin32Error(), iCat));
if (hCatInfoPrev != NULL)
g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/);
g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/);
goto l_fresh_context;
}
ULONG ulErr = RtlGetLastWin32Error();
fNoSignedCatalogFound = ulErr == ERROR_NOT_FOUND && fNoSignedCatalogFound != 0;
if (iCat == 0)
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATAdminEnumCatalogFromHash failed ERRROR_NOT_FOUND (%u)\n", ulErr));
else if (iCat == 0)
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATAdminEnumCatalogFromHash failed %u\n", ulErr));
break;
}
fNoSignedCatalogFound = 0;
Assert(hCatInfoPrev == NULL);
hCatInfoPrev = hCatInfo;
/*
* Call WinVerifyTrust.
*/
CATALOG_INFO CatInfo;
CatInfo.cbStruct = sizeof(CatInfo);
CatInfo.wszCatalogFile[0] = '\0';
if (g_pfnCryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0 /*dwFlags*/))
{
WINTRUST_CATALOG_INFO WtCatInfo;
RT_ZERO(WtCatInfo);
WtCatInfo.cbStruct = sizeof(WtCatInfo);
WtCatInfo.dwCatalogVersion = 0;
WtCatInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
WtCatInfo.pcwszMemberTag = wszDigest;
WtCatInfo.pcwszMemberFilePath = pwszWinPath;
WtCatInfo.pbCalculatedFileHash = abHash;
WtCatInfo.cbCalculatedFileHash = cbHash;
WtCatInfo.pcCatalogContext = NULL;
WINTRUST_DATA TrustData;
RT_ZERO(TrustData);
TrustData.cbStruct = sizeof(TrustData);
TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
TrustData.dwStateAction = WTD_STATEACTION_VERIFY;
TrustData.dwUIChoice = WTD_UI_NONE;
TrustData.dwProvFlags = 0;
if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
else
TrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
TrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
TrustData.pCatalog = &WtCatInfo;
HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: WinVerifyTrust => %#x; cat='%ls'; file='%ls'\n",
hrc, CatInfo.wszCatalogFile, pwszName));
if (SUCCEEDED(hrc))
rc = VINF_SUCCESS;
else if (hrc == TRUST_E_NOSIGNATURE)
{ /* ignore because it's useless. */ }
else if (hrc == ERROR_INVALID_PARAMETER)
{ /* This is returned if the given file isn't found in the catalog, it seems. */ }
else
{
rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_WINTRUST_CAT_FAILURE,
"WinVerifyTrust failed with hrc=%#x on '%ls' and .cat-file='%ls'.",
hrc, pwszWinPath, CatInfo.wszCatalogFile);
fTryNextPolicy |= (hrc == CERT_E_UNTRUSTEDROOT);
}
/* clean up state data. */
TrustData.dwStateAction = WTD_STATEACTION_CLOSE;
hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
Assert(SUCCEEDED(hrc));
}
else
{
rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
"CryptCATCatalogInfoFromContext failed: %d [file=%s]",
RtlGetLastWin32Error(), pwszName);
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATCatalogInfoFromContext failed\n"));
}
iCat++;
} while (rc == VERR_LDRVI_NOT_SIGNED && iCat < 128);
if (hCatInfoPrev != NULL)
if (!g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/))
AssertFailed();
}
else
rc = RTErrInfoSetF(pErrInfo, rc2, "RTUtf16PrintHexBytes failed: %Rrc", rc);
}
else
rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
"CryptCATAdminCalcHashFromFileHandle[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
if (!ASMAtomicCmpXchgPtr(&s_aHashes[i].hCachedCatAdmin, hCatAdmin, NULL))
if (!g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/))
AssertFailed();
}
else
rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
"CryptCATAdminAcquireContext[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
iPolicy++;
} while ( fTryNextPolicy
&& iPolicy < RT_ELEMENTS(s_aPolicies));
/*
* Only repeat if we've got g_pfnCryptCATAdminAcquireContext2 and can specify the hash algorithm.
*/
if (!g_pfnCryptCATAdminAcquireContext2)
break;
if (rc != VERR_LDRVI_NOT_SIGNED)
break;
}
if (hFileClose != NULL)
NtClose(hFileClose);
/*
* DLLs that are likely candidates for local modifications.
*/
if (rc == VERR_LDRVI_NOT_SIGNED)
{
bool fCoreSystemDll = false;
PCRTUTF16 pwsz;
uint32_t cwcName = (uint32_t)RTUtf16Len(pwszName);
uint32_t cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR);
if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
{
pwsz = pwszName + cwcOther + 1;
if ( supHardViUtf16PathIsEqual(pwsz, "uxtheme.dll")
|| supHardViUtf16PathIsEqual(pwsz, "user32.dll")
|| supHardViUtf16PathIsEqual(pwsz, "gdi32.dll")
|| supHardViUtf16PathIsEqual(pwsz, "opengl32.dll")
|| (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "KernelBase.dll"))
|| (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "kernel32.dll"))
|| (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "ntdll.dll"))
)
{
if (RTErrInfoIsSet(pErrInfo))
RTErrInfoAdd(pErrInfo, rc, "\n");
RTErrInfoAddF(pErrInfo, rc, "'%ls' is most likely modified.", pwszName);
}
}
/* Kludge for ancient windows versions we don't want to support but
users still wants to use. Keep things as safe as possible without
unnecessary effort. Problem is that 3rd party catalog files cannot
easily be found. Showstopper for ATI users. */
if ( fNoSignedCatalogFound == 1
&& g_uNtVerCombined < SUP_NT_VER_VISTA
&& !fCoreSystemDll)
{
rc = VINF_LDRVI_NOT_SIGNED;
}
}
return rc;
}
/**
* Verifies the given image using WinVerifyTrust in some way.
*
* This is used by supHardenedWinVerifyImageByLdrMod as well as
* supR3HardenedScreenImage.
*
* @returns IPRT status code.
* @param hFile Handle of the file to verify.
* @param pwszName Full NT path to the DLL in question, used for
* dealing with unsigned system dlls as well as for
* error/logging.
* @param pfWinVerifyTrust Where to return whether WinVerifyTrust was
* actually used.
* @param pErrInfo Pointer to error info structure. Optional.
*/
DECLHIDDEN(int) supHardenedWinVerifyImageTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, int rc,
bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
{
if (pfWinVerifyTrust)
*pfWinVerifyTrust = false;
/*
* Call the windows verify trust API if we've resolved it and aren't in
* some obvious recursion.
*/
if (g_pfnWinVerifyTrust != NULL)
{
/* Check for recursion. */
bool fNoRecursion;
if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
{
fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0;
if (fNoRecursion)
TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1);
}
else
{
uint32_t const idCurrentThread = RTNtCurrentThreadId();
fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
}
if (fNoRecursion)
{
/* We can call WinVerifyTrust. */
if (pfWinVerifyTrust)
*pfWinVerifyTrust = true;
if (rc != VERR_LDRVI_NOT_SIGNED)
{
if (rc == VINF_LDRVI_NOT_SIGNED)
{
if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)
{
int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc));
rc = rc2;
}
else
{
AssertFailed();
rc = VERR_LDRVI_NOT_SIGNED;
}
}
else if (RT_SUCCESS(rc))
{
/** @todo having trouble with a 32-bit windows box when letting these calls thru */
rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
}
else
{
int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
AssertMsg(RT_FAILURE_NP(rc2),
("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>"));
}
}
/* Unwind recursion. */
if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0);
else
ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX);
}
else
SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
}
return rc;
}
/**
* Checks if WinVerifyTrust is callable on the current thread.
*
* Used by the main code to figure whether it makes sense to try revalidate an
* image that hasn't passed thru WinVerifyTrust yet.
*
* @returns true if callable on current thread, false if not.
*/
DECLHIDDEN(bool) supHardenedWinIsWinVerifyTrustCallable(void)
{
return g_pfnWinVerifyTrust != NULL
&& ( g_iTlsWinVerifyTrustRecursion != UINT32_MAX
? (uintptr_t)TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0
: g_idActiveThread != RTNtCurrentThreadId() );
}
/**
* Initializes g_uNtVerCombined and g_NtVerInfo.
* Called from suplibHardenedWindowsMain and suplibOsInit.
*/
DECLHIDDEN(void) supR3HardenedWinInitVersion(void)
{
/*
* Get the windows version. Use RtlGetVersion as GetVersionExW and
* GetVersion might not be telling the whole truth (8.0 on 8.1 depending on
* the application manifest).
*/
OSVERSIONINFOEXW NtVerInfo;
RT_ZERO(NtVerInfo);
NtVerInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&NtVerInfo)))
{
RT_ZERO(NtVerInfo);
PPEB pPeb = NtCurrentPeb();
NtVerInfo.dwMajorVersion = pPeb->OSMajorVersion;
NtVerInfo.dwMinorVersion = pPeb->OSMinorVersion;
NtVerInfo.dwBuildNumber = pPeb->OSPlatformId;
}
g_uNtVerCombined = SUP_MAKE_NT_VER_COMBINED(NtVerInfo.dwMajorVersion, NtVerInfo.dwMinorVersion, NtVerInfo.dwBuildNumber,
NtVerInfo.wServicePackMajor, NtVerInfo.wServicePackMinor);
}
#endif /* IN_RING3 */