SUPHardenedVerifyProcess-win.cpp revision f71c6ce3d63d12af823dfc6df1c57ce9928b6a3a
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox Support Library/Driver - Hardened Process Verification, Windows.
1ef682c649d3f26392a8b7a091337adb78ddd87dvboxsync * Copyright (C) 2006-2014 Oracle Corporation
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * available from http://www.virtualbox.org. This file is free software;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * General Public License (GPL) as published by the Free Software
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * The contents of this file may alternatively be used under the terms
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * of the Common Development and Distribution License Version 1.0
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * CDDL are applicable instead of those of the GPL.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * You may elect to license modified versions of this file under the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * terms and conditions of either the GPL or the CDDL or both.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Header Files *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
bda3dd52e256c637c703aecf163ecc5b682a43a4vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Structures and Typedefs *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Virtual address space region.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The RVA of the region. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The size of the region. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The protection of the region. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** Pointer to a virtual address space region. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Virtual address space image information.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The base address of the image. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync /** The size of the image mapping. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The name from the allowed lists. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync const char *pszName;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Name structure for NtQueryVirtualMemory/MemorySectionName. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The full unicode name. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Buffer space. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The number of mapping regions. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Mapping regions. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The image characteristics from the FileHeader. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The DLL characteristics from the OptionalHeader. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Set if this is the DLL. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Set if the image is NTDLL an the verficiation code needs to watch out for
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * the NtCreateSection patch. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Whether the API set schema hack needs to be applied when verifying memory
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * content. The hack means that we only check if the 1st section is mapped. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/** Pointer to image info from the virtual address space scan. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Virtual address space scanning state.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** The result. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Number of images in aImages. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Images found in the process.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * The array is large enough to hold the executable, all allowed DLLs, and one
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * more so we can get the image name of the first unwanted DLL. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Memory compare scratch buffer.*/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** File compare scratch buffer.*/
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Section headers for use when comparing file and loaded image. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /** Pointer to the error info. */
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync/** Pointer to stat information of a virtual address space scan. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync/*******************************************************************************
b2640405e06105d868b5fc8f7b676bb680884380vboxsync* Global Variables *
b2640405e06105d868b5fc8f7b676bb680884380vboxsync*******************************************************************************/
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * System DLLs allowed to be loaded into the process.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @remarks supHardNtVpCheckDlls assumes these are lower case.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsyncstatic const char *g_apszSupNtVpAllowedDlls[] =
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "ntdll.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "kernel32.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "kernelbase.dll",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "apphelp.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "apisetschema.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "psapi.dll",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "msvcrt.dll",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync "advapi32.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "sechost.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "rpcrt4.dll",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "SamplingRuntime.dll",
2347f07aa55c4c0035118a2a1634e5187a3ffdf4vboxsync * VBox executables allowed to start VMs.
eb4f1fa4c357485330370c0eaba27e5a2af7d9c4vboxsync * @remarks Remember to keep in sync with SUPR3HardenedVerify.cpp.
8ad79874169cc981a694a15e8a806b9a39133673vboxsyncstatic const char *g_apszSupNtVpAllowedVmExes[] =
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "VBoxHeadless.exe",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "VirtualBox.exe",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "VBoxSDL.exe",
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync "VBoxNetDHCP.exe",
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync "VBoxNetNAT.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstMicro.exe",
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync "tstPDMAsyncCompletion.exe",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "tstPDMAsyncCompletionStress.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstVMM.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstVMREQ.exe",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync "tstCFGM.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstIntNet-1.exe",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync "tstMMHyperHeap.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstR0ThreadPreemptionDriver.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstRTR0MemUserKernelDriver.exe",
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync "tstRTR0SemMutexDriver.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstRTR0TimerDriver.exe",
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync "tstSSM.exe",
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync/** Pointer to NtQueryVirtualMemory. Initialized by SUPDrv-win.cpp in
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * ring-0, in ring-3 it's just a slightly confusing define. */
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsyncPFNNTQUERYVIRTUALMEMORY g_pfnNtQueryVirtualMemory = NULL;
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync# define g_pfnNtQueryVirtualMemory NtQueryVirtualMemory
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Fills in error information.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @returns @a rc.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @param pErrInfo Pointer to the extended error info structure.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Can be NULL.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @param pszErr Where to return error details.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @param cbErr Size of the buffer @a pszErr points to.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @param rc The status to return.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param pszMsg The format string for the message.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @param ... The arguments for the format string.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsyncstatic int supHardNtVpSetInfo1(PRTERRINFO pErrInfo, int rc, const char *pszMsg, ...)
8ad79874169cc981a694a15e8a806b9a39133673vboxsync supR3HardenedError(rc, false /*fFatal*/, "%N\n", pszMsg, &va);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * Fills in error information.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync * @returns @a rc.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * @param pThis The process validator instance.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync * @param pszErr Where to return error details.
3383321ffc6907012f92f16b26b026908de7fe7fvboxsync * @param cbErr Size of the buffer @a pszErr points to.
69dc1a8b612032236f9f04033e7c53ce7a478f17vboxsync * @param rc The status to return.
485e602154df33e5466e0dcca16d8f97914ce41dvboxsync * @param pszMsg The format string for the message.
485e602154df33e5466e0dcca16d8f97914ce41dvboxsync * @param ... The arguments for the format string.
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsyncstatic int supHardNtVpSetInfo2(PSUPHNTVPSTATE pThis, int rc, const char *pszMsg, ...)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync supR3HardenedError(rc, false /*fFatal*/, "%N\n", pszMsg, &va);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync RTErrInfoAddF(pThis->pErrInfo, rc, " \n[rc=%d] ", rc);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsyncstatic NTSTATUS supHardNtVpReadFile(HANDLE hFile, uint64_t off, void *pvBuf, size_t cbRead)
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsyncstatic NTSTATUS supHardNtVpReadMem(HANDLE hProcess, uintptr_t uPtr, void *pvBuf, size_t cbRead)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync /* ASSUMES hProcess is the current process. */
8ad79874169cc981a694a15e8a806b9a39133673vboxsync /** @todo use MmCopyVirtualMemory where available! */
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync NTSTATUS rcNt = NtReadVirtualMemory(hProcess, (PVOID)uPtr, pvBuf, cbRead, &cbIgn);
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic int supHardNtVpFileMemCompare(PSUPHNTVPSTATE pThis, const void *pvFile, const void *pvMemory, size_t cbToCompare,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (suplibHardenedMemComp(pvFile, pvMemory, cbToCompare) == 0)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Find the exact location. */
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync const uint8_t *pbMemory = (const uint8_t *)pvMemory;
3383321ffc6907012f92f16b26b026908de7fe7fvboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync "%s: memory compare at %#x failed: %#x != %#x\n", pImage->pszName, uRva, *pbFile, *pbMemory);
485e602154df33e5466e0dcca16d8f97914ce41dvboxsyncstatic int supHardNtVpCheckSectionProtection(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t offRegion = uRva - pImage->aRegions[i].uRva;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t cbLeft = pImage->aRegions[i].cb - offRegion;
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_SECTION_PROTECTION_MISMATCH,
eafe2940026f325feeaa433c9ea44823431ec5ffvboxsync "%s: RVA range %#x-%#x protection is %#x, expected %#x. (cb=%#x)",
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pImage->pszName, uRva, uRva + cbLeft - 1, pImage->aRegions[i].fProt, fProt, cb);
0c802efc285bf77b849eaf660a9c18a0e7f62445vboxsync#if 0 /* This shouldn't ever be necessary. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, cbOrg == cb ? VERR_SUP_VP_SECTION_NOT_MAPPED : VERR_SUP_VP_SECTION_NOT_FULLY_MAPPED,
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync "%s: RVA range %#x-%#x is not mapped?", pImage->pszName, uRva, uRva + cb - 1);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Compares process memory with the disk content.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @returns VBox status code.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pThis The process scanning state structure (for the
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * two scratch buffers).
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pImage The image data collected during the address
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * space scan.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param hProcess Handle to the process.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param hFile Handle to the image file.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * @param pErrInfo Pointer to error info structure. Optional.
b2640405e06105d868b5fc8f7b676bb680884380vboxsyncstatic int supHardNtVpVerifyImageCompareMemory(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, HANDLE hProcess, HANDLE hFile,
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Read and find the file headers.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync NTSTATUS rcNt = supHardNtVpReadFile(hFile, 0, pThis->abFile, sizeof(pThis->abFile));
bda3dd52e256c637c703aecf163ecc5b682a43a4vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_IMAGE_HDR_READ_ERROR,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Error reading image header: %#x", pImage->pszName, rcNt);
bda3dd52e256c637c703aecf163ecc5b682a43a4vboxsync PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)&pThis->abFile[0];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (offNtHdrs > 512 || offNtHdrs < sizeof(*pDosHdr))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_MZ_OFFSET,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Unexpected e_lfanew value: %#x", pImage->pszName, offNtHdrs);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)&pThis->abFile[offNtHdrs];
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_IMAGE_SIGNATURE,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: No PE signature at %#x: %#x", pImage->pszName, offNtHdrs, pNtHdrs->Signature);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Do basic header validation.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pNtHdrs->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pNtHdrs->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
bda3dd52e256c637c703aecf163ecc5b682a43a4vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_UNEXPECTED_IMAGE_MACHINE,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Unexpected machine: %#x", pImage->pszName, pNtHdrs->FileHeader.Machine);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(pNtHdrs->OptionalHeader))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_OPTIONAL_HEADER,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Unexpected optional header size: %#x",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pImage->pszName, pNtHdrs->FileHeader.SizeOfOptionalHeader);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pNtHdrs->OptionalHeader.Magic != RT_CONCAT3(IMAGE_NT_OPTIONAL_HDR,ARCH_BITS,_MAGIC))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_OPTIONAL_HEADER,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Unexpected optional header magic: %#x", pImage->pszName, pNtHdrs->OptionalHeader.Magic);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_OPTIONAL_HEADER,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "%s: Unexpected data dirs: %#x", pImage->pszName, pNtHdrs->OptionalHeader.NumberOfRvaAndSizes);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync * Before we start comparing things, store what we need to know from the headers.
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync uint32_t const cSections = pNtHdrs->FileHeader.NumberOfSections;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_TOO_MANY_SECTIONS,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "%s: Too many section headers: %#x", pImage->pszName, cSections);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync suplibHardenedMemCopy(pThis->aSecHdrs, pNtHdrs + 1, cSections * sizeof(IMAGE_SECTION_HEADER));
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uintptr_t const uImageBase = pNtHdrs->OptionalHeader.ImageBase;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_IMAGE_BASE,
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync "%s: Invalid image base: %p", pImage->pszName, uImageBase);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t const cbImage = pNtHdrs->OptionalHeader.SizeOfImage;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (RT_ALIGN_32(pImage->cbImage, PAGE_SIZE) != RT_ALIGN_32(cbImage, PAGE_SIZE) && !pImage->fApiSetSchemaOnlySection1)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_IMAGE_SIZE,
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync "%s: SizeOfImage (%#x) isn't close enough to the mapping size (%#x)",
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync uint32_t const cbSectAlign = pNtHdrs->OptionalHeader.SectionAlignment;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync || cbSectAlign > (pImage->fApiSetSchemaOnlySection1 ? _64K : (uint32_t)PAGE_SIZE) )
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SECTION_ALIGNMENT_VALUE,
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync "%s: Unexpected SectionAlignment value: %#x", pImage->pszName, cbSectAlign);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t const cbFileAlign = pNtHdrs->OptionalHeader.FileAlignment;
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync if (!RT_IS_POWER_OF_TWO(cbFileAlign) || cbFileAlign < 512 || cbFileAlign > PAGE_SIZE || cbFileAlign > cbSectAlign)
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_FILE_ALIGNMENT_VALUE,
8ad79874169cc981a694a15e8a806b9a39133673vboxsync "%s: Unexpected FileAlignment value: %#x (cbSectAlign=%#x)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t const cbHeaders = pNtHdrs->OptionalHeader.SizeOfHeaders;
8ad79874169cc981a694a15e8a806b9a39133673vboxsync uint32_t const cbMinHdrs = offNtHdrs + sizeof(*pNtHdrs) + sizeof(IMAGE_SECTION_HEADER) * cSections;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SIZE_OF_HEADERS,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Headers are too small: %#x < %#x (cSections=%#x)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t const cbHdrsFile = RT_ALIGN_32(cbHeaders, cbFileAlign);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SIZE_OF_HEADERS,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Headers are larger than expected: %#x/%#x (expected max %zx)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pImage->pszName, cbHeaders, cbHdrsFile, sizeof(pThis->abFile));
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync * Compare the file header with the loaded bits. The loader will fiddle
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync * with image base, changing it to the actual load address.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rcNt = supHardNtVpReadMem(hProcess, pImage->uImageBase, pThis->abMemory, cbHdrsFile);
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_READ_ERROR,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Error reading image header from memory: %#x", pImage->pszName, rcNt);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pNtHdrs->OptionalHeader.ImageBase = pImage->uImageBase;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync rc = supHardNtVpFileMemCompare(pThis, pThis->abFile, pThis->abMemory, cbHeaders, pImage, 0 /*uRva*/);
ce95f18112057771f68abe58df709edd7c467db1vboxsync rc = supHardNtVpCheckSectionProtection(pThis, pImage, 0 /*uRva*/, cbHdrsFile, PAGE_READONLY);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Save some header fields we might be using later on.
8ad79874169cc981a694a15e8a806b9a39133673vboxsync pImage->fImageCharecteristics = pNtHdrs->FileHeader.Characteristics;
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync pImage->fDllCharecteristics = pNtHdrs->OptionalHeader.DllCharacteristics;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync * Validate sections and check them against the mapping regions.
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Validate the section. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t uSectRva = pThis->aSecHdrs[i].VirtualAddress;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (uSectRva < uRva || uSectRva > cbImage || RT_ALIGN_32(uSectRva, cbSectAlign) != uSectRva)
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SECTION_RVA,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Section %u: Invalid virtual address: %#x (uRva=%#x, cbImage=%#x, cbSectAlign=%#x)",
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync pImage->pszName, i, uSectRva, uRva, cbImage, cbSectAlign);
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync uint32_t cbMap = pThis->aSecHdrs[i].Misc.VirtualSize;
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SECTION_VIRTUAL_SIZE,
083344b49cc7370da15d3cb7e3a9c9cb2d8dfbb0vboxsync "%s: Section %u: Invalid virtual size: %#x (uSectRva=%#x, uRva=%#x, cbImage=%#x)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pImage->pszName, i, cbMap, uSectRva, uRva, cbImage);
b2640405e06105d868b5fc8f7b676bb680884380vboxsync uint32_t cbFile = pThis->aSecHdrs[i].SizeOfRawData;
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (cbFile != RT_ALIGN_32(cbFile, cbFileAlign) || cbFile > RT_ALIGN_32(cbMap, cbSectAlign))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_SECTION_FILE_SIZE,
b2640405e06105d868b5fc8f7b676bb680884380vboxsync "%s: Section %u: Invalid file size: %#x (cbMap=%#x, uSectRva=%#x)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync /* Validate the protection. */
b2640405e06105d868b5fc8f7b676bb680884380vboxsync switch (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
b2640405e06105d868b5fc8f7b676bb680884380vboxsync if (!suplibHardenedMemComp(pThis->aSecHdrs[i].Name, ".mrdata", 8)) /* w8.1, ntdll */
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_UNEXPECTED_SECTION_FLAGS,
a57b3586d0f1a87e0024e318f3c8dad382113611vboxsync "%s: Section %u: Unexpected characteristics: %#x (uSectRva=%#x, cbMap=%#x)",
b2640405e06105d868b5fc8f7b676bb680884380vboxsync pImage->pszName, i, pThis->aSecHdrs[i].Characteristics, uSectRva, cbMap);
8ad79874169cc981a694a15e8a806b9a39133673vboxsync rc = supHardNtVpCheckSectionProtection(pThis, pImage, uSectRva, RT_ALIGN_32(cbMap, PAGE_SIZE), fProt);
cf2d13234ccc8755e2610badbdab5dc0b7bfb1dcvboxsync /* Advance the RVA. */
return VINF_SUCCESS;
InitializeObjectAttributes(&ObjAttr, &pImage->Name.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
#ifdef IN_RING0
&ObjAttr,
&Ios,
return rc;
NTSTATUS rcNt = NtQueryInformationThread(hThread, ThreadAmILastThread, &fAmI, sizeof(fAmI), &cbIgn);
if (!fAmI)
return VINF_SUCCESS;
#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
if (uPtr != 0)
return VINF_SUCCESS;
if (pThis)
return pThis;
supHardNtVpSetInfo1(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %zu bytes for state structures.", sizeof(*pThis));
return NULL;
if (!ch1)
static int supHardNtVpNewImage(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, PMEMORY_BASIC_INFORMATION pMemInfo)
while ( cwcDirName > 0
pwszFilename--;
cwcDirName--;
if (!*pwszFilename)
while ( cwcDirName > 0
cwcDirName--;
"See http://www.symantec.com/connect/articles/creating-application-control-exclusions-symantec-endpoint-protection-121"
return pThis->rcResult = VERR_SUP_VP_SYSFER_DLL; /* Try make sure this is what the user sees first! */
"Invalid AllocationBase/BaseAddress for %s: %p vs %p.",
return VINF_SUCCESS;
static int supHardNtVpAddRegion(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, PMEMORY_BASIC_INFORMATION pMemInfo)
return VINF_SUCCESS;
(void const *)uPtrWhere,
&MemInfo,
sizeof(MemInfo),
&cbActual);
(void const *)uPtrWhere,
&cbActual);
pThis->aImages[iImg].Name.UniStr.Buffer[pThis->aImages[iImg].Name.UniStr.Length / sizeof(WCHAR)] = '\0';
bool fNew = true;
while (iSearch-- > 0)
if (supHardNtVpAreUniStringsEqual(&pThis->aImages[iSearch].Name.UniStr, &pThis->aImages[iImg].Name.UniStr))
return rc;
fNew = false;
if (fNew)
return rc;
return rc;
else if ( (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))
&& cXpExceptions == 0
else if (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))
# ifdef IN_RING3
unsigned cExecs = 0;
unsigned iExe = ~0U;
cExecs++;
iExe = i;
if (cExecs == 0)
int rc;
if (!pUniStr)
NTSTATUS rcNt = NtQueryInformationProcess(hProcess, ProcessImageFileName, pUniStr, cbUniStr - sizeof(WCHAR), &cbIgn);
return rc;
return rc;
rcNt = NtQueryInformationProcess(hProcess, ProcessImageInformation, &ImageInfo, sizeof(ImageInfo), NULL);
return VINF_SUCCESS;
uint32_t j = i;
iNtDll = i;
iKernel32 = i;
iApiSetSchema = i;
pThis->aImages[i].fApiSetSchemaOnlySection1 = i == iApiSetSchema && pThis->aImages[i].cRegions == 1;
return rc;
return VINF_SUCCESS;
#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
if (pThis)
return rc;