SUPDrv-win.cpp revision 7977a6394c1f7cf0668245e17a04230461aa767e
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * VBoxDrv - The VirtualBox Support Driver - Windows NT specifics.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2012 Oracle Corporation
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * available from http://www.virtualbox.org. This file is free software;
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync* Header Files *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Defined Constants And Macros *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** The support service name. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** The Pool tag (VBox). */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** NT device name for system access. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** NT device name for user access. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** NT device name for hardened stub access. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync# define DEVICE_NAME_NT_STUB L"\\Device\\VBoxDrvStub"
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Macro for checking for deflecting calls to the stub device. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) \
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync do { if ((a_pDevObj) == g_pDevObjStub) supdrvNtCompleteRequest(STATUS_ACCESS_DENIED, a_pIrp); } while (0)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) do {} while (0)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Enables the fast I/O control code path. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Structures and Typedefs *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Device extension used by VBoxDrvU.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Global cookie (same location as in SUPDRVDEVEXT, different value). */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Pointer to the main driver extension. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncAssertCompileMembersAtSameOffset(SUPDRVDEVEXT, u32Cookie, SUPDRVDEVEXTUSR, u32Cookie);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to the VBoxDrvU device extension. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Value of SUPDRVDEVEXTUSR::u32Cookie. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Get the main device extension. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync : ((PSUPDRVDEVEXTUSR)pDevObj->DeviceExtension)->pMainDrvExt )
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Device extension used by VBoxDrvS.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Common header. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to the VBoxDrvS device extension. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Value of SUPDRVDEVEXTSTUB::Common.u32Cookie. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync#define SUPDRVDEVEXTSTUB_COOKIE UINT32_C(0x90abcdef)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * The kind of process we're protecting.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Stub process protection while performing process verification.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Next: StubSpawning (or free) */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Stub process protection before it creates the VM process.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Next: StubParent, StubDead. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Stub process protection while having a VM process as child.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Next: StubDead */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Dead stub process. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Potential VM process.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Next: VmProcessConfirmed, VmProcessDead. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Confirmed VM process.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Next: VmProcessDead. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Dead VM process. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** End of valid protection kinds. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * A NT process protection structure.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** The AVL node core structure. The process ID is the pid. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Magic value (SUPDRVNTPROTECT_MAGIC). */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Reference counter. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** The kind of process we're protecting. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** 8.1: Hack to allow more rights to the handle returned by
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle duplicated by CSR
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * during process creation. Only applicable to VmProcessUnconfirmed. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** 7,: Hack to allow the supid themes service duplicate handle privileges to
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * our process. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** The parent PID for VM processes, otherwise NULL. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** The PID of the CSRSS process associated with this process. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** Pointer to the CSRSS process structure (referenced). */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** State dependent data. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** A stub process in the StubParent state will keep a reference to a child
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * while it's in the VmProcessUnconfirmed state so that it can be cleaned up
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * correctly if things doesn't work out. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** A process in the VmProcessUnconfirmed state will keep a weak
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * reference to the parent's protection structure so it can clean up the pChild
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * refernece the parent has to it. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to a NT process protection record. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** The SUPDRVNTPROTECT::u32Magic value (Robert A. Heinlein). */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** The SUPDRVNTPROTECT::u32Magic value of a dead structure. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync# define SUPDRVNTPROTECT_MAGIC_DEAD UINT32_C(0x19880508)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to ObRegisterCallbacks. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsynctypedef NTSTATUS (NTAPI *PFNOBREGISTERCALLBACKS)(POB_CALLBACK_REGISTRATION, PVOID *);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to ObUnregisterCallbacks. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsynctypedef VOID (NTAPI *PFNOBUNREGISTERCALLBACKS)(PVOID);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to PsSetCreateProcessNotifyRoutineEx. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsynctypedef NTSTATUS (NTAPI *PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)(PCREATE_PROCESS_NOTIFY_ROUTINE_EX, BOOLEAN);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to PsReferenceProcessFilePointer. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsynctypedef NTSTATUS (NTAPI *PFNPSREFERENCEPROCESSFILEPOINTER)(PEPROCESS, PFILE_OBJECT *);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to PsIsProtectedProcessLight. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsynctypedef BOOLEAN (NTAPI *PFNPSISPROTECTEDPROCESSLIGHT)(PEPROCESS);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync#endif /* VBOX_WITH_HARDENINIG */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Internal Functions *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic void _stdcall VBoxDrvNtUnload(PDRIVER_OBJECT pDrvObj);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtCleanup(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput,
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic VOID _stdcall VBoxPowerDispatchCallback(PVOID pCallbackContext, PVOID pArgument1, PVOID pArgument2);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic void supdrvNtProtectTerm(void);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid,
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic void supdrvNtProtectRelease(PSUPDRVNTPROTECT pNtProtect);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic PSUPDRVNTPROTECT supdrvNtProtectLookup(HANDLE hPid);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int supdrvNtProtectFindAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int supdrvNtProtectVerifyProcess(PSUPDRVNTPROTECT pNtProtect);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic bool supdrvNtIsDebuggerAttached(void);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Exported Functions *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Global Variables *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to the system device instance. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to the user device instance. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Fast I/O dispatch table. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic FAST_IO_DISPATCH const g_VBoxDrvFastIoDispatch =
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /* .SizeOfFastIoDispatch = */ sizeof(g_VBoxDrvFastIoDispatch),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /* .FastIoDeviceControl = */ VBoxDrvNtFastIoDeviceControl,
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync#endif /* VBOXDRV_WITH_FAST_IO */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Pointer to the stub device instance. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Spinlock protecting g_NtProtectTree as well as the releasing of protection
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * structures. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic RTSPINLOCK g_hNtProtectLock = NIL_RTSPINLOCK;
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** AVL tree of SUPDRVNTPROTECT structures. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** Cookie returned by ObRegisterCallbacks for the callbacks. */
# ifdef RT_ARCH_AMD64
NTSTATUS rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjSys);
rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXTUSR), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjUsr);
#ifdef VBOX_WITH_HARDENING
rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXTSTUB), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjStub);
return rcNt;
#ifdef VBOX_WITH_HARDENING
return rcNt;
static void vboxdrvNtDestroyDevices(void)
if (g_pDevObjUsr)
#ifdef VBOX_WITH_HARDENING
if (g_pDevObjStub)
#ifdef VBOX_WITH_HARDENING
#ifdef VBOXDRV_WITH_FAST_IO
return STATUS_INTERNAL_ERROR;
#ifdef VBOX_WITH_HARDENING
if (!vrc)
#ifdef VBOXDRV_WITH_FAST_IO
return STATUS_SUCCESS;
#ifdef VBOX_WITH_HARDENING
RTR0Term();
return rcNt;
#ifdef VBOX_WITH_HARDENING
RTR0Term();
return rcNt;
#ifdef VBOX_WITH_HARDENING
LogRel(("vboxdrv: Declined %p access to VBoxDrvStub: rc=%d\n", PsGetProcessId(PsGetCurrentProcess()), rc));
if (pNtProtect)
&pSession);
rc = supdrvCreateSession(pDevExt, true /*fUser*/, pDevObj == g_pDevObjSys /*fUnrestricted*/, &pSession);
return supdrvNtCompleteRequest(rcNt, pIrp); /* Note. the IoStatus is completely ignored on error. */
#ifdef VBOX_WITH_HARDENING
if (pNtProtect)
if (pSession)
#ifdef VBOX_WITH_HARDENING
if (pNtProtect)
if (pSession)
#ifdef VBOXDRV_WITH_FAST_IO
static BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput,
if (!pSession)
return TRUE;
if (supdrvNtIsDebuggerAttached())
return TRUE;
return TRUE;
unsigned cbOut = 0;
int rc = 0;
Log2(("VBoxDrvNtFastIoDeviceControl(%p): ioctl=%#x pvIn=%p cbIn=%#x pvOut=%p cbOut=%#x pSession=%p\n",
# ifdef RT_ARCH_AMD64
if (pHdr)
if (cbOut)
# ifdef RT_ARCH_AMD64
if (supdrvNtIsDebuggerAttached())
int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession);
static int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack)
unsigned cbOut = 0;
int rc = 0;
#ifdef RT_ARCH_AMD64
if (!rc)
#ifdef RT_ARCH_AMD64
return rcNt;
unsigned cbOut = 0;
int rc = 0;
: !pSession
if (!rc)
return rcNt;
return STATUS_NOT_SUPPORTED;
if ((unsigned)pArgument2 == 0)
#ifdef VBOX_WITH_HARDENING
void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
typedef struct MYSYSTEMGDIDRIVERINFO
int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
# ifndef RT_ARCH_X86
return VERR_NOT_SUPPORTED;
return rc;
if (!pwcsFilename)
return VERR_NO_TMP_MEMORY;
NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemLoadGdiDriverInSystemSpaceInformation, &Info, sizeof(Info));
Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer));
# ifdef DEBUG_bird
Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer);
rc = RTR0MemObjLockKernel(&pImage->hMemLock, pImage->pvImage, pImage->cbImageBits, RTMEM_PROT_READ);
switch (rcNt)
# ifdef RT_ARCH_AMD64
return rc;
int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
return VINF_SUCCESS;
static int supdrvNtCompare(PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, uint32_t uRva, uint32_t cb)
if (iDiff)
return iDiff;
int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
return VINF_SUCCESS;
&& pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size >= sizeof(IMAGE_IMPORT_DESCRIPTOR)
&& pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress > sizeof(IMAGE_NT_HEADERS)
&& pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress < pImage->cbImageBits
struct MyRegion
unsigned cExcludeRgns = 0;
/ sizeof(IMAGE_IMPORT_DESCRIPTOR);
while ( cImpsLeft-- > 0
cThunks++;
for (; i < cExcludeRgns; i++)
if (i != cExcludeRgns)
cExcludeRgns++;
pImp++;
int iDiff = 0;
if (!iDiff)
return VINF_SUCCESS;
return VERR_LDR_MISMATCH_NATIVE;
return VERR_INTERNAL_ERROR_4;
#ifdef SUPDRV_WITH_MSR_PROBER
typedef struct SUPDRVNTMSPROBERARGS
bool fGp;
return rc;
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
return rc;
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
bool fBeforeGp = true;
bool fModifyGp = true;
bool fAfterGp = true;
bool fRestoreGp = true;
if (!fFaster)
fBeforeGp = false;
fBeforeGp = true;
if (!fBeforeGp)
fModifyGp = false;
fModifyGp = true;
fAfterGp = false;
fAfterGp = true;
fRestoreGp = false;
fRestoreGp = true;
if (!fFaster)
ASMReloadCR3();
ASMNopPause();
return VINF_SUCCESS;
switch (rc)
if (rc < 0)
return STATUS_UNSUCCESSFUL;
#ifdef VBOX_WITH_HARDENING
if (!pszImageFile)
} Buf;
if (!chRight)
int rc;
if (uSessionId == 0)
&pvApiPortObj);
return VERR_SUPDRV_APIPORT_OPEN_ERROR;
if (!pbBuf)
cbNeeded = 0;
if ( pbBuf
bool fThatsIt = false;
ppPortProc++;
fThatsIt = false;
if (fThatsIt)
return rc;
static bool supdrvNtProtectIsFrigginThemesService(PSUPDRVNTPROTECT pNtProtect, PEPROCESS pAnnoyingProcess)
static bool supdrvNtProtectIsSpawningStubProcess(PSUPDRVNTPROTECT pNtStub, HANDLE hParentPid, HANDLE hChildPid)
bool fRc = false;
return fRc;
int rc = supdrvNtProtectCreate(&pNtChild, hChildPid, kSupDrvNtProtectKind_VmProcessUnconfirmed, false /*fLink*/);
if (fSuccess)
return VINF_SUCCESS;
return rc;
if (pNtProtect)
if (g_pDevObjSys)
if (pSession)
static void supdrvNtProtectVerifyNewChildProtection(PSUPDRVNTPROTECT pNtStub, PSUPDRVNTPROTECT pNtVm, bool fCallerChecks)
if ( fCallerChecks
LogRel(("vboxdrv: Misdetected vm stub; hParentPid=%p hChildPid=%p\n", pNtStub->AvlCore.Key, pNtVm->AvlCore.Key));
if (fCreated)
if (pNtStub)
if (!pNtVm)
supdrvNtProtectCallback_ProcessCreateNotifyEx(PEPROCESS pNewProcess, HANDLE hNewPid, PPS_CREATE_NOTIFY_INFO pInfo)
if (pInfo)
pInfo->FileOpenNameAvailable && pInfo->ImageFileName ? (size_t)pInfo->ImageFileName->Length / 2 : 0,
if (pNtStub)
if (!pNtVm)
# define SUPDRV_NT_ALLOW_PROCESS_RIGHTS \
| PROCESS_VM_READ \
| DELETE \
| READ_CONTROL \
| SYNCHRONIZE)
# define SUPDRV_NT_EVIL_PROCESS_RIGHTS \
| PROCESS_VM_WRITE \
Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
if (!pNtProtect)
if (pNtStub)
if (pNtProtect)
&& pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == 0x1478 /* 6.1.7600.16385 (win7_rtm.090713-1255) */
Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p wants %#x to %p/pid=%04zx [%d], allow %#x => %#x; %s\n",
Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
return OB_PREOP_SUCCESS;
Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
/* From ntifs.h */
# define SUPDRV_NT_ALLOWED_THREAD_RIGHTS \
( THREAD_TERMINATE \
| DELETE \
| READ_CONTROL \
| SYNCHRONIZE)
# define SUPDRV_NT_EVIL_THREAD_RIGHTS \
Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
if (pNtProtect)
Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p wants %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s\n",
Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] self\n",
Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s\n",
return OB_PREOP_SUCCESS;
Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
fGrantedAccess, SUPDRV_NT_ALLOWED_THREAD_RIGHTS, fGrantedAccess & ~SUPDRV_NT_ALLOWED_THREAD_RIGHTS));
static int supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid, SUPDRVNTPROTECTKIND enmProcessKind, bool fLink)
if (!pNtProtect)
return VERR_NO_MEMORY;
if (fLink)
if (!fSuccess)
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
if (!pNtProtect)
if (cRefs != 0)
PSUPDRVNTPROTECT pRemoved = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pNtProtect->AvlCore.Key);
if (pChild)
if (!cChildRefs)
if (pChild)
if (pFound)
return pFound;
if (!pbBuf)
return VERR_NO_MEMORY;
const char *pszType;
# ifndef VBOX_WITH_VISTA_NO_SP
return rc;
AssertReturn(PsGetProcessId(PsGetCurrentProcess()) == pNtProtect->AvlCore.Key, VERR_INTERNAL_ERROR_3);
pNtProtect->enmProcessKind = RT_SUCCESS(rc) ? kSupDrvNtProtectKind_StubSpawning : kSupDrvNtProtectKind_StubDead;
return rc;
# ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
static bool supdrvNtIsDebuggerAttached(void)
static void supdrvNtProtectTerm(void)
rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, TRUE /*fRemove*/);
# ifdef RT_ARCH_X86
g_pfnPsSetCreateProcessNotifyRoutineEx = (PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)MmGetSystemRoutineAddress(&RoutineName);
g_pfnPsReferenceProcessFilePointer = (PFNPSREFERENCEPROCESSFILEPOINTER)MmGetSystemRoutineAddress(&RoutineName);
g_pfnPsIsProtectedProcessLight = (PFNPSISPROTECTEDPROCESSLIGHT)MmGetSystemRoutineAddress(&RoutineName);
# ifdef RT_ARCH_X86
case 0xb0: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xAF; break; /* just in case */
case 0xb1: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB0; break; /* just in case */
case 0xb2: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB1; break; /* just in case */
case 0xb3: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* XP SP3 */
case 0xb4: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* just in case */
case 0xb5: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB3; break; /* just in case */
case 0xb6: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB4; break; /* just in case */
case 0xb7: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB5; break; /* just in case */
case 0xb8: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB6; break; /* just in case */
case 0xb9: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB7; break; /* just in case */
case 0xba: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB8; break; /* just in case */
case 0xbb: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBA; break; /* W2K3 R2 SP2 */
case 0xbc: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBB; break; /* just in case */
case 0xbd: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBC; break; /* just in case */
case 0xbe: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBD; break; /* just in case */
case 0xbf: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBE; break; /* just in case */
case 0x1e: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x1F; break;
case 0x1f: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x20; break;
case 0x20: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x21; break;
case 0x21: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x22; break;
case 0x22: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x23; break;
LogRel(("vboxdrv: Cannot locate ZwQueryVirtualMemory in ntoskrnl, nor were we able to cook up a replacement.\n"));
return STATUS_PROCEDURE_NOT_FOUND;
rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, FALSE /*fRemove*/);
rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, FALSE /*fRemove*/);
for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszAltitudes) && rcNt == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION; i++)
return STATUS_SUCCESS;
# ifndef VBOX_WITH_VISTA_NO_SP
DbgPrint("vboxdrv: ObRegisterCallbacks was not found. Please make sure you got the latest updates and service packs installed\n");
g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
return rcNt;