13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox Support Library/Driver - Hardened Image Verification, Windows.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The contents of this file may alternatively be used under the terms
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * of the Common Development and Distribution License Version 1.0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * CDDL are applicable instead of those of the GPL.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * You may elect to license modified versions of this file under the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * terms and conditions of either the GPL or the CDDL or both.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Defined Constants And Macros *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
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. */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#if defined(VBOX_PERMIT_EVEN_MORE) && !defined(VBOX_PERMIT_MORE)
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# error "VBOX_PERMIT_EVEN_MORE without VBOX_PERMIT_MORE!"
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Structures and Typedefs *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
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,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef HCATINFO (WINAPI *PFNCRYPTCATADMINENUMCATALOGFROMHASH)(HCATADMIN hCatAdmin, BYTE *pbHash, DWORD cbHash,
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);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef HCERTSTORE (WINAPI *PFNCERTOPENSTORE)(PCSTR pszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef BOOL (WINAPI *PFNCERTCLOSESTORE)(HCERTSTORE hCertStore, DWORD dwFlags);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsynctypedef PCCERT_CONTEXT (WINAPI *PFNCERTENUMCERTIFICATESINSTORE)(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsynctypedef NTSTATUS (WINAPI *PFNBCRYPTOPENALGORTIHMPROVIDER)(BCRYPT_ALG_HANDLE *phAlgo, PCWSTR pwszAlgoId,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Global Variables *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The build certificate. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store for root software publisher certificates. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Store for root NT kernel certificates. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic RTCRSTORE g_hNtKernelRootStore = NIL_RTCRSTORE;
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/** The full \\SystemRoot\\System32 path. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** The full \\SystemRoot\\WinSxS path. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Program Files' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Program Files (x86)' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Common Files' path. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync/** The full 'Common Files (x86)' path. */
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_MORE*/
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic union
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync/** The TrustedInstaller SID (Vista+). */
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync/** Local system ID (S-1-5-21). */
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync/** Builtin Administrators group alias (S-1-5-32-544). */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Set after we've retrived other SPC root certificates from the system. */
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. */
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync/** Timestamp hack working around issues with old DLLs that we ship.
2f8175b63b0fa558fb56df987387875c2dda6299vboxsync * See supHardenedWinVerifyImageByHandle() for details. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** Pointer to WinVerifyTrust. */
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;
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;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Internal Functions *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
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/** @copydoc RTLDRREADER::pfnRead */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Check for type overflow (paranoia). */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Make sure the event semaphore is reset (normally we don't use one). */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* Perform the read. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync /* In ring-0 the handles shall be synchronized and not alertable. */
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync AssertMsg(rcNt == STATUS_SUCCESS || !NT_SUCCESS(rcNt), ("%#x\n", rcNt));
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 rcNt = NtWaitForSingleObject(pNtViRdr->hEvent ? pNtViRdr->hEvent : pNtViRdr->hFile, FALSE /*Alertable*/, NULL);
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 "supHardNtViRdrRead: Only got %#zx bytes when requesting %#zx bytes at %#llx in '%s'.\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnTell */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(RTFOFF) supHardNtViRdrTell(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnSize */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(RTFOFF) supHardNtViRdrSize(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnLogName */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(const char *) supHardNtViRdrLogName(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnMap */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrMap(PRTLDRREADER pReader, const void **ppvBits)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnUnmap */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrUnmap(PRTLDRREADER pReader, const void *pvBits)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/** @copydoc RTLDRREADER::pfnDestroy */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViRdrDestroy(PRTLDRREADER pReader)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Creates a loader reader instance for the given NT file handle.
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.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsyncDECLHIDDEN(int) supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Try determine the size of the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NTSTATUS rcNt = NtQueryInformationFile(hFile, &Ios, &StdInfo, sizeof(StdInfo), FileStandardInformation);
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 rcNt = NtQueryInformationFile(hFile, &Ios, &fMode, sizeof(fMode), FileModeInformation);
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync if (!(fMode & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)))
5a62252a15cf89959ce9f8d309351546c8e631ffvboxsync rcNt = NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calc the file name length and allocate memory for the reader instance.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync PSUPHNTVIRDR pNtViRdr = (PSUPHNTVIRDR)RTMemAllocZ(sizeof(*pNtViRdr) + cchFilename);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize the structure.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTUtf16ToUtf8Ex(pwszName, RTSTR_MAX, &pszName, cchFilename + 1, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertStmt(RT_SUCCESS(rc), pNtViRdr->szFilename[0] = '\0');
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync * Checks if the file is owned by TrustedInstaller (Vista+) or similar.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @returns true if owned by TrustedInstaller of pre-Vista, false if not.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @param hFile The handle to the file.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * @param pwszName The name of the file.
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsyncstatic bool supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(HANDLE hFile, PCRTUTF16 pwszName)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return true;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Get the ownership information.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = NtQuerySecurityObject(hFile, OWNER_SECURITY_INFORMATION, &uBuf.Abs, sizeof(uBuf), &cbActual);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("NtQuerySecurityObject failed with rcNt=%#x on '%ls'\n", rcNt, pwszName));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync return false;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Check the owner.
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).
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 * 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 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 return true;
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync return true;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync SUP_DPRINTF(("%ls: Owner is administrators group.\n", pwszName));
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync return true;
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;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII path compare.
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.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsyncDECLHIDDEN(bool) supHardViUtf16PathIsEqualEx(PCRTUTF16 pawcLeft, size_t cwcLeft, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * Simple case insensitive UTF-16 / ASCII path compare.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @returns true if equal, false if not.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param pwszLeft The UTF-16 path string.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync * @param pszRight The ascii string.
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsyncstatic bool supHardViUtf16PathIsEqual(PCRTUTF16 pwszLeft, const char *pszRight)
817577d2c4d6dee709de7a92d3bb7d0aeedae9aevboxsync return supHardViUtf16PathIsEqualEx(pwszLeft, RTSTR_MAX, pszRight);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII ends-with path predicate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if equal, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pszSuffix The ascii suffix string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supHardViUtf16PathEndsWith(PCRTUTF16 pwsz, const char *pszSuffix)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return supHardViUtf16PathIsEqual(pwsz + cwc - cchSuffix, pszSuffix);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Simple case insensitive UTF-16 / ASCII starts-with path predicate.
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.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncstatic bool supHardViUtf16PathStartsWithAscii(PCRTUTF16 pwszLeft, const char *pszRight)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (b == '/')
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
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.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(bool) supHardViUtf16PathStartsWithEx(PCRTUTF16 pwszLeft, uint32_t cwcLeft,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync PCRTUTF16 pwszRight, uint32_t cwcRight, bool fCheckSlash)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* See if we can get away with a case sensitive compare first. */
361ef195c21ec36df0a44797ce62edb13d649d06vboxsync if (memcmp(pwszLeft, pwszRight, cwcRight * sizeof(RTUTF16)) == 0)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* No luck, do a slow case insensitive comapre. */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync while (cLeft-- > 0)
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync wcLeft = wcLeft < 0x80 ? wcLeft == '/' ? '\\' : RT_C_TO_LOWER(wcLeft) : wcLeft;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync wcRight = wcRight < 0x80 ? wcRight == '/' ? '\\' : RT_C_TO_LOWER(wcRight) : wcRight;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync /* Check for slash following the prefix, if request. */
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return true;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync * Simple case insensitive UNICODE_STRING starts-with path predicate.
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.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(bool) supHardViUniStrPathStartsWithUniStr(UNICODE_STRING const *pUniStrLeft, UNICODE_STRING const *pUniStrRight,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync return supHardViUtf16PathStartsWithEx(pUniStrLeft->Buffer, pUniStrLeft->Length / sizeof(WCHAR),
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync pUniStrRight->Buffer, pUniStrRight->Length / sizeof(WCHAR), fCheckSlash);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Counts slashes in the given UTF-8 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns Number of slashes.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pwsz The UTF-16 path string.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic uint32_t supHardViUtf16PathCountSlashes(PCRTUTF16 pwsz)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * Checks if the path goes into %windir%\apppatch\.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @returns true if apppatch, false if not.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * @param pwszPath The path to examine.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsyncDECLHIDDEN(bool) supHardViIsAppPatchDir(PCRTUTF16 pwszPath, uint32_t cwcName)
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync uint32_t cwcWinDir = (g_System32NtPath.UniStr.Length - sizeof(L"System32")) / sizeof(WCHAR);
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (memcmp(pwszPath, g_System32NtPath.UniStr.Buffer, cwcWinDir * sizeof(WCHAR)))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (!supHardViUtf16PathStartsWithAscii(&pwszPath[cwcWinDir], "\\AppPatch\\"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Checks if the unsigned DLL is fine or not.
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..
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic int supHardNtViCheckIfNotSignedOk(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, uint32_t fFlags, HANDLE hFile, int rc)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (fFlags & (SUPHNTVI_F_REQUIRE_BUILD_CERT | SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Version macros.
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 * The System32 directory.
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 * 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 uint32_t cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
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))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Core DLLs. */
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 if (supHardViUtf16PathIsEqual(pwsz, "apphelp.dll"))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
e352c25b01398e5503235fed02436cb2992f1021vboxsync if (supHardViUtf16PathIsEqual(pwsz, "verifier.dll"))
e352c25b01398e5503235fed02436cb2992f1021vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (uNtVer >= SUP_NT_VER_W70) /* hard limit: user32.dll is unwanted prior to w7. */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_MAKE_NT_VER_SIMPLE(6, 4) ? VINF_LDRVI_NOT_SIGNED : rc;
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync return uNtVer < SUP_NT_VER_W81 ? VINF_LDRVI_NOT_SIGNED : rc;
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. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* IN_RING0 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The WinSxS white list.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Just like with System32 there are potentially a number of DLLs that
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * could be required from WinSxS.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cwcOther = g_WinSxSNtPath.UniStr.Length / sizeof(WCHAR);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_WinSxSNtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* The WinSxS layout means everything worth loading is exactly one level down. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cSlashes = supHardViUtf16PathCountSlashes(pwsz);
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync /* Must be owned by trusted installer. */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* !IN_RING0 */
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync * AppPatch whitelist.
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR); /* ASSUMES System32 is called System32. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AppPatch64\\AcGenral.dll"))
02a86c3f55161b12d393bdf96b01c0086fd42313vboxsync if (supHardViUtf16PathIsEqual(pwsz, "AcGenral.dll"))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# endif /* !VBOX_PERMIT_EVEN_MORE */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync#endif /* VBOX_PERMIT_MORE */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# if defined(VBOX_PERMIT_MORE) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Program files and common files.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Permit anything that's signed and correctly installed.
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 || 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*/)
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync if ( !(fFlags & SUPHNTVI_F_TRUSTED_INSTALLER_OWNER)
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync && !supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync# elif defined(VBOX_PERMIT_MORE) && defined(VBOX_PERMIT_EVEN_MORE)
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Anything that's owned by the trusted installer.
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync || supHardNtViCheckIsOwnedByTrustedInstallerOrSimilar(hFile, pwszName))
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync#endif /* !IN_RING0 */
cd2274c977e1b722b535e4f601a324e8029b5e43vboxsync * Not permitted.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @callback_method_impl{RTCRPKCS7VERIFYCERTCALLBACK,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Standard code signing. Use this for Microsoft SPC.}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViCertVerifyCallback(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
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 if (RTCrX509Certificate_Compare(pCert, &g_BuildX509Cert) == 0) /* healthy paranoia */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_BUILD_CERT_IPE, "Not valid kernel code signature.");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Standard code signing capabilites required.
8cba79d647bd84eb8b7d9eb39ac77cc85ae247c5vboxsync int rc = RTCrPkcs7VerifyCertCallbackCodeSigning(pCert, hCertPaths, fFlags, NULL, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * If kernel signing, a valid certificate path must be anchored by the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * microsoft kernel signing root certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint32_t cPaths = RTCrX509CertPathsGetPathCount(hCertPaths);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrX509CertPathsQueryPathInfo(hCertPaths, iPath, &fTrusted, NULL /*pcNodes*/, &pSubject, &pPublicKeyInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Search the kernel signing root store for a matching anchor.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280(g_hNtKernelRootStore, pSubject, &Search);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while ((pCertCtx = RTCrStoreCertSearchNext(g_hNtKernelRootStore, &Search)) != NULL)
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync PCRTCRX509SUBJECTPUBLICKEYINFO pCertPubKeyInfo = NULL;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync pCertPubKeyInfo = &pCertCtx->pCert->TbsCertificate.SubjectPublicKeyInfo;
8ca9bc7876e76fd62c489a54b9a5acf26cace946vboxsync && RTCrX509SubjectPublicKeyInfo_Compare(pCertPubKeyInfo, pPublicKeyInfo) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc2 = RTCrStoreCertSearchDestroy(g_hNtKernelRootStore, &Search); AssertRC(rc2);
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 * More requirements? NT5 build lab?
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic DECLCALLBACK(int) supHardNtViCallback(RTLDRMOD hLdrMod, RTLDRSIGNATURETYPE enmSignature,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check out the input.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync Assert(pNtViRdr->Core.uMagic == RTLDRREADER_MAGIC);
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 * If special certificate requirements, check them out before validating
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * the signature.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!RTCrX509Certificate_MatchIssuerAndSerialNumber(&g_BuildX509Cert,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSet(pErrInfo, VERR_SUP_VP_NOT_SIGNED_WITH_BUILD_CERT, "Not signed with the build certificate.");
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 RTTimeSpecSetSeconds(&ValidationTime, pNtViRdr->uTimestamp);
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;
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);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Verifies the given loader image.
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 * @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.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync bool fAvoidWinVerifyTrust, bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync /* Check that the caller has performed the necessary library initialization. */
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (!RTCrX509Certificate_IsPresent(&g_BuildX509Cert))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync "supHardenedWinVerifyImageByHandle: supHardenedWinInitImageVerifier was not called.");
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Check the trusted installer bit first, if requested as it's somewhat
90624af27b0e648b68167bd3b332d0e3b1d18ab1vboxsync * cheaper than the rest.
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 * 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 * 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).
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))
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));
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_NOT_OWNED_BY_TRUSTED_INSTALLER,
f26952c8159edeeef1d0e4e585d2b57c173a0235vboxsync "supHardenedWinVerifyImageByHandle: TrustedInstaller is not the owner of '%ls'.", pwszName);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Verify it.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * The PKCS #7 SignedData signature is checked in the callback. Any
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * signing certificate restrictions are also enforced there.
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 * 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 int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp));
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Microsoft doesn't sign a whole bunch of DLLs, so we have to
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * ASSUME that a bunch of system DLLs are fine.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, pNtViRdr->hFile, rc);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync * Check for the signature checking enforcement, if requested to do so.
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT))
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced));
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.",
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED,
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync "The image '%ls' was not linked with /IntegrityCheck.", pwszName);
7d6ce198fd361f58bd1ebdeee7772f76b4e58966vboxsync RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc);
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Pass it thru WinVerifyTrust when possible.
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, rc, pfWinVerifyTrust, pErrInfo);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync * Hook for the LdrLoadDll code to schedule scanning of imports.
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync supR3HardenedWinVerifyCacheScheduleImports(hLdrMod, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verifies the given executable image.
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 * @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.
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool fAvoidWinVerifyTrust,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Create a reader instance.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardNtViRdrCreate(hFile, pwszName, fFlags, &pNtViRdr);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the image.
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;
8825cfa0db3bf263a5b0da21f8ad487699e3af61vboxsync rc = RTLdrOpenWithReader(&pNtViRdr->Core, fLdrFlags, enmArch, &hLdrMod, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Verify it.
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, fAvoidWinVerifyTrust, pfWinVerifyTrust, pErrInfo);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d (%ls)%s\n",
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync rc, pwszName, pfWinVerifyTrust && *pfWinVerifyTrust ? "WinVerifyTrust" : ""));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * supHardenedWinVerifyImageByHandle version without the name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * The name is derived from the handle.
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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Determine the NT name and call the verification function.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';
cf0e96b2c5a08292c6d13e4fdcb2d9518d1983e8vboxsync return supHardenedWinVerifyImageByHandle(hFile, uBuf.UniStr.Buffer, fFlags, false /*fAvoidWinVerifyTrust*/,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync#endif /* IN_RING3 */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Retrieves the full official path to the system root or one of it's sub
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * directories.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This code is also used by the support driver.
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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardNtGetSystemRootDir(void *pvBuf, uint32_t cbBuf, SUPHARDNTSYSROOTDIR enmDir, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszNameSystem32[] = L"\\SystemRoot\\System32\\";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = sizeof(s_wszNameSystem32) - sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const WCHAR s_wszNameWinSxS[] = L"\\SystemRoot\\WinSxS\\";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = sizeof(s_wszNameWinSxS) - sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0 /*EaLength*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Make sure it's terminated so it can safely be printed.*/
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pUniStr->Buffer[pUniStr->Length / sizeof(WCHAR)] = '\0';
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtQueryObject returned an empty path for '%ls'", NtName.Buffer);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH, "NtQueryObject failed on '%ls' dir: %#x", NtName.Buffer, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SYSTEM32_PATH, "Failure to open '%ls': %#x", NtName.Buffer, rcNt);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize one certificate entry.
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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertInit(PRTCRX509CERTIFICATE pCert, unsigned char const *pabCert, unsigned cbCert,
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 RTAsn1CursorInitPrimary(&PrimaryCursor, pabCert, cbCert, pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, pCert, pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrX509Certificate_CheckSanity(pCert, 0, pErrInfo, pszErrorTag);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertStoreAddArray(RTCRSTORE hStore, PCSUPTAENTRY paCerts, unsigned cCerts, PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_TAF_DER, paCerts[i].pch, paCerts[i].cb, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize a certificate table.
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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supHardNtViCertStoreInit(PRTCRSTORE phStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(*phStore == NIL_RTCRSTORE, VERR_WRONG_ORDER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrStoreCreateInMem(phStore, cCerts1 + cCerts2);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "RTCrStoreCreateMemoryStore failed: %Rrc", rc);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts1, cCerts1, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts2, cCerts2, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreAddArray(*phStore, paCerts3, cCerts3, pErrInfo);
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#if defined(IN_RING3) && !defined(VBOX_PERMIT_EVEN_MORE)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Initializes the windows paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsyncstatic void supHardenedWinInitImageVerifierWinPaths(void)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Windows paths that we're interested in.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync static const struct
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_ProgramFilesNtPath, L"ProgramFilesDir", "ProgDir" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_CommonFilesNtPath, L"CommonFilesDir", "ComDir" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_ProgramFilesX86NtPath, L"ProgramFilesDir (x86)", "ProgDir32" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync { &g_CommonFilesX86NtPath, L"CommonFilesDir (x86)", "ComDir32" },
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Open the registry key containing the paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync UNICODE_STRING NtName = RTNT_CONSTANT_UNISTR(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjAttr);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Loop over the paths and resolve their NT paths.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Query the value first.
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 uint8_t abPadding[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR) * 128];
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = NtQueryValueKey(hKey, &ValueName, KeyValuePartialInformation, &uBuf, sizeof(uBuf) - sizeof(WCHAR), &cbActual);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Must be a simple string value, terminate it.
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 if (Src.Length >= sizeof(WCHAR) && Src.Buffer[Src.Length / sizeof(WCHAR) - 1] == '\0')
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Src.Buffer[uBuf.PartialInfo.DataLength / sizeof(WCHAR)] = '\0';
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync Dst.MaximumLength = sizeof(s_aPaths[i].pNtPath->awcBuffer) - sizeof(WCHAR) * 5;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync rcNt = RtlExpandEnvironmentStrings_U(NULL, &Src, &Dst, NULL);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Include the \\??\\ prefix in the result and open the path.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync InitializeObjectAttributes(&ObjAttr, &Dst, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync 0 /*EaLength*/);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Query the real NT name.
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 SUP_DPRINTF(("%s: NtQueryObject returned empty string\n", s_aPaths[i].pszLogName));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtQueryObject failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtCreateFile failed: %#x (%ls)\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: RtlExpandEnvironmentStrings_U failed: %#x (%ls)\n",
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: type mismatch: %#x\n", s_aPaths[i].pszLogName, uBuf.PartialInfo.Type));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("%s: NtQueryValueKey failed: %#x\n", s_aPaths[i].pszLogName, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /* Stub the entry on failure. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("NtOpenKey(%ls) failed: %#x\n", NtName.Buffer, rcNt));
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync /* Stub all the entries on failure. */
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aPaths); i++)
0c2ffca957882f38c677fc23f324cfd695b96947vboxsync#endif /* IN_RING3 && !VBOX_PERMIT_EVEN_MORE */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This initializes the certificates globals so we don't have to reparse them
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * every time we need to verify an image.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns IPRT status code.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Where to return extended error info. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(int) supHardenedWinInitImageVerifier(PRTERRINFO pErrInfo)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync AssertReturn(!RTCrX509Certificate_IsPresent(&g_BuildX509Cert), VERR_WRONG_ORDER);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Get the system root paths.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supHardNtGetSystemRootDir(&g_System32NtPath, sizeof(g_System32NtPath), kSupHardNtSysRootDir_System32, pErrInfo);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtGetSystemRootDir(&g_WinSxSNtPath, sizeof(g_WinSxSNtPath), kSupHardNtSysRootDir_WinSxS, pErrInfo);
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)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initialize it, leaving the cleanup to the termination call.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertInit(&g_BuildX509Cert, g_abSUPBuildCert, g_cbSUPBuildCert, pErrInfo, "BuildCertificate");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcRootStore, g_aSUPSpcRootTAs, g_cSUPSpcRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hNtKernelRootStore, g_aSUPNtKernelRootTAs, g_cSUPNtKernelRootTAs,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcAndNtKernelRootStore,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = supHardNtViCertStoreInit(&g_hSpcAndNtKernelSuppStore,
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 && RTCrX509Name_Compare(&g_BuildX509Cert.TbsCertificate.Subject, &g_BuildX509Cert.TbsCertificate.Issuer) == 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync * Finally initialize known SIDs that we use.
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SID_IDENTIFIER_AUTHORITY s_NtAuth = SECURITY_NT_AUTHORITY;
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync NTSTATUS rcNt = RtlInitializeSid(&g_TrustedInstallerSid, &s_NtAuth, SECURITY_SERVICE_ID_RID_COUNT);
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;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync rcNt = RtlInitializeSid(&g_LocalSystemSid, &s_NtAuth, 1);
0bc5fa2d224947a76f49bca2ac9bdceb27bc23a0vboxsync *RtlSubAuthoritySid(&g_LocalSystemSid, 0) = SECURITY_LOCAL_SYSTEM_RID;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync rcNt = RtlInitializeSid(&g_AdminsGroupSid, &s_NtAuth, 2);
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
0a391f08407ad2804a24429ad6aa664f3efd829dvboxsync *RtlSubAuthoritySid(&g_AdminsGroupSid, 1) = DOMAIN_ALIAS_RID_ADMINS;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Releases resources allocated by supHardenedWinInitImageVerifier.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncDECLHIDDEN(void) supHardenedWinTermImageVerifier(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Certificate_IsPresent(&g_BuildX509Cert))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This is a hardcoded list of certificates we thing we might need.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @returns true if wanted, false if not.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pCert The certificate.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic bool supR3HardenedWinIsDesiredRootCA(PCRTCRX509CERTIFICATE pCert)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync RTCrX509Name_FormatAsString(&pCert->TbsCertificate.Subject, szSubject, sizeof(szSubject) - 1, NULL);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Check that it's a plausible root certificate.
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - not-self-signed: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTAsn1Integer_UnsignedCompareWithU32(&pCert->TbsCertificate.T0.Version, 3) > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if ( !(pCert->TbsCertificate.T3.fExtKeyUsage & RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && (pCert->TbsCertificate.T3.fFlags & RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE) )
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-cert-sign: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync && !pCert->TbsCertificate.T3.pBasicConstraints->CA.fValue)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - non-CA: %s\n", szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits < 256) /* mostly for u64KeyId reading. */
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - key too small: %u bits %s\n",
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.cBits, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync uint64_t const u64KeyId = pCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey.uBits.pu64[1];
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync * Whitelist - Array of names and key clues of the certificates we want.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync const char *pszName;
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 { 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 /* 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 while (i-- > 0)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, s_aWanted[i].pszName))
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return true;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping %#llx %s\n", u64KeyId, szSubject));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync * Blacklist approach.
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync static struct
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync { UINT64_C(0xffffffffffffffff), "C=US, O=U.S. Robots and Mechanical Men, Inc., OU=V.I.K.I." }, /* dummy entry */
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync while (i-- > 0)
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync if (RTCrX509Name_MatchWithString(&pCert->TbsCertificate.Subject, s_aUnwanted[i].pszName))
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: skipping - blacklisted: %#llx %s\n", u64KeyId, szSubject));
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync return false;
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync SUP_DPRINTF(("supR3HardenedWinIsDesiredRootCA: Adding %#llx %s\n", u64KeyId, szSubject));
1f7b836686e1f04175cfbda46a5f9d20b98aca99vboxsync return true;
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Loads a module in the system32 directory.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsync * @returns Module handle on success. Won't return on failure if fMandatory = true.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * @param pszName The name of the DLL to load.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsync * @param fMandatory Whether the library is mandatory.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsyncDECLHIDDEN(HMODULE) supR3HardenedWinLoadSystem32Dll(const char *pszName, bool fMandatory)
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync UINT cwcDir = GetSystemDirectoryW(wszName, RT_ELEMENTS(wszName) - 60);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync RTUtf16CopyAscii(&wszName[cwcDir + 1], RT_ELEMENTS(wszName) - cwcDir, pszName);
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync HMODULE hMod = LoadLibraryExW(wszName, NULL, fFlags);
30f07af559efcbd967e801903746fc21f81ee533vboxsync && RtlGetLastWin32Error() == ERROR_INVALID_PARAMETER)
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error loading '%s': %u [%ls]", pszName, RtlGetLastWin32Error(), wszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Called by supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation to
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * import selected root CAs from the system certificate store.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * These certificates permits us to correctly validate third party DLLs.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsyncstatic void supR3HardenedWinRetrieveTrustedRootCAs(void)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Load crypt32.dll and resolve the APIs we need.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsync HMODULE hCrypt32 = supR3HardenedWinLoadSystem32Dll("crypt32.dll", true /*fMandatory*/);
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 * Open the root store and look for the certificates we wish to use.
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 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 while ((pCurCtx = pfnCertEnumCertificatesInStore(hStore, pCurCtx)) != NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (pCurCtx->dwCertEncodingType & X509_ASN_ENCODING)
2f9acd6c5608d79e003dda3b5ebbd511d7f6fdd0vboxsync RTAsn1CursorInitPrimary(&PrimaryCursor, pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "CurCtx");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &MyCert, "Cert");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTCrStoreCertAddEncoded(g_hSpcAndNtKernelRootStore, RTCRCERTCTX_F_ENC_X509_DER,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pCurCtx->pbCertEncoded, pCurCtx->cbCertEncoded, NULL /*pErrInfo*/);
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 pfnCertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardenedWinRetrieveTrustedRootCAs: cAdded=%u\n", cAdded));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Resolves the WinVerifyTrust API after the process has been verified and
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * installs a thread creation hook.
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 * @param pszProgName The program name.
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsyncDECLHIDDEN(void) supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(const char *pszProgName)
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 * The thread creation hook makes the threads very slippery to debuggers by
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * irreversably disabling most (if not all) debug events for them.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxSupLib.DLL"));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HMODULE hSupLibMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, true /*fSystem32Only*/);
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error loading '%s': %u", szPath, RtlGetLastWin32Error());
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync * Allocate TLS entry for WinVerifyTrust recursion prevention.
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedError(RtlGetLastWin32Error(), false /*fFatal*/, "TlsAlloc failed");
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * Resolve the imports we need.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsync HMODULE hWintrust = supR3HardenedWinLoadSystem32Dll("Wintrust.dll", true /*fMandatory*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#define RESOLVE_CRYPT_API(a_Name, a_pfnType, a_uMinWinVer) \
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 PFNWINVERIFYTRUST pfnWinVerifyTrust = (PFNWINVERIFYTRUST)GetProcAddress(hWintrust, "WinVerifyTrust");
30f07af559efcbd967e801903746fc21f81ee533vboxsync supR3HardenedFatal("Error locating 'WinVerifyTrust' in 'Wintrust.dll': %u", RtlGetLastWin32Error());
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 RESOLVE_CRYPT_API(CryptCATAdminAcquireContext2, PFNCRYPTCATADMINACQUIRECONTEXT2, SUP_NT_VER_W80);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync RESOLVE_CRYPT_API(CryptCATAdminCalcHashFromFileHandle2, PFNCRYPTCATADMINCALCHASHFROMFILEHANDLE2, SUP_NT_VER_W80);
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.
47873d8cc62e11fef8791aaea2b3d9c7d8ed9681vboxsync HMODULE hBCrypt = supR3HardenedWinLoadSystem32Dll("bcrypt.dll", false /*fMandatory*/);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync PFNBCRYPTOPENALGORTIHMPROVIDER pfnOpenAlgoProvider;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync pfnOpenAlgoProvider = (PFNBCRYPTOPENALGORTIHMPROVIDER)GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider");
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("bcrypt.dll loaded at %p, BCryptOpenAlgorithmProvider at %p, preloading providers:\n",
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 SUP_DPRINTF(("Warning! Failed to find BCryptOpenAlgorithmProvider in bcrypt.dll\n"));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Warning! Failed to load bcrypt.dll\n"));
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 int rc = supR3HardNtViCallWinVerifyTrust(NULL, g_SupLibHardenedExeNtPath.UniStr.Buffer, 0,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync supR3HardenedFatalMsg(pszProgName, kSupInitOp_Integrity, rc,
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync "WinVerifyTrust failed on stub executable: %s", ErrInfoStatic.szMsg);
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);
d1e6154d21dcc739e31ac7d8b139ee0fdfe60d45vboxsync SUP_DPRINTF(("g_pfnWinVerifyTrust=%p\n", pfnWinVerifyTrust));
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * Load some problematic DLLs into the verifier cache to prevent
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync * recursion trouble.
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\crypt32.dll");
48e06e6a052c50ecf176f63f5537f80b544bf34avboxsync supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\Wintrust.dll");
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Now, get trusted root CAs so we can verify a broader scope of signatures.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViNtToWinPath(PCRTUTF16 pwszNtName, PCRTUTF16 *ppwszWinPath,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static const RTUTF16 s_wszPrefix[] = L"\\\\.\\GLOBALROOT";
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (RT_ELEMENTS(s_wszPrefix) + cwcNtName > cwcWinPathBuf)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(pwszWinPathBuf, s_wszPrefix, sizeof(s_wszPrefix));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync memcpy(&pwszWinPathBuf[sizeof(s_wszPrefix) / sizeof(RTUTF16) - 1], pwszNtName, (cwcNtName + 1) * sizeof(RTUTF16));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calls WinVerifyTrust to verify an PE image.
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 * @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.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
9a49f7e775b1d8e5850e637526e4e067c2bb0144vboxsync PFNWINVERIFYTRUST pfnWinVerifyTrust, HRESULT *phrcWinVerifyTrust)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the name into a Windows name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrust: rc=%Rrc '%ls'", rc, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Construct input parameters and call the API.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync GUID PolicyActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Failed. Format a nice error message.
0c8e85263a357c44964520942cb5816ab1c2e69dvboxsync if (hrc != CERT_E_CHAINING /* Un-updated vistas, XPs, ++ */)
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 rc = RTErrInfoSetF(pErrInfo, VERR_LDRVI_UNSUPPORTED_ARCH,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "WinVerifyTrust failed with hrc=%s on '%ls'", pszErrConst, pwszName);
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",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* clean up state data. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &PolicyActionGuid, &TrustData);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Calls WinVerifyTrust to verify an PE image via catalog files.
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 * @param fFlags Flags, SUPHNTVI_F_XXX.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pErrInfo Pointer to error info structure. Optional.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * @param pfnWinVerifyTrust Pointer to the API.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncstatic int supR3HardNtViCallWinVerifyTrustCatFile(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PRTERRINFO pErrInfo,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hFile=%p pwszName=%ls\n", hFile, pwszName));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Convert the name into a Windows name.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync int rc = supR3HardNtViNtToWinPath(pwszName, &pwszWinPath, wszWinPathBuf, RT_ELEMENTS(wszWinPathBuf));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, rc, "Bad path passed to supR3HardNtViCallWinVerifyTrustCatFile: rc=%Rrc '%ls'", rc, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Open the file if we didn't get a handle.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (hFile == RTNT_INVALID_HANDLE_VALUE || hFile == NULL)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.Length = (USHORT)(RTUtf16Len(pwszName) * sizeof(WCHAR));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync 0 /*EaLength*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTErrInfoSetF(pErrInfo, RTErrConvertFromNtStatus(rcNt),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "NtCreateFile returned %#x opening '%ls'.", rcNt, pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * On Windows 8.0 and later there are more than one digest choice.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync static struct
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** The digest algorithm name. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /** Cached catalog admin handle. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync for (uint32_t i = 0; i < RT_ELEMENTS(s_aHashes); i++)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Another loop for dealing with different trust provider policies
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * required for successfully validating different catalog signatures.
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 * Create a context.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATADMIN hCatAdmin = ASMAtomicXchgPtr(&s_aHashes[i].hCachedCatAdmin, NULL);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Cached context %p\n", hCatAdmin));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fRc = g_pfnCryptCATAdminAcquireContext2(&hCatAdmin, &s_aPolicies[iPolicy], s_aHashes[i].pszAlgorithm,
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync fRc = g_pfnCryptCATAdminAcquireContext(&hCatAdmin, &s_aPolicies[iPolicy], 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: New context %p\n", hCatAdmin));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: hCatAdmin=%p\n", hCatAdmin));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Hash the file.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fRc = g_pfnCryptCATAdminCalcHashFromFileHandle2(hCatAdmin, hFile, &cbHash, abHash, 0 /*dwFlags*/);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync fRc = g_pfnCryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, abHash, 0 /*dwFlags*/);
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 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: cbHash=%u wszDigest=%ls\n", cbHash, wszDigest));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Enumerate catalog information that matches the hash.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* Get the next match. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HCATINFO hCatInfo = g_pfnCryptCATAdminEnumCatalogFromHash(hCatAdmin, abHash, cbHash, 0, &hCatInfoPrev);
30f07af559efcbd967e801903746fc21f81ee533vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Retrying with fresh context (CryptCATAdminEnumCatalogFromHash -> %u; iCat=%#x)\n", RtlGetLastWin32Error(), iCat));
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/);
a60be2c64ea23bb7ce4c9998bcd541c4db879fbavboxsync g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/);
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync fNoSignedCatalogFound = ulErr == ERROR_NOT_FOUND && fNoSignedCatalogFound != 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 * Call WinVerifyTrust.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_pfnCryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0 /*dwFlags*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync WtCatInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.fdwRevocationChecks = WTD_REVOKE_NONE; /* Keep simple for now. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync TrustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync HRESULT hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
9b62e122a37f42c2bbaae1312ad198f44bebea5cvboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: WinVerifyTrust => %#x; cat='%ls'; file='%ls'\n",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { /* ignore because it's useless. */ }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync { /* This is returned if the given file isn't found in the catalog, it seems. */ }
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_WINTRUST_CAT_FAILURE,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "WinVerifyTrust failed with hrc=%#x on '%ls' and .cat-file='%ls'.",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync /* clean up state data. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync hrc = pfnWinVerifyTrust(NULL /*hwnd*/, &s_aPolicies[iPolicy], &TrustData);
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync "CryptCATCatalogInfoFromContext failed: %d [file=%s]",
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATCatalogInfoFromContext failed\n"));
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync } while (rc == VERR_LDRVI_NOT_SIGNED && iCat < 128);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync rc = RTErrInfoSetF(pErrInfo, rc2, "RTUtf16PrintHexBytes failed: %Rrc", rc);
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "CryptCATAdminCalcHashFromFileHandle[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!ASMAtomicCmpXchgPtr(&s_aHashes[i].hCachedCatAdmin, hCatAdmin, NULL))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/))
30f07af559efcbd967e801903746fc21f81ee533vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(RtlGetLastWin32Error()),
30f07af559efcbd967e801903746fc21f81ee533vboxsync "CryptCATAdminAcquireContext[2] failed: %d [file=%s]", RtlGetLastWin32Error(), pwszName);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Only repeat if we've got g_pfnCryptCATAdminAcquireContext2 and can specify the hash algorithm.
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync * DLLs that are likely candidates for local modifications.
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync uint32_t cwcOther = g_System32NtPath.UniStr.Length / sizeof(WCHAR);
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if (supHardViUtf16PathStartsWithEx(pwszName, cwcName, g_System32NtPath.UniStr.Buffer, cwcOther, true /*fCheckSlash*/))
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync if ( supHardViUtf16PathIsEqual(pwsz, "uxtheme.dll")
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "KernelBase.dll"))
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "kernel32.dll"))
1ff19c6bd579b290ca46ce7f391712dfc470e01avboxsync || (fCoreSystemDll = supHardViUtf16PathIsEqual(pwsz, "ntdll.dll"))
9eca6d49e3fd77fc38cfdbd021e5afa83a27526fvboxsync RTErrInfoAddF(pErrInfo, rc, "'%ls' is most likely modified.", pwszName);
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. */
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Verifies the given image using WinVerifyTrust in some way.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * This is used by supHardenedWinVerifyImageByLdrMod as well as
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * supR3HardenedScreenImage.
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 * @param pfWinVerifyTrust Where to return whether WinVerifyTrust was
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * actually used.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * @param pErrInfo Pointer to error info structure. Optional.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsyncDECLHIDDEN(int) supHardenedWinVerifyImageTrust(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, int rc,
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Call the windows verify trust API if we've resolved it and aren't in
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync * some obvious recursion.
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync uint32_t const idCurrentThread = RTNtCurrentThreadId();
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Check if loader lock owner. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync struct _RTL_CRITICAL_SECTION volatile *pLoaderLock = NtCurrentPeb()->LoaderLock;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync && pLoaderLock->OwningThread == (HANDLE)(uintptr_t)idCurrentThread
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Check for recursion. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync fNoRecursion = TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0;
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)1);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync fNoRecursion = ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* We can call WinVerifyTrust. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION)
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo,
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust,
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 && (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION))
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync rc = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (was CERT_E_CHAINING)\n", rc));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust, NULL);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>"));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync /* Unwind recursion. */
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync TlsSetValue(g_iTlsWinVerifyTrustRecursion, (void *)0);
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync * No can do.
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
0dce96288d862069ff8c049d6b7a8dc625f9f555vboxsync SUP_DPRINTF(("Detected loader lock ownership: rc=%Rrc '%ls'.\n", rc, pwszName));
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsync * Checks if WinVerifyTrust is callable on the current thread.
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 * @returns true if callable on current thread, false if not.
db87bb1112c1f2827ffa192593174cf845f8f04dvboxsyncDECLHIDDEN(bool) supHardenedWinIsWinVerifyTrustCallable(void)
f2c1a5f27ded5c0265c47c5a928a5a7fd6b01a41vboxsync ? (uintptr_t)TlsGetValue(g_iTlsWinVerifyTrustRecursion) == 0
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Initializes g_uNtVerCombined and g_NtVerInfo.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Called from suplibHardenedWindowsMain and suplibOsInit.
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 NtVerInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&NtVerInfo)))
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync g_uNtVerCombined = SUP_MAKE_NT_VER_COMBINED(NtVerInfo.dwMajorVersion, NtVerInfo.dwMinorVersion, NtVerInfo.dwBuildNumber,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync NtVerInfo.wServicePackMajor, NtVerInfo.wServicePackMinor);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#endif /* IN_RING3 */