SUPHardenedVerifyImage-win.cpp revision f1f6f0dfb3894c3c606f33186666914daf3213c3
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
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#if defined(VBOX_PERMIT_EVEN_MORE) && !defined(VBOX_PERMIT_MORE)
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# error "VBOX_PERMIT_EVEN_MORE without VBOX_PERMIT_MORE!"
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#endif
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
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);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsynctypedef NTSTATUS (WINAPI *PFNBCRYPTOPENALGORTIHMPROVIDER)(BCRYPT_ALG_HANDLE *phAlgo, PCWSTR pwszAlgoId,
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PCWSTR pwszImpl, DWORD dwFlags);
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;
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Program Files' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncSUPSYSROOTDIRBUF g_ProgramFilesNtPath;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# ifdef RT_ARCH_AMD64
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Program Files (x86)' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncSUPSYSROOTDIRBUF g_ProgramFilesX86NtPath;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Common Files' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncSUPSYSROOTDIRBUF g_CommonFilesNtPath;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# ifdef RT_ARCH_AMD64
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Common Files (x86)' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncSUPSYSROOTDIRBUF g_CommonFilesX86NtPath;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_MORE*/
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic union
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync{
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SID Sid;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync uint8_t abPadding[SECURITY_MAX_SID_SIZE];
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync}
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync/** The TrustedInstaller SID (Vista+). */
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync g_TrustedInstallerSid,
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync/** Local system ID (S-1-5-21). */
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync g_LocalSystemSid,
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync/** Builtin Administrators group alias (S-1-5-32-544). */
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync g_AdminsGroupSid;
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync
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
396186df506c303aa6137c1707423855981eb0c2vboxsync#ifdef IN_RING3
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync/** Timestamp hack working around issues with old DLLs that we ship.
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync * See supHardenedWinVerifyImageByHandle() for details. */
396186df506c303aa6137c1707423855981eb0c2vboxsyncstatic uint64_t g_uBuildTimestampHack = 0;
396186df506c303aa6137c1707423855981eb0c2vboxsync#endif
396186df506c303aa6137c1707423855981eb0c2vboxsync
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;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync/** Where we store the TLS entry for detecting WinVerifyTrustRecursion. */
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsyncstatic uint32_t g_iTlsWinVerifyTrustRecursion = UINT32_MAX;
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync/** Fallback WinVerifyTrust recursion protection. */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncstatic uint32_t volatile g_idActiveThread = UINT32_MAX;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
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,
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust, HRESULT *phrcWinVerifyTrust);
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);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NTSTATUS rcNt;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Check for type overflow (paranoia). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ((ULONG)cb != cb)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_OUT_OF_RANGE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Make sure the event semaphore is reset (normally we don't use one). */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (pNtViRdr->hEvent)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtClearEvent(pNtViRdr->hEvent);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (!NT_SUCCESS(rcNt))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync return RTErrConvertFromNtStatus(rcNt);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Perform the read. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync LARGE_INTEGER offNt;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync offNt.QuadPart = off;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtReadFile(pNtViRdr->hFile,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pNtViRdr->hEvent,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NULL /*ApcRoutine*/,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NULL /*ApcContext*/,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync &Ios,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pvBuf,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync (ULONG)cb,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync &offNt,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NULL);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#ifdef IN_RING0
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* In ring-0 the handles shall be synchronized and not alertable. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync AssertMsg(rcNt == STATUS_SUCCESS || !NT_SUCCESS(rcNt), ("%#x\n", rcNt));
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#else
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* In ring-3 we like our handles synchronized and non-alertable, but we
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync sometimes have to take what we can get. So, deal with pending I/O as
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync best we can. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (rcNt == STATUS_PENDING)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtWaitForSingleObject(pNtViRdr->hEvent ? pNtViRdr->hEvent : pNtViRdr->hFile, FALSE /*Alertable*/, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (NT_SUCCESS(rcNt))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = Ios.Status;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (NT_SUCCESS(rcNt))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* We require the caller to not read beyond the end of the file since
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync we don't have any way to communicate that we've read less that
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync requested. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (Ios.Information == cb)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pNtViRdr->off = off + cb; /* (just for show) */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync return VINF_SUCCESS;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifdef IN_RING3
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync supR3HardenedError(VERR_READ_ERROR, false,
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync "supHardNtViRdrRead: Only got %#zx bytes when requesting %#zx bytes at %#llx in '%s'.\n",
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync Ios.Information, off, cb, pNtViRdr->szFilename);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pNtViRdr->off = -1;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync return VERR_READ_ERROR;
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
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
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;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#ifdef IN_RING3
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (pNtViRdr->hEvent)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NtClose(pNtViRdr->hEvent);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pNtViRdr->hEvent = NULL;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync }
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#endif
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 */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsyncDECLHIDDEN(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
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /*
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync * Figure the file mode so we can see whether we'll be needing an event
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync * semaphore for waiting on reads. This may happen in very unlikely
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync * NtCreateSection scenarios.
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#if defined(IN_RING3) || defined(VBOX_STRICT)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync Ios.Status = STATUS_UNSUCCESSFUL;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync ULONG fMode;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtQueryInformationFile(hFile, &Ios, &fMode, sizeof(fMode), FileModeInformation);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (!NT_SUCCESS(rcNt) || !NT_SUCCESS(Ios.Status))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync return VERR_SUP_VP_FILE_MODE_ERROR;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#endif
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync HANDLE hEvent = NULL;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#ifdef IN_RING3
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (!(fMode & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (!NT_SUCCESS(rcNt))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync return VERR_SUP_VP_CREATE_READ_EVT_SEM_FAILED;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync }
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#else
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync Assert(fMode & FILE_SYNCHRONOUS_IO_NONALERT);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#endif
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync
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)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync {
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#ifdef IN_RING3
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (hEvent != NULL)
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync NtClose(hEvent);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_NO_MEMORY;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync }
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;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync pNtViRdr->hEvent = hEvent;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->off = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->cbFile = StdInfo.EndOfFile.QuadPart;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pNtViRdr->fFlags = fFlags;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *ppNtViRdr = pNtViRdr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/**
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * Checks if the file is owned by TrustedInstaller (Vista+) or similar.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @returns true if owned by TrustedInstaller of pre-Vista, false if not.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @param hFile The handle to the file.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @param pwszName The name of the file.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsyncstatic bool supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(HANDLE hFile, PCRTUTF16 pwszName)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync{
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (g_uNtVerCombined < SUP_NT_VER_VISTA)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return true;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Get the ownership information.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync union
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SECURITY_DESCRIPTOR_RELATIVE Rel;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SECURITY_DESCRIPTOR Abs;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync uint8_t abView[256];
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync } uBuf;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ULONG cbActual;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = NtQuerySecurityObject(hFile, OWNER_SECURITY_INFORMATION, &uBuf.Abs, sizeof(uBuf), &cbActual);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (!NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("NtQuerySecurityObject failed with rcNt=%#x on '%ls'\n", rcNt, pwszName));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return false;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Check the owner.
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync *
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * Initially we wished to only allow TrustedInstaller. But a Windows CAPI
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * plugin "Program Files\Tumbleweed\Desktop Validator\tmwdcapiclient.dll"
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * turned up owned by the local system user, and we cannot operate without
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * the plugin loaded once it's installed (WinVerityTrust fails).
ca3d954105919597e09cb2278ab6132919c34c96vboxsync *
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * We'd like to avoid allowing Builtin\Administrators here since it's the
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * default owner of anything an admin user creates (at least when elevated).
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * Seems windows update or someone ends up installing or modifying system
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * DLL ownership to this group, so for system32 and winsxs it's unavoidable.
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * And, not surprise, a bunch of products, including AV, firewalls and similar
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * ends up with their files installed with this group as owner. For instance
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * if we wish to have NAT continue working, we need to allow this.
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync *
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * Hopefully, we can limit the allowed files to these owners though, so
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * we won't be subject to ordinary (non-admin, or not elevated) users
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * downloading or be tricked into putting evil DLLs around the place...
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync PSID pOwner = uBuf.Rel.Control & SE_SELF_RELATIVE ? &uBuf.abView[uBuf.Rel.Owner] : uBuf.Abs.Owner;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Assert((uintptr_t)pOwner - (uintptr_t)&uBuf < sizeof(uBuf) - sizeof(SID));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (RtlEqualSid(pOwner, &g_TrustedInstallerSid))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return true;
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync if (RtlEqualSid(pOwner, &g_LocalSystemSid))
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync return true;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync if (RtlEqualSid(pOwner, &g_AdminsGroupSid))
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync {
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync SUP_DPRINTF(("%ls: Owner is administrators group.\n", pwszName));
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync return true;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%ls: Owner is not trusted installer (%.*Rhxs)\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync pwszName, ((uint8_t *)pOwner)[1] /*SubAuthorityCount*/ * sizeof(ULONG) + 8, pOwner));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return false;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync}
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII path compare.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if equal, false if not.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param pawcLeft The UTF-16 path string, not necessarily null
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * terminated.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param cwcLeft The number of chars in the left string,
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * RTSTR_MAX if unknown but terminated.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszRight The ascii string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsyncDECLHIDDEN(bool) supHardViUtf16PathIsEqualEx(PCRTUTF16 pawcLeft, size_t cwcLeft, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (;;)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync RTUTF16 wc;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync if (cwcLeft-- > 0)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wc =*pawcLeft++;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync else
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync wc = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t b = *pszRight++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b != wc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc >= 0x80)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wc = RT_C_TO_LOWER(wc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = RT_C_TO_LOWER(b);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync/**
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Simple case insensitive UTF-16 / ASCII path compare.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync *
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @returns true if equal, false if not.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param pwszLeft The UTF-16 path string.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param pszRight The ascii string.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync */
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsyncstatic bool supHardViUtf16PathIsEqual(PCRTUTF16 pwszLeft, const char *pszRight)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync{
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return supHardViUtf16PathIsEqualEx(pwszLeft, RTSTR_MAX, pszRight);
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync}
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync
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 */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncstatic 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;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc >= 0x80 || wc == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wc = RT_C_TO_LOWER(wc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = RT_C_TO_LOWER(b);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync wc = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync b = '\\';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc != b)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync/**
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync *
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @returns true if starts with given string, false if not.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param pwszLeft The path to check.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param cwcLeft The length of @a pwszLeft
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param pwszRight The starts-with path.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param cwcRight The length of @a pwszRight.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param fCheckSlash Check for a slash following the prefix.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(bool) supHardViUtf16PathStartsWithEx(PCRTUTF16 pwszLeft, uint32_t cwcLeft,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync PCRTUTF16 pwszRight, uint32_t cwcRight, bool fCheckSlash)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync{
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (cwcLeft < cwcRight || !cwcRight || !pwszRight)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* See if we can get away with a case sensitive compare first. */
361ef195c21ec36df0a44797ce62edb13d649d06vboxsync if (memcmp(pwszLeft, pwszRight, cwcRight * sizeof(RTUTF16)) == 0)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync pwszLeft += cwcRight;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync else
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync {
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* No luck, do a slow case insensitive comapre. */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync uint32_t cLeft = cwcRight;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync while (cLeft-- > 0)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync {
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync RTUTF16 wcLeft = *pwszLeft++;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync RTUTF16 wcRight = *pwszRight++;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (wcLeft != wcRight)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync {
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync wcLeft = wcLeft < 0x80 ? wcLeft == '/' ? '\\' : RT_C_TO_LOWER(wcLeft) : wcLeft;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync wcRight = wcRight < 0x80 ? wcRight == '/' ? '\\' : RT_C_TO_LOWER(wcRight) : wcRight;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (wcLeft != wcRight)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync }
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync }
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync }
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* Check for slash following the prefix, if request. */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if ( !fCheckSlash
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync || *pwszLeft == '\\'
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync || *pwszLeft == '/')
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return true;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync}
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync/**
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync *
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @returns true if starts with given string, false if not.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param pUniStrLeft The path to check.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param pUniStrRight The starts-with path.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param fCheckSlash Check for a slash following the prefix.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(bool) supHardViUniStrPathStartsWithUniStr(UNICODE_STRING const *pUniStrLeft, UNICODE_STRING const *pUniStrRight,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync bool fCheckSlash)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync{
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return supHardViUtf16PathStartsWithEx(pUniStrLeft->Buffer, pUniStrLeft->Length / sizeof(WCHAR),
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync pUniStrRight->Buffer, pUniStrRight->Length / sizeof(WCHAR), fCheckSlash);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync}
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync
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;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((wc = *pwsz++) != '\0')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (wc == '/' || wc == '\\')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cSlashes++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return cSlashes;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
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
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (!supHardViUtf16PathStartsWithAscii(&pwszPath[cwcWinDir], "\\AppPatch\\"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return g_uNtVerCombined >= SUP_NT_VER_VISTA;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync}
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#else
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync# error should not get here..
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#endif
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
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.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @param hFile The file handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param rc The status code..
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic 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);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pwsz = pwszName + cwcOther + 1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync /* Must be owned by trusted installer. (This test is superfuous, thus no relaxation here.) */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return rc;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Core DLLs. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "ntdll.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_NT_VER_VISTA ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "kernel32.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "kernelbase.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return IS_W80() || IS_W70() ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "apisetschema.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return IS_W70() ? VINF_LDRVI_NOT_SIGNED : rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supHardViUtf16PathIsEqual(pwsz, "apphelp.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
e352c25b01398e5503235fed02436cb2992f1021vboxsync#ifdef VBOX_PERMIT_VERIFIER_DLL
e352c25b01398e5503235fed02436cb2992f1021vboxsync if (supHardViUtf16PathIsEqual(pwsz, "verifier.dll"))
e352c25b01398e5503235fed02436cb2992f1021vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
e352c25b01398e5503235fed02436cb2992f1021vboxsync#endif
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#ifdef VBOX_PERMIT_MORE
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (uNtVer >= SUP_NT_VER_W70) /* hard limit: user32.dll is unwanted prior to w7. */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "sfc.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "sfc_os.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "user32.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync }
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#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;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* IN_RING0 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#ifndef IN_RING0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The WinSxS white list.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Just like with System32 there are potentially a number of DLLs that
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * could be required from WinSxS.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcOther = g_WinSxSNtPath.UniStr.Length / sizeof(WCHAR);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync 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
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync /* Must be owned by trusted installer. */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return rc;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return VINF_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* !IN_RING0 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync#ifdef VBOX_PERMIT_MORE
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync /*
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * AppPatch whitelist.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViIsAppPatchDir(pwszName, cwcName))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync {
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR); /* ASSUMES System32 is called System32. */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync pwsz = pwszName + cwcOther + 1;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return rc;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifndef VBOX_PERMIT_EVEN_MORE
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "acres.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return VINF_LDRVI_NOT_SIGNED;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifdef RT_ARCH_AMD64
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AppPatch64\\AcGenral.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return VINF_LDRVI_NOT_SIGNED;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# elif defined(RT_ARCH_X86)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AcGenral.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return VINF_LDRVI_NOT_SIGNED;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif /* !VBOX_PERMIT_EVEN_MORE */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# ifdef IN_RING0
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return rc;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# else
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return VINF_LDRVI_NOT_SIGNED;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* VBOX_PERMIT_MORE */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#ifndef IN_RING0
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# if defined(VBOX_PERMIT_MORE) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Program files and common files.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Permit anything that's signed and correctly installed.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( supHardViUtf16PathStartsWithEx(pwszName, cwcName,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync g_ProgramFilesNtPath.UniStr.Buffer, g_ProgramFilesNtPath.UniStr.Length,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync true /*fCheckSlash*/)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync g_CommonFilesNtPath.UniStr.Buffer, g_CommonFilesNtPath.UniStr.Length,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync true /*fCheckSlash*/)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# ifdef RT_ARCH_AMD64
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync g_ProgramFilesX86NtPath.UniStr.Buffer, g_ProgramFilesX86NtPath.UniStr.Length,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync true /*fCheckSlash*/)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync || supHardViUtf16PathStartsWithEx(pwszName, cwcName,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync g_CommonFilesX86NtPath.UniStr.Buffer, g_CommonFilesX86NtPath.UniStr.Length,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync true /*fCheckSlash*/)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync )
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return rc;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return VINF_LDRVI_NOT_SIGNED;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# elif defined(VBOX_PERMIT_MORE) && defined(VBOX_PERMIT_EVEN_MORE)
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync /*
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Anything that's owned by the trusted installer.
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if ( (fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync || supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync return VINF_LDRVI_NOT_SIGNED;
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#endif /* !IN_RING0 */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync /*
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Not permitted.
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Standard code signing. Use this for Microsoft SPC.}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViCertVerifyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)pvUser;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * If there is no certificate path build & validator associated with this
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * callback, it must be because of the build certificate. We trust the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * build certificate without any second thoughts.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hCertPaths == NIL_RTCRX509CERTPATHS)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Certificate_Compare(pCert, &g_BuildX509Cert) == 0) /* healthy paranoia */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_BUILD_CERT_IPE, "Not valid kernel code signature.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Standard code signing capabilites required.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, fFlags, NULL, pErrInfo);
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync if ( RT_SUCCESS(rc)
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync && (fFlags & RTCRPKCS7VCC_F_SIGNED_DATA))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * If kernel signing, a valid certificate path must be anchored by the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * microsoft kernel signing root certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cPaths = RTCrX509CertPathsGetPathCount(hCertPaths);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cFound = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cValid = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t iPath = 0; iPath < cPaths; iPath++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fTrusted;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTCRX509NAME pSubject;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTCRX509SUBJECTPUBLICKEYINFO pPublicKeyInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rcVerify;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrX509CertPathsQueryPathInfo(hCertPaths, iPath, &fTrusted, NULL /*pcNodes*/, &pSubject, &pPublicKeyInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL, NULL /*pCertCtx*/, &rcVerify);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRCBreak(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rcVerify))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(fTrusted);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cValid++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Search the kernel signing root store for a matching anchor.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCRSTORECERTSEARCH Search;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280(g_hNtKernelRootStore, pSubject, &Search);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRCBreak(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTCRCERTCTX pCertCtx;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((pCertCtx = RTCrStoreCertSearchNext(g_hNtKernelRootStore, &Search)) != NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync PCRTCRX509SUBJECTPUBLICKEYINFO pCertPubKeyInfo = NULL;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if (pCertCtx->pCert)
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync pCertPubKeyInfo = &pCertCtx->pCert->TbsCertificate.SubjectPublicKeyInfo;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync else if (pCertCtx->pTaInfo)
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync pCertPubKeyInfo = &pCertCtx->pTaInfo->PubKey;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync else
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync pCertPubKeyInfo = NULL;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync if ( pCertPubKeyInfo
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync && RTCrX509SubjectPublicKeyInfo_Compare(pCertPubKeyInfo, pPublicKeyInfo) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cFound++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrCertCtxRelease(pCertCtx);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc2 = RTCrStoreCertSearchDestroy(g_hNtKernelRootStore, &Search); AssertRC(rc2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc) && cFound == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_VALID_KERNEL_CODE_SIGNATURE, "Not valid kernel code signature.");
208b6c2dc45ecf098ded011e80eb380698695ee8vboxsync if (RT_SUCCESS(rc) && cValid < 2 && g_fHaveOtherRoots)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_UNEXPECTED_VALID_PATH_COUNT,
a5d6536233b36d63d25e3127624f1ddb7b59c52bvboxsync "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 /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * If special certificate requirements, check them out before validating
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the signature.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync * Verify the signature. We instruct the verifier to use the signing time
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync * counter signature present when present, falling back on the timestamp
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync * planted by the linker when absent. In ring-0 we don't have all the
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync * necessary timestamp server root certificate info, so we have to allow
814cc4006ca929fb4013fef16a8908d525b1b45avboxsync * using counter signatures unverified there. Ditto for the early period
814cc4006ca929fb4013fef16a8908d525b1b45avboxsync * of ring-3 hardened stub execution.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTTIMESPEC ValidationTime;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync uint32_t fFlags = RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync | RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync | RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY;
814cc4006ca929fb4013fef16a8908d525b1b45avboxsync#ifndef IN_RING0
814cc4006ca929fb4013fef16a8908d525b1b45avboxsync if (!g_fHaveOtherRoots)
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync#endif
4ee2f4fc8e99dc69ba5d63fd7dd3f52a38d0501evboxsync fFlags |= RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED | RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED;
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync return RTCrPkcs7VerifySignedData(pContentInfo, fFlags, g_hSpcAndNtKernelSuppStore, g_hSpcAndNtKernelRootStore,
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync &ValidationTime, supHardNtViCertVerifyCallback, pNtViRdr, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync/**
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Verifies the given loader image.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync *
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * @returns IPRT status code.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hLdrMod File handle to the executable file.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszName Full NT path to the DLL in question, used for
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * dealing with unsigned system dlls as well as for
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * error/logging.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pNtViRdr The reader instance /w flags.
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync * @param fAvoidWinVerifyTrust Whether to avoid WinVerifyTrust because of
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync * deadlock or other loader related dangers.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was used.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pErrInfo Pointer to error info structure. Optional.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync bool fAvoidWinVerifyTrust, bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync{
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (pfWinVerifyTrust)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync *pfWinVerifyTrust = false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifdef IN_RING3
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /* Check that the caller has performed the necessary library initialization. */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (!RTCrX509Certificate_IsPresent(&g_BuildX509Cert))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync return RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync "supHardenedWinVerifyImageByHandle: supHardenedWinInitImageVerifier was not called.");
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Check the trusted installer bit first, if requested as it's somewhat
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * cheaper than the rest.
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync *
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * We relax this for system32 and a little for WinSxS, like we used to, as
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * there are apparently some systems out there where the user, admin, or
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * someone has changed the ownership of core windows DLLs like user32.dll
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * and comctl32.dll. Since we need user32.dll and will be checking it's
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * digital signature, it's reasonably safe to let this thru. (The report
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * was of SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * owning user32.dll, see public ticket 13187, VBoxStartup.3.log.)
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync *
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * We've also had problems with graphics driver components like ig75icd64.dll
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * and atig6pxx.dll not being owned by TrustedInstaller, with the result
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * that 3D got broken (mod by zero issue in test build 5). These were also
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS.
ac181e85aa56547be29282b8235794b5af53edbfvboxsync *
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * In one report by 'thor' the WinSxS resident comctl32.dll was owned by
ac181e85aa56547be29282b8235794b5af53edbfvboxsync * SECURITY_BUILTIN_DOMAIN_RID + DOMAIN_ALIAS_RID_ADMINS (with 4.3.16).
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync /** @todo Since we're now allowing Builtin\Administrators after all, perhaps we
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync * could drop these system32 + winsxs hacks?? */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( (pNtViRdr->fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(pNtViRdr->hFile, pwszName))
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync {
ac181e85aa56547be29282b8235794b5af53edbfvboxsync if (supHardViUtf16PathStartsWithEx(pwszName, (uint32_t)RTUtf16Len(pwszName),
ac181e85aa56547be29282b8235794b5af53edbfvboxsync g_System32NtPath.UniStr.Buffer, g_System32NtPath.UniStr.Length / sizeof(WCHAR),
ac181e85aa56547be29282b8235794b5af53edbfvboxsync true /*fCheckSlash*/))
ac181e85aa56547be29282b8235794b5af53edbfvboxsync SUP_DPRINTF(("%ls: Relaxing the TrustedInstaller requirement for this DLL (it's in system32).\n", pwszName));
ac181e85aa56547be29282b8235794b5af53edbfvboxsync else if (supHardViUtf16PathStartsWithEx(pwszName, (uint32_t)RTUtf16Len(pwszName),
ac181e85aa56547be29282b8235794b5af53edbfvboxsync g_WinSxSNtPath.UniStr.Buffer, g_WinSxSNtPath.UniStr.Length / sizeof(WCHAR),
ac181e85aa56547be29282b8235794b5af53edbfvboxsync true /*fCheckSlash*/))
ac181e85aa56547be29282b8235794b5af53edbfvboxsync SUP_DPRINTF(("%ls: Relaxing the TrustedInstaller requirement for this DLL (it's in WinSxS).\n", pwszName));
ac181e85aa56547be29282b8235794b5af53edbfvboxsync else
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_OWNED_BY_TRUSTED_INSTALLER,
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync "supHardenedWinVerifyImageByHandle: TrustedInstaller is not the owner of '%ls'.", pwszName);
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Verify it.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync *
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * The PKCS #7 SignedData signature is checked in the callback. Any
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * signing certificate restrictions are also enforced there.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync *
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * For the time being, we use the executable timestamp as the
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * certificate validation date. We must query that first to avoid
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * potential issues re-entering the loader code from the callback.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync *
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Update: Save the first timestamp we validate with build cert and
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * use this as a minimum timestamp for further build cert
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * validations. This works around issues with old DLLs that
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * we sign against with our certificate (crt, sdl, qt).
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp));
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rc))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifdef IN_RING3 /* Hack alert! (see above) */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && pNtViRdr->uTimestamp < g_uBuildTimestampHack)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync pNtViRdr->uTimestamp = g_uBuildTimestampHack;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifdef IN_RING3 /* Hack alert! (see above) */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync g_uBuildTimestampHack = pNtViRdr->uTimestamp;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Microsoft doesn't sign a whole bunch of DLLs, so we have to
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * ASSUME that a bunch of system DLLs are fine.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (rc == VERR_LDRVI_NOT_SIGNED)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, pNtViRdr->hFile, rc);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_FAILURE(rc))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /*
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Check for the signature checking enforcement, if requested to do so.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync {
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync bool fEnforced = false;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced));
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_FAILURE(rc2))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.",
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync pwszName, rc2);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync else if (!fEnforced)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync "The image '%ls' was not linked with /IntegrityCheck.", pwszName);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync }
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync else
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync#ifdef IN_RING3
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync /*
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Pass it thru WinVerifyTrust when possible.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync */
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync if (!fAvoidWinVerifyTrust)
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, rc, pfWinVerifyTrust, pErrInfo);
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync#endif
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#ifdef IN_SUP_HARDENED_R3
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync /*
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook for the LdrLoadDll code to schedule scanning of imports.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (RT_SUCCESS(rc))
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinVerifyCacheScheduleImports(hLdrMod, pwszName);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return rc;
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync}
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the given executable image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param hFile File handle to the executable file.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pwszName Full NT path to the DLL in question, used for
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * dealing with unsigned system dlls as well as for
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * error/logging.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param fFlags Flags, SUPHNTVI_F_XXX.
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync * @param fAvoidWinVerifyTrust Whether to avoid WinVerifyTrust because of
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync * deadlock or other loader related dangers.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was used.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool fAvoidWinVerifyTrust,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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 */
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync RTLDRMOD hLdrMod;
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync RTLDRARCH enmArch = fFlags & SUPHNTVI_F_RC_IMAGE ? RTLDRARCH_X86_32 : RTLDRARCH_HOST;
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync uint32_t fLdrFlags = RTLDR_O_FOR_VALIDATION | RTLDR_O_IGNORE_ARCH_IF_NO_CODE;
2be6efa3a888d76feb7ad8b050e0b6c7e2d66c36vboxsync if (fFlags & SUPHNTVI_F_IGNORE_ARCHITECTURE)
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync fLdrFlags |= RTLDR_O_IGNORE_ARCH_IF_NO_CODE;
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync rc = RTLdrOpenWithReader(&pNtViRdr->Core, fLdrFlags, enmArch, &hLdrMod, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify it.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, fAvoidWinVerifyTrust, pfWinVerifyTrust, pErrInfo);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc2 = RTLdrClose(hLdrMod); AssertRC(rc2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supHardNtViRdrDestroy(&pNtViRdr->Core);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d (%ls)%s\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync 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";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync return supHardenedWinVerifyImageByHandle(hFile, uBuf.UniStr.Buffer, fFlags, false /*fAvoidWinVerifyTrust*/,
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync NULL /*pfWinVerifyTrust*/, pErrInfo);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync}
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif /* IN_RING3 */
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
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
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/**
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Initializes the windows paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic void supHardenedWinInitImageVerifierWinPaths(void)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync{
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Windows paths that we're interested in.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync static const struct
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUPSYSROOTDIRBUF *pNtPath;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync WCHAR const *pwszRegValue;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync const char *pszLogName;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync } s_aPaths[] =
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_ProgramFilesNtPath, L"ProgramFilesDir", "ProgDir" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_CommonFilesNtPath, L"CommonFilesDir", "ComDir" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# ifdef RT_ARCH_AMD64
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_ProgramFilesX86NtPath, L"ProgramFilesDir (x86)", "ProgDir32" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_CommonFilesX86NtPath, L"CommonFilesDir (x86)", "ComDir32" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync# endif
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync };
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Open the registry key containing the paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync UNICODE_STRING NtName = RTNT_CONSTANT_UNISTR(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync OBJECT_ATTRIBUTES ObjAttr;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync HANDLE hKey;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjAttr);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Loop over the paths and resolve their NT paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Query the value first.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync UNICODE_STRING ValueName;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ValueName.Buffer = (WCHAR *)s_aPaths[i].pwszRegValue;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ValueName.Length = (USHORT)(RTUtf16Len(s_aPaths[i].pwszRegValue) * sizeof(WCHAR));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ValueName.MaximumLength = ValueName.Length + sizeof(WCHAR);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync union
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync uint8_t abPadding[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR) * 128];
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync uint64_t uAlign;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync } uBuf;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ULONG cbActual = 0;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR), &cbActual);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Must be a simple string value, terminate it.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( uBuf.PartialInfo.Type == REG_EXPAND_SZ
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync || uBuf.PartialInfo.Type == REG_SZ)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Expand any environment variable references before opening it.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * We use the result buffer as storage for the expaneded path,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * reserving space for the windows name space prefix.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync UNICODE_STRING Src;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.Buffer = (WCHAR *)uBuf.PartialInfo.Data;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.Length = uBuf.PartialInfo.DataLength;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (Src.Length >= sizeof(WCHAR) && Src.Buffer[Src.Length / sizeof(WCHAR) - 1] == '\0')
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.Length -= sizeof(WCHAR);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.MaximumLength = Src.Length + sizeof(WCHAR);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.Buffer[uBuf.PartialInfo.DataLength / sizeof(WCHAR)] = '\0';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->awcBuffer[0] = '\\';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->awcBuffer[1] = '?';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->awcBuffer[2] = '?';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->awcBuffer[3] = '\\';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync UNICODE_STRING Dst;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Buffer = &s_aPaths[i].pNtPath->awcBuffer[4];
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.MaximumLength = sizeof(s_aPaths[i].pNtPath->awcBuffer) - sizeof(WCHAR) * 5;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Length = Dst.MaximumLength;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (uBuf.PartialInfo.Type == REG_EXPAND_SZ)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = RtlExpandEnvironmentStrings_U(NULL, &Src, &Dst, NULL);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync memcpy(Dst.Buffer, Src.Buffer, Src.Length);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Length = Src.Length;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Buffer[Dst.Length / sizeof(WCHAR)] = '\0';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Include the \\??\\ prefix in the result and open the path.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Buffer -= 4;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.Length += 4 * sizeof(WCHAR);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.MaximumLength += 4 * sizeof(WCHAR);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync InitializeObjectAttributes(&ObjAttr, &Dst, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync HANDLE hFile = INVALID_HANDLE_VALUE;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_READ_DATA | SYNCHRONIZE,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync &ObjAttr,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync &Ios,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NULL /* Allocation Size*/,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_ATTRIBUTE_NORMAL,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_OPEN,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync | FILE_SYNCHRONOUS_IO_NONALERT,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NULL /*EaBuffer*/,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync 0 /*EaLength*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = Ios.Status;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Query the real NT name.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ULONG cbIgn;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = NtQueryObject(hFile,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync ObjectNameInformation,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync sizeof(*s_aPaths[i].pNtPath) - sizeof(WCHAR),
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync &cbIgn);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (s_aPaths[i].pNtPath->UniStr.Length > 0)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /* Make sure it's terminated.*/
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Buffer[s_aPaths[i].pNtPath->UniStr.Length / sizeof(WCHAR)] = '\0';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s:%*s %ls\n", s_aPaths[i].pszLogName, 9 - strlen(s_aPaths[i].pszLogName), "",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Buffer));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtQueryObject returned empty string\n", s_aPaths[i].pszLogName));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = STATUS_INVALID_PARAMETER;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtQueryObject failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NtClose(hFile);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtCreateFile failed: %#x (%ls)\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pszLogName, rcNt, Dst.Buffer));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: RtlExpandEnvironmentStrings_U failed: %#x (%ls)\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pszLogName, rcNt, Src.Buffer));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: type mismatch: %#x\n", s_aPaths[i].pszLogName, uBuf.PartialInfo.Type));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = STATUS_INVALID_PARAMETER;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtQueryValueKey failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /* Stub the entry on failure. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (!NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Length = 0;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Buffer = NULL;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NtClose(hKey);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync else
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("NtOpenKey(%ls) failed: %#x\n", NtName.Buffer, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /* Stub all the entries on failure. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Length = 0;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync s_aPaths[i].pNtPath->UniStr.Buffer = NULL;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync}
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_EVEN_MORE */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
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 {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("System32: %ls\n", g_System32NtPath.UniStr.Buffer));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("WinSxS: %ls\n", g_WinSxSNtPath.UniStr.Buffer));
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync supHardenedWinInitImageVerifierWinPaths();
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync
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
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync#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)
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync#else
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync if (RT_SUCCESS(rc))
1a42673c3eb659db7687e89abd0951582ee8ae0dvboxsync#endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_abSUPBuildCert, g_cbSUPBuildCert, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /*
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Finally initialize known SIDs that we use.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SID_IDENTIFIER_AUTHORITY s_NtAuth = SECURITY_NT_AUTHORITY;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = RtlInitializeSid(&g_TrustedInstallerSid, &s_NtAuth, SECURITY_SERVICE_ID_RID_COUNT);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if (NT_SUCCESS(rcNt))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync {
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 0) = SECURITY_SERVICE_ID_BASE_RID;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 1) = 956008885;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 2) = 3418522649;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 3) = 1831038044;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 4) = 1853292631;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync *RtlSubAuthoritySid(&g_TrustedInstallerSid, 5) = 2271478464;
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync rcNt = RtlInitializeSid(&g_LocalSystemSid, &s_NtAuth, 1);
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync if (NT_SUCCESS(rcNt))
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync {
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync *RtlSubAuthoritySid(&g_LocalSystemSid, 0) = SECURITY_LOCAL_SYSTEM_RID;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync rcNt = RtlInitializeSid(&g_AdminsGroupSid, &s_NtAuth, 2);
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync if (NT_SUCCESS(rcNt))
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync {
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 1) = DOMAIN_ALIAS_RID_ADMINS;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync return VINF_SUCCESS;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync }
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rc = RTErrConvertFromNtStatus(rcNt);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync }
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{
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync char szSubject[512];
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync szSubject[sizeof(szSubject) - 1] = '\0';
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync RTCrX509Name_FormatAsString(&pCert->TbsCertificate.Subject, szSubject, sizeof(szSubject) - 1, NULL);
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check that it's a plausible root certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!RTCrX509Certificate_IsSelfSigned(pCert))
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - not-self-signed: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync
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) )
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-cert-sign: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( pCert->TbsCertificate.T3.pBasicConstraints
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !pCert->TbsCertificate.T3.pBasicConstraints->CA.fValue)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-CA: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits < 256) /* mostly for u64KeyId reading. */
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - key too small: %u bits %s\n",
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync uint64_t const u64KeyId = pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.uBits.pu64[1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync# if 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync * 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))
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync# else
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync /*
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync * Blacklist approach.
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync */
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync static struct
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync uint64_t u64KeyId;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync const char *pszName;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync } const s_aUnwanted[] =
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync { UINT64_C(0xffffffffffffffff), "C=US, O=U.S. Robots and Mechanical Men, Inc., OU=V.I.K.I." }, /* dummy entry */
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync };
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync uint32_t i = RT_ELEMENTS(s_aUnwanted);
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync while (i-- > 0)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync if ( s_aUnwanted[i].u64KeyId == u64KeyId
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync || s_aUnwanted[i].u64KeyId == UINT64_MAX)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync if (RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, s_aUnwanted[i].pszName))
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync {
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - blacklisted: %#llx %s\n", u64KeyId, szSubject));
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync }
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync return true;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync/**
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Loads a module in the system32 directory.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync *
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @returns Module handle on success. Won't return on faliure.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pszName The name of the DLL to load.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncDECLHIDDEN(HMODULE) supR3HardenedWinLoadSystem32Dll(const char *pszName)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync{
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync WCHAR wszName[200+60];
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UINT cwcDir = GetSystemDirectoryW(wszName, RT_ELEMENTS(wszName) - 60);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync wszName[cwcDir] = '\\';
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUtf16CopyAscii(&wszName[cwcDir + 1], RT_ELEMENTS(wszName) - cwcDir, pszName);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync DWORD fFlags = 0;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags = LOAD_LIBRARY_SEARCH_SYSTEM32;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync HMODULE hMod = LoadLibraryExW(wszName, NULL, fFlags);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if ( hMod == NULL
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && fFlags
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 2)
30f07af559efcbd967e801903746fc21f81ee533vboxsync && RtlGetLastWin32Error() == ERROR_INVALID_PARAMETER)
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync {
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync fFlags = 0;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync hMod = LoadLibraryExW(wszName, NULL, fFlags);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync }
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (hMod == NULL)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error loading '%s': %u [%ls]", pszName, RtlGetLastWin32Error(), wszName);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync return hMod;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync}
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
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 */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncstatic void supR3HardenedWinRetrieveTrustedRootCAs(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cAdded = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Load crypt32.dll and resolve the APIs we need.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync 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); \
30f07af559efcbd967e801903746fc21f81ee533vboxsync 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 {
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync RTERRINFOSTATIC StaticErrInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTASN1CURSORPRIMARY PrimaryCursor;
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync RTAsn1CursorInitPrimary(&PrimaryCursor, pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded,
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync RTErrInfoInitStatic(&StaticErrInfo),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "CurCtx");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCRX509CERTIFICATE MyCert;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &MyCert, "Cert");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (supR3HardenedWinIsDesiredRootCA(&MyCert))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRC(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertRC(rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cAdded++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTCrX509Certificate_Delete(&MyCert);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync /* XP root certificate "C&W HKT SecureNet CA SGC Root" has non-standard validity
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync timestamps, the UTC formatting isn't Zulu time but specifies timezone offsets.
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync Ignore these failures and certificates. */
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync else if (rc != VERR_ASN1_INVALID_UTC_TIME_ENCODING)
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync AssertMsgFailed(("RTCrX509Certificate_DecodeAsn1 failed: rc=%#x: %s\n", rc, StaticErrInfo.szMsg));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pfnCertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_fHaveOtherRoots = true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinRetrieveTrustedRootCAs: cAdded=%u\n", cAdded));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Resolves the WinVerifyTrust API after the process has been verified and
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * installs a thread creation hook.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The WinVerifyTrust API is used in addition our own Authenticode verification
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * code. If the image has the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * set, it will be checked again by the kernel. All our image has this flag set
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * and we require all VBox extensions to have it set as well. In effect, the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * authenticode signature will be checked two or three times.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync *
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * @param pszProgName The program name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(void) supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(const char *pszProgName)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef IN_SUP_HARDENED_R3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Load our the support library DLL that does the thread hooking as the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * security API may trigger the creation of COM worker threads (or
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * whatever they are).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The thread creation hook makes the threads very slippery to debuggers by
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * irreversably disabling most (if not all) debug events for them.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync char szPath[RTPATH_MAX];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxSupLib.DLL"));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync suplibHardenedStrCat(szPath, "/VBoxSupLib.DLL");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HMODULE hSupLibMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, true /*fSystem32Only*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hSupLibMod == NULL)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error loading '%s': %u", szPath, RtlGetLastWin32Error());
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync /*
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync * Allocate TLS entry for WinVerifyTrust recursion prevention.
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync */
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync DWORD iTls = TlsAlloc();
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync if (iTls != TLS_OUT_OF_INDEXES)
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync g_iTlsWinVerifyTrustRecursion = iTls;
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync else
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedError(RtlGetLastWin32Error(), false /*fFatal*/, "TlsAlloc failed");
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * Resolve the imports we need.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define RESOLVE_CRYPT_API(a_Name, a_pfnType, a_uMinWinVer) \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do { \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_pfn##a_Name = (a_pfnType)GetProcAddress(hWintrust, #a_Name); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_pfn##a_Name == NULL && (a_uMinWinVer) < g_uNtVerCombined) \
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error locating '" #a_Name "' in 'Wintrust.dll': %u", RtlGetLastWin32Error()); \
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust = (PFNWINVERIFYTRUST)GetProcAddress(hWintrust, "WinVerifyTrust");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!pfnWinVerifyTrust)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error locating 'WinVerifyTrust' in 'Wintrust.dll': %u", RtlGetLastWin32Error());
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminAcquireContext, PFNCRYPTCATADMINACQUIRECONTEXT, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminEnumCatalogFromHash, PFNCRYPTCATADMINENUMCATALOGFROMHASH, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminReleaseCatalogContext, PFNCRYPTCATADMINRELEASECATALOGCONTEXT, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminReleaseContext, PFNCRYPTCATDADMINRELEASECONTEXT, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATCatalogInfoFromContext, PFNCRYPTCATCATALOGINFOFROMCONTEXT, 0);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminAcquireContext2, PFNCRYPTCATADMINACQUIRECONTEXT2, SUP_NT_VER_W80);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle2, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2, SUP_NT_VER_W80);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync# ifdef IN_SUP_HARDENED_R3
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * Load bcrypt.dll and instantiate a few hashing and signing providers to
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * make sure the providers are cached for later us. Avoid recursion issues.
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync HMODULE hBCrypt = supR3HardenedWinLoadSystem32Dll("bcrypt.dll");
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (hBCrypt)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PFNBCRYPTOPENALGORTIHMPROVIDER pfnOpenAlgoProvider;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync pfnOpenAlgoProvider = (PFNBCRYPTOPENALGORTIHMPROVIDER)GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider");
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (pfnOpenAlgoProvider)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("bcrypt.dll loaded at %p, BCryptOpenAlgorithmProvider at %p, preloading providers:\n",
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync hBCrypt, pfnOpenAlgoProvider));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync# define PRELOAD_ALGO_PROVIDER(a_Name) \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync do { \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync BCRYPT_ALG_HANDLE hAlgo = NULL; \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync NTSTATUS rcNt = pfnOpenAlgoProvider(&hAlgo, a_Name, NULL, 0); \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("%sBCryptOpenAlgorithmProvider(,'%ls',0,0) -> %#x (hAlgo=%p)\n", \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync NT_SUCCESS(rcNt) ? " " : "warning: ", a_Name, rcNt, hAlgo)); \
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync } while (0)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_MD2_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_MD4_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_MD5_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_SHA1_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_SHA256_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_SHA512_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_RSA_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PRELOAD_ALGO_PROVIDER(BCRYPT_DSA_ALGORITHM);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync# undef PRELOAD_ALGO_PROVIDER
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Warning! Failed to find BCryptOpenAlgorithmProvider in bcrypt.dll\n"));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Warning! Failed to load bcrypt.dll\n"));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /*
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * Call the verification API on ourselves and ntdll to make sure it works
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * and loads more stuff it needs, preventing any recursive fun we'd run
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * into after we set g_pfnWinVerifyTrust.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTERRINFOSTATIC ErrInfoStatic;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTErrInfoInitStatic(&ErrInfoStatic);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardNtViCallWinVerifyTrust(NULL, g_SupLibHardenedExeNtPath.UniStr.Buffer, 0,
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync &ErrInfoStatic.Core, pfnWinVerifyTrust, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync supR3HardenedFatalMsg(pszProgName, kSupInitOp_Integrity, rc,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync "WinVerifyTrust failed on stub executable: %s", ErrInfoStatic.szMsg);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 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. */
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync supR3HardNtViCallWinVerifyTrust(NULL, L"\\SystemRoot\\System32\\ntdll.dll", 0, NULL, pfnWinVerifyTrust, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardNtViCallWinVerifyTrustCatFile(NULL, L"\\SystemRoot\\System32\\ntdll.dll", 0, NULL, pfnWinVerifyTrust);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_pfnWinVerifyTrust = pfnWinVerifyTrust;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync SUP_DPRINTF(("g_pfnWinVerifyTrust=%p\n", pfnWinVerifyTrust));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync# ifdef IN_SUP_HARDENED_R3
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync /*
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Load some problematic DLLs into the verifier cache to prevent
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * recursion trouble.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\crypt32.dll");
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\Wintrust.dll");
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync# endif
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Now, get trusted root CAs so we can verify a broader scope of signatures.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinRetrieveTrustedRootCAs();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViNtToWinPath(PCRTUTF16 pwszNtName, PCRTUTF16 *ppwszWinPath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PRTUTF16 pwszWinPathBuf, size_t cwcWinPathBuf)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const RTUTF16 s_wszPrefix[] = L"\\\\.\\GLOBALROOT";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (*pwszNtName != '\\' && *pwszNtName != '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_PATH_DOES_NOT_START_WITH_ROOT;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t cwcNtName = RTUtf16Len(pwszNtName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_ELEMENTS(s_wszPrefix) + cwcNtName > cwcWinPathBuf)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VERR_FILENAME_TOO_LONG;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pwszWinPathBuf, s_wszPrefix, sizeof(s_wszPrefix));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(&pwszWinPathBuf[sizeof(s_wszPrefix) / sizeof(RTUTF16) - 1], pwszNtName, (cwcNtName + 1) * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *ppwszWinPath = pwszWinPathBuf;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calls WinVerifyTrust to verify an PE image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VBox 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 pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pfnWinVerifyTrust Pointer to the API.
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync * @param phrcWinVerifyTrust Where to WinVerifyTrust error status on failure,
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync * optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust, HRESULT *phrcWinVerifyTrust)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync if (phrcWinVerifyTrust)
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync *phrcWinVerifyTrust = S_OK;
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the name into a Windows name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wszWinPathBuf[MAX_PATH];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTUTF16 pwszWinPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrust: rc=%Rrc '%ls'", rc, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct input parameters and call the API.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINTRUST_FILE_INFO FileInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(FileInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FileInfo.cbStruct = sizeof(FileInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FileInfo.pcwszFilePath = pwszWinPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FileInfo.hFile = hFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync GUID PolicyActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINTRUST_DATA TrustData;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.cbStruct = sizeof(TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwStateAction = WTD_STATEACTION_VERIFY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwUIChoice = WTD_UI_NONE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwUnionChoice = WTD_CHOICE_FILE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.pFile = &FileInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hrc == S_OK)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Failed. Format a nice error message.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# ifdef DEBUG_bird
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync if (hrc != CERT_E_CHAINING /* Un-updated vistas, XPs, ++ */)
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync __debugbreak();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync# endif
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszErrConst = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync switch (hrc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_SYSTEM_ERROR: pszErrConst = "TRUST_E_SYSTEM_ERROR"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_NO_SIGNER_CERT: pszErrConst = "TRUST_E_NO_SIGNER_CERT"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_COUNTER_SIGNER: pszErrConst = "TRUST_E_COUNTER_SIGNER"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_CERT_SIGNATURE: pszErrConst = "TRUST_E_CERT_SIGNATURE"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_TIME_STAMP: pszErrConst = "TRUST_E_TIME_STAMP"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_BAD_DIGEST: pszErrConst = "TRUST_E_BAD_DIGEST"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_BASIC_CONSTRAINTS: pszErrConst = "TRUST_E_BASIC_CONSTRAINTS"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_FINANCIAL_CRITERIA: pszErrConst = "TRUST_E_FINANCIAL_CRITERIA"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_PROVIDER_UNKNOWN: pszErrConst = "TRUST_E_PROVIDER_UNKNOWN"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_ACTION_UNKNOWN: pszErrConst = "TRUST_E_ACTION_UNKNOWN"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_SUBJECT_FORM_UNKNOWN: pszErrConst = "TRUST_E_SUBJECT_FORM_UNKNOWN"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_SUBJECT_NOT_TRUSTED: pszErrConst = "TRUST_E_SUBJECT_NOT_TRUSTED"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_NOSIGNATURE: pszErrConst = "TRUST_E_NOSIGNATURE"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_FAIL: pszErrConst = "TRUST_E_FAIL"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case TRUST_E_EXPLICIT_DISTRUST: pszErrConst = "TRUST_E_EXPLICIT_DISTRUST"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case CERT_E_CHAINING: pszErrConst = "CERT_E_CHAINING"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case CERT_E_REVOCATION_FAILURE: pszErrConst = "CERT_E_REVOCATION_FAILURE"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case CRYPT_E_FILE_ERROR: pszErrConst = "CRYPT_E_FILE_ERROR"; break;
a6c871653045073d6ef74d0589de345ae62b607dvboxsync case CRYPT_E_REVOKED: pszErrConst = "CRYPT_E_REVOKED"; break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pszErrConst)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_UNSUPPORTED_ARCH,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "WinVerifyTrust failed with hrc=%s on '%ls'", pszErrConst, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_UNSUPPORTED_ARCH,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "WinVerifyTrust failed with hrc=%Rhrc on '%ls'", hrc, pwszName);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrust: WinVerifyTrust failed with %#x (%s) on '%ls'\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync hrc, pszErrConst, pwszName));
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync if (phrcWinVerifyTrust)
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync *phrcWinVerifyTrust = hrc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* clean up state data. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwStateAction = WTD_STATEACTION_CLOSE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FileInfo.hFile = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calls WinVerifyTrust to verify an PE image via catalog files.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns VBox 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 pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pfnWinVerifyTrust Pointer to the API.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrustCatFile(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hFile=%p pwszName=%ls\n", hFile, pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the name into a Windows name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wszWinPathBuf[MAX_PATH];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PCRTUTF16 pwszWinPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_FAILURE(rc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrustCatFile: rc=%Rrc '%ls'", rc, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the file if we didn't get a handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HANDLE hFileClose = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hFile == RTNT_INVALID_HANDLE_VALUE || hFile == NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hFile = RTNT_INVALID_HANDLE_VALUE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync UNICODE_STRING NtName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Buffer = (PWSTR)pwszName;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OBJECT_ATTRIBUTES ObjAttr;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtCreateFile(&hFile,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &ObjAttr,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &Ios,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NULL /* Allocation Size*/,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_ATTRIBUTE_NORMAL,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_SHARE_READ,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_OPEN,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_NON_DIRECTORY_FILE | 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 return RTErrInfoSetF(pErrInfo, RTErrConvertFromNtStatus(rcNt),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtCreateFile returned %#x opening '%ls'.", rcNt, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hFileClose = hFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * On Windows 8.0 and later there are more than one digest choice.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync int fNoSignedCatalogFound = -1;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VERR_LDRVI_NOT_SIGNED;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The digest algorithm name. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const WCHAR *pszAlgorithm;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Cached catalog admin handle. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATADMIN volatile hCachedCatAdmin;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } s_aHashes[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { NULL, NULL },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { L"SHA256", NULL },
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aHashes); i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Another loop for dealing with different trust provider policies
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * required for successfully validating different catalog signatures.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync bool fTryNextPolicy;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t iPolicy = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const GUID s_aPolicies[] =
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DRIVER_ACTION_VERIFY, /* Works with microsoft bits. Most frequently used, thus first. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINTRUST_ACTION_GENERIC_VERIFY_V2, /* Works with ATI and other SPC kernel-code signed stuff. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync };
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create a context.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fTryNextPolicy = false;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync bool fFreshContext = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync BOOL fRc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATADMIN hCatAdmin = ASMAtomicXchgPtr(&s_aHashes[i].hCachedCatAdmin, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hCatAdmin)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Cached context %p\n", hCatAdmin));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fFreshContext = false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fRc = TRUE;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsyncl_fresh_context:
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fFreshContext = true;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (g_pfnCryptCATAdminAcquireContext2)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fRc = g_pfnCryptCATAdminAcquireContext2(&hCatAdmin, &s_aPolicies[iPolicy], s_aHashes[i].pszAlgorithm,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync NULL /*pStrongHashPolicy*/, 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync else
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fRc = g_pfnCryptCATAdminAcquireContext(&hCatAdmin, &s_aPolicies[iPolicy], 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: New context %p\n", hCatAdmin));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fRc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hCatAdmin=%p\n", hCatAdmin));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Hash the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync BYTE abHash[SUPHARDNTVI_MAX_CAT_HASH_SIZE];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync DWORD cbHash = sizeof(abHash);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_pfnCryptCATAdminCalcHashFromFileHandle2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fRc = g_pfnCryptCATAdminCalcHashFromFileHandle2(hCatAdmin, hFile, &cbHash, abHash, 0 /*dwFlags*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fRc = g_pfnCryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, abHash, 0 /*dwFlags*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fRc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Produce a string version of it that we can pass to WinVerifyTrust. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RTUTF16 wszDigest[SUPHARDNTVI_MAX_CAT_HASH_SIZE * 2 + 1];
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc2 = RTUtf16PrintHexBytes(wszDigest, RT_ELEMENTS(wszDigest), abHash, cbHash, RTSTRPRINTHEXBYTES_F_UPPER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_SUCCESS(rc2))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: cbHash=%u wszDigest=%ls\n", cbHash, wszDigest));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Enumerate catalog information that matches the hash.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t iCat = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATINFO hCatInfoPrev = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync do
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Get the next match. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATINFO hCatInfo = g_pfnCryptCATAdminEnumCatalogFromHash(hCatAdmin, abHash, cbHash, 0, &hCatInfoPrev);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!hCatInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (!fFreshContext)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync {
30f07af559efcbd967e801903746fc21f81ee533vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Retrying with fresh context (CryptCATAdminEnumCatalogFromHash -> %u; iCat=%#x)\n", RtlGetLastWin32Error(), iCat));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync if (hCatInfoPrev != NULL)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync goto l_fresh_context;
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync }
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync ULONG ulErr = RtlGetLastWin32Error();
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync fNoSignedCatalogFound = ulErr == ERROR_NOT_FOUND && fNoSignedCatalogFound != 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (iCat == 0)
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATAdminEnumCatalogFromHash failed ERRROR_NOT_FOUND (%u)\n", ulErr));
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync else if (iCat == 0)
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATAdminEnumCatalogFromHash failed %u\n", ulErr));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync fNoSignedCatalogFound = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(hCatInfoPrev == NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hCatInfoPrev = hCatInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Call WinVerifyTrust.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync CATALOG_INFO CatInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync CatInfo.cbStruct = sizeof(CatInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync CatInfo.wszCatalogFile[0] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_pfnCryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0 /*dwFlags*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINTRUST_CATALOG_INFO WtCatInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(WtCatInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.cbStruct = sizeof(WtCatInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.dwCatalogVersion = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pcwszMemberTag = wszDigest;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pcwszMemberFilePath = pwszWinPath;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pbCalculatedFileHash = abHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.cbCalculatedFileHash = cbHash;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pcCatalogContext = NULL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WINTRUST_DATA TrustData;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RT_ZERO(TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.cbStruct = sizeof(TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwStateAction = WTD_STATEACTION_VERIFY;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwUIChoice = WTD_UI_NONE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = 0;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.pCatalog = &WtCatInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: WinVerifyTrust => %#x; cat='%ls'; file='%ls'\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync hrc, CatInfo.wszCatalogFile, pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (SUCCEEDED(hrc))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = VINF_SUCCESS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (hrc == TRUST_E_NOSIGNATURE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { /* ignore because it's useless. */ }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else if (hrc == ERROR_INVALID_PARAMETER)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { /* This is returned if the given file isn't found in the catalog, it seems. */ }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_WINTRUST_CAT_FAILURE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "WinVerifyTrust failed with hrc=%#x on '%ls' and .cat-file='%ls'.",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hrc, pwszWinPath, CatInfo.wszCatalogFile);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fTryNextPolicy |= (hrc == CERT_E_UNTRUSTEDROOT);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* clean up state data. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwStateAction = WTD_STATEACTION_CLOSE;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(SUCCEEDED(hrc));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "CryptCATCatalogInfoFromContext failed: %d [file=%s]",
30f07af559efcbd967e801903746fc21f81ee533vboxsync RtlGetLastWin32Error(), pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATCatalogInfoFromContext failed\n"));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync iCat++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (rc == VERR_LDRVI_NOT_SIGNED && iCat < 128);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hCatInfoPrev != NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertFailed();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, rc2, "RTUtf16PrintHexBytes failed: %Rrc", rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "CryptCATAdminCalcHashFromFileHandle[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!ASMAtomicCmpXchgPtr(&s_aHashes[i].hCachedCatAdmin, hCatAdmin, NULL))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertFailed();
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync else
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "CryptCATAdminAcquireContext[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync iPolicy++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while ( fTryNextPolicy
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && iPolicy < RT_ELEMENTS(s_aPolicies));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Only repeat if we've got g_pfnCryptCATAdminAcquireContext2 and can specify the hash algorithm.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_pfnCryptCATAdminAcquireContext2)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (rc != VERR_LDRVI_NOT_SIGNED)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync break;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hFileClose != NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtClose(hFileClose);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync /*
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync * DLLs that are likely candidates for local modifications.
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync */
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if (rc == VERR_LDRVI_NOT_SIGNED)
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync {
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync bool fCoreSystemDll = false;
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync PCRTUTF16 pwsz;
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync uint32_t cwcName = (uint32_t)RTUtf16Len(pwszName);
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync uint32_t cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR);
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync {
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync pwsz = pwszName + cwcOther + 1;
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if ( supHardViUtf16PathIsEqual(pwsz, "uxtheme.dll")
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync || supHardViUtf16PathIsEqual(pwsz, "user32.dll")
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync || supHardViUtf16PathIsEqual(pwsz, "gdi32.dll")
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync || supHardViUtf16PathIsEqual(pwsz, "opengl32.dll")
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "KernelBase.dll"))
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "kernel32.dll"))
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "ntdll.dll"))
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync )
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync {
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if (RTErrInfoIsSet(pErrInfo))
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync RTErrInfoAdd(pErrInfo, rc, "\n");
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync RTErrInfoAddF(pErrInfo, rc, "'%ls' is most likely modified.", pwszName);
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync }
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync }
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync /* Kludge for ancient windows versions we don't want to support but
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync users still wants to use. Keep things as safe as possible without
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync unnecessary effort. Problem is that 3rd party catalog files cannot
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync easily be found. Showstopper for ATI users. */
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync if ( fNoSignedCatalogFound == 1
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync && g_uNtVerCombined < SUP_NT_VER_VISTA
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync && !fCoreSystemDll)
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync {
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync rc = VINF_LDRVI_NOT_SIGNED;
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync }
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync }
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return rc;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync/**
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Verifies the given image using WinVerifyTrust in some way.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync *
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * This is used by supHardenedWinVerifyImageByLdrMod as well as
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * supR3HardenedScreenImage.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync *
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @returns IPRT status code.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @param hFile Handle of the file to verify.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @param pwszName Full NT path to the DLL in question, used for
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * dealing with unsigned system dlls as well as for
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * error/logging.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * actually used.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @param pErrInfo Pointer to error info structure. Optional.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync */
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, int rc,
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync{
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync if (pfWinVerifyTrust)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync *pfWinVerifyTrust = false;
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync /*
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Call the windows verify trust API if we've resolved it and aren't in
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync * some obvious recursion.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync */
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync if (g_pfnWinVerifyTrust != NULL)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync uint32_t const idCurrentThread = RTNtCurrentThreadId();
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Check if loader lock owner. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync struct _RTL_CRITICAL_SECTION volatile *pLoaderLock = NtCurrentPeb()->LoaderLock;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync bool fOwnsLoaderLock = pLoaderLock
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync && pLoaderLock->OwningThread == (HANDLE)(uintptr_t)idCurrentThread
f1f6f0dfb3894c3c606f33186666914daf3213c3vboxsync && pLoaderLock->RecursionCount > 0;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (!fOwnsLoaderLock)
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Check for recursion. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync bool fNoRecursion;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (fNoRecursion)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (fNoRecursion && !fOwnsLoaderLock)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* We can call WinVerifyTrust. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (pfWinVerifyTrust)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync *pfWinVerifyTrust = true;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (rc != VERR_LDRVI_NOT_SIGNED)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (rc == VINF_LDRVI_NOT_SIGNED)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo,
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync g_pfnWinVerifyTrust);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = rc2;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync AssertFailed();
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = VERR_LDRVI_NOT_SIGNED;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else if (RT_SUCCESS(rc))
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync HRESULT hrcWinVerifyTrust;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust,
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync &hrcWinVerifyTrust);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* DLLs signed with special roots, like "Microsoft Digital Media Authority 2005",
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync may fail here because the root cert is not in the normal certificate stores
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync (if any). Our verification code has the basics of these certificates included
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync and can verify them, which is why we end up here instead of in the
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync VINF_LDRVI_NOT_SIGNED case above. Current workaround is to do as above.
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync (Intel graphics driver DLLs, like igdusc64.dll. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if ( RT_FAILURE(rc)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync && hrcWinVerifyTrust == CERT_E_CHAINING
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION))
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync }
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync else
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync {
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync AssertMsg(RT_FAILURE_NP(rc2),
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>"));
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync }
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Unwind recursion. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (g_iTlsWinVerifyTrustRecursion != UINT32_MAX)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0);
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync ASMAtomicWriteU32(&g_idActiveThread, UINT32_MAX);
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /*
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * No can do.
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync */
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync else
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Detected loader lock ownership: rc=%Rrc '%ls'.\n", rc, pwszName));
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync }
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync return rc;
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync}
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync/**
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Checks if WinVerifyTrust is callable on the current thread.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync *
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Used by the main code to figure whether it makes sense to try revalidate an
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * image that hasn't passed thru WinVerifyTrust yet.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync *
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @returns true if callable on current thread, false if not.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync */
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsyncDECLHIDDEN(bool) supHardenedWinIsWinVerifyTrustCallable(void)
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync{
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync return g_pfnWinVerifyTrust != NULL
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync && ( g_iTlsWinVerifyTrustRecursion != UINT32_MAX
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync ? (uintptr_t)TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0
30f07af559efcbd967e801903746fc21f81ee533vboxsync : g_idActiveThread != RTNtCurrentThreadId() );
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync}
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/**
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initializes g_uNtVerCombined and g_NtVerInfo.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Called from suplibHardenedWindowsMain and suplibOsInit.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supR3HardenedWinInitVersion(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /*
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the windows version. Use RtlGetVersion as GetVersionExW and
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * GetVersion might not be telling the whole truth (8.0 on 8.1 depending on
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the application manifest).
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync OSVERSIONINFOEXW NtVerInfo;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync RT_ZERO(NtVerInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtVerInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&NtVerInfo)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync {
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync RT_ZERO(NtVerInfo);
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync PPEB pPeb = NtCurrentPeb();
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NtVerInfo.dwMajorVersion = pPeb->OSMajorVersion;
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NtVerInfo.dwMinorVersion = pPeb->OSMinorVersion;
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync NtVerInfo.dwBuildNumber = pPeb->OSPlatformId;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync }
fd658895339cb48b2ba581b1a1141aea39009ff7vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_uNtVerCombined = SUP_MAKE_NT_VER_COMBINED(NtVerInfo.dwMajorVersion, NtVerInfo.dwMinorVersion, NtVerInfo.dwBuildNumber,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtVerInfo.wServicePackMajor, NtVerInfo.wServicePackMinor);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING3 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync