cheat-engine/DBKKernel/IOPLDispatcher.c
pyj2323 4e81c3bc6a
Update IOPLDispatcher.c
alloc contiguously
2021-06-05 09:25:46 +09:00

2540 lines
60 KiB
C

#pragma warning( disable: 4100 4101 4103 4189)
#include "IOPLDispatcher.h"
#include "DBKFunc.h"
#include "DBKDrvr.h"
#include "memscan.h"
#include "deepkernel.h"
#include "processlist.h"
#include "threads.h"
#include "interruptHook.h"
#include "debugger.h"
#include "vmxhelper.h"
#include "vmxoffload.h"
#include "ultimap.h"
#include "ultimap2.h"
UINT64 PhysicalMemoryRanges=0; //initialized once, and used thereafter. If the user adds/removes ram at runtime, screw him and make him the reload the driver
UINT64 PhysicalMemoryRangesListSize=0;
#if (NTDDI_VERSION >= NTDDI_VISTA)
PVOID DRMHandle = NULL;
PEPROCESS DRMProcess = NULL;
PEPROCESS DRMProcess2 = NULL;
#endif
typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
GET_PROCESS_IMAGE_NAME PsGetProcessImageFileName;
/*
typedef struct
{
int listcount;
char cpunrs[255];
} CPULISTFILLSTRUCT, *PCPULISTFILLSTRUCT;
VOID GetCPUIDS_all(PCPULISTFILLSTRUCT p)
{
DbgPrint("GetCPUIDS_all(for cpu %d)\n", cpunr());
if (p->listcount<255)
{
p->cpunrs[p->listcount]=cpunr();
p->listcount++;
}
}
*/
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL);
void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
ULONG_PTR iswow64;
ExFreePool(Apc);
DbgPrint("My second kernelmode apc!!!!\n");
DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument1);
DbgPrint("SystemArgument2=%x\n", *(PULONG)SystemArgument2);
if (ZwQueryInformationProcess(ZwCurrentProcess(), ProcessWow64Information, &iswow64, sizeof(iswow64), NULL) == STATUS_SUCCESS)
{
#if (NTDDI_VERSION >= NTDDI_VISTA)
if (iswow64)
{
DbgPrint("WOW64 apc");
PsWrapApcWow64Thread(NormalContext, (PVOID*)NormalRoutine);
}
#endif
}
}
void nothing2(PVOID arg1, PVOID arg2, PVOID arg3)
{
return;
}
void mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//kernelmode apc, always gets executed
PKAPC kApc;
LARGE_INTEGER Timeout;
kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
ExFreePool(Apc);
DbgPrint("My kernelmode apc!!!!(irql=%d)\n", KeGetCurrentIrql());
DbgPrint("NormalRoutine=%p\n",*(PUINT_PTR)NormalRoutine);
DbgPrint("NormalContext=%p\n",*(PUINT_PTR)NormalContext);
DbgPrint("SystemArgument1=%p\n",*(PUINT_PTR)SystemArgument1);
DbgPrint("SystemArgument2=%p\n",*(PUINT_PTR)SystemArgument2);
KeInitializeApc(kApc,
(PKTHREAD)PsGetCurrentThread(),
0,
(PKKERNEL_ROUTINE)mykapc2,
NULL,
(PKNORMAL_ROUTINE)*(PUINT_PTR)SystemArgument1,
UserMode,
(PVOID)*(PUINT_PTR)NormalContext
);
KeInsertQueueApc (kApc, (PVOID)*(PUINT_PTR)SystemArgument1, (PVOID)*(PUINT_PTR)SystemArgument2, 0);
//wait in usermode (so interruptable by a usermode apc)
Timeout.QuadPart = 0;
KeDelayExecutionThread(UserMode, TRUE, &Timeout);
return;
}
void nothing(PVOID arg1, PVOID arg2, PVOID arg3)
{
return;
}
void CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)
{
PKTHREAD kThread;
PKAPC kApc;
kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
kThread=(PKTHREAD)getPEThread(threadid);
DbgPrint("(PVOID)KThread=%p\n",kThread);
DbgPrint("addresstoexecute=%p\n", addresstoexecute);
KeInitializeApc(kApc,
kThread,
0,
(PKKERNEL_ROUTINE)mykapc,
NULL,
(PKNORMAL_ROUTINE)nothing,
KernelMode,
0
);
KeInsertQueueApc (kApc, addresstoexecute, addresstoexecute, 0);
}
#define PROCESS_TERMINATE (0x0001)
#define PROCESS_CREATE_THREAD (0x0002)
#define PROCESS_SET_SESSIONID (0x0004)
#define PROCESS_VM_OPERATION (0x0008)
#define PROCESS_VM_READ (0x0010)
#define PROCESS_VM_WRITE (0x0020)
#define PROCESS_DUP_HANDLE (0x0040)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_SET_QUOTA (0x0100)
#define PROCESS_SET_INFORMATION (0x0200)
#define PROCESS_QUERY_INFORMATION (0x0400)
#define PROCESS_SUSPEND_RESUME (0x0800)
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#if (NTDDI_VERSION >= NTDDI_VISTA)
OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
if (DRMProcess == NULL)
return OB_PREOP_SUCCESS;
if (PsGetCurrentProcess() == DRMProcess)
return OB_PREOP_SUCCESS;
if (OperationInformation->ObjectType == *PsThreadType)
{
if ((PsGetProcessId(DRMProcess) == PsGetThreadProcessId(OperationInformation->Object)) || ((DRMProcess2) && (PsGetProcessId(DRMProcess2) == PsGetThreadProcessId(OperationInformation->Object))))
{
//probably block it
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
//create handle
ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
DbgPrint("PID %d opened a handle to the a CE thread with access mask %x", PsGetCurrentProcessId(), da);
da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
}
else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
//duplicate handle
ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;
DbgPrint("PID %d duplicated a handle to a CE thread with access mask %x", PsGetCurrentProcessId(), da);
da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
}
}
}
return OB_PREOP_SUCCESS;
}
VOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
//DbgPrint("ProcessPostCallback");
}
OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
if (DRMProcess == NULL)
return OB_PREOP_SUCCESS;
//if (PsGetCurrentProcess() == DRMProcess)
// return OB_PREOP_SUCCESS;
if (OperationInformation->ObjectType == *PsProcessType)
{
if ((OperationInformation->Object == DRMProcess) || (OperationInformation->Object == DRMProcess2))
{
//probably block it
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
//create handle
ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);
da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);
//da = da & PROCESS_SUSPEND_RESUME;
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
}
else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
//duplicate handle
ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;
DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);
da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);
//da = da & PROCESS_SUSPEND_RESUME;
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
}
}
}
return OB_PREOP_SUCCESS;
}
VOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
//DbgPrint("ProcessPostCallback");
}
#endif
BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned)
/*
Called if dbvm has loaded the driver. Use this to setup a fake irp
*/
{
//allocate a in and out buffer
//setup a fake IRP
IRP FakeIRP;
BOOL r;
PVOID buffer;
buffer=ExAllocatePool(PagedPool, max(nInBufferSize, nOutBufferSize));
RtlCopyMemory(buffer, lpInBuffer, nInBufferSize);
DbgPrint("DispatchIoctlDBVM\n");
FakeIRP.AssociatedIrp.SystemBuffer=buffer;
FakeIRP.Flags=IoControlCode; //(ab)using an unused element
r=DispatchIoctl(DeviceObject, &FakeIRP)==STATUS_SUCCESS;
RtlCopyMemory(lpOutBuffer, buffer, nOutBufferSize);
ExFreePool(buffer);
return r;
}
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION irpStack=NULL;
LUID sedebugprivUID;
ULONG IoControlCode;
if (!loadedbydbvm)
{
irpStack=IoGetCurrentIrpStackLocation(Irp);
IoControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
}
else
IoControlCode=Irp->Flags;
//DbgPrint("DispatchIoctl. IoControlCode=%x\n", IoControlCode);
#ifdef TOBESIGNED
sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;
sedebugprivUID.HighPart=0;
if (SeSinglePrivilegeCheck(sedebugprivUID, UserMode)==FALSE)
{
DbgPrint("DispatchIoctl called by a process without SeDebugPrivilege");
return STATUS_UNSUCCESSFUL;
}
#endif
switch(IoControlCode)
{
case IOCTL_CE_READMEMORY:
__try
{
struct input
{
UINT64 processid;
UINT64 startaddress;
WORD bytestoread;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ReadProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestoread,pinp) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
__except(1)
{
ntStatus = STATUS_UNSUCCESSFUL;
};
break;
case IOCTL_CE_WRITEMEMORY:
__try
{
struct input
{
UINT64 processid;
UINT64 startaddress;
WORD bytestowrite;
} *pinp,inp;
DbgPrint("sizeof(inp)=%d\n",sizeof(inp));
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=WriteProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestowrite,(PVOID)((UINT_PTR)pinp+sizeof(inp))) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
__except(1)
{
//something went wrong and I don't know what
ntStatus = STATUS_UNSUCCESSFUL;
};
break;
case IOCTL_CE_OPENPROCESS:
{
PEPROCESS selectedprocess = NULL;
ULONG processid=*(PULONG)Irp->AssociatedIrp.SystemBuffer;
HANDLE ProcessHandle = GetHandleForProcessID((HANDLE)processid);
struct out
{
UINT64 h;
BYTE Special;
} *POutput = Irp->AssociatedIrp.SystemBuffer;
ntStatus = STATUS_SUCCESS;
if (ProcessHandle == 0)
{
POutput->Special = 0;
__try
{
ProcessHandle = 0;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid), &selectedprocess) == STATUS_SUCCESS)
{
//DbgPrint("Calling ObOpenObjectByPointer\n");
ntStatus = ObOpenObjectByPointer(
selectedprocess,
0,
NULL,
PROCESS_ALL_ACCESS,
*PsProcessType,
KernelMode, //UserMode,
&ProcessHandle);
//DbgPrint("ntStatus=%x",ntStatus);
}
}
__except (1)
{
ntStatus = STATUS_UNSUCCESSFUL;
}
}
else
{
//DbgPrint("ProcessHandle=%x", (int)ProcessHandle);
POutput->Special = 1;
}
if (selectedprocess)
{
ObDereferenceObject(selectedprocess);
}
POutput->h=(UINT64)ProcessHandle;
break;
}
case IOCTL_CE_OPENTHREAD:
{
HANDLE ThreadHandle;
CLIENT_ID ClientID;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlZeroMemory(&ObjectAttributes,sizeof(OBJECT_ATTRIBUTES));
ntStatus=STATUS_SUCCESS;
ClientID.UniqueProcess=0;
ClientID.UniqueThread=(HANDLE)(UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer;
ThreadHandle=0;
__try
{
ThreadHandle=0;
ntStatus=ZwOpenThread(&ThreadHandle,PROCESS_ALL_ACCESS,&ObjectAttributes,&ClientID);
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)ThreadHandle;
break;
}
case IOCTL_CE_MAKEWRITABLE:
{
#ifdef AMD64
//untill I know how win64 handles paging, not implemented
#else
struct InputBuf
{
UINT64 StartAddress;
ULONG Size;
BYTE CopyOnWrite;
} *PInputBuf;
PInputBuf=Irp->AssociatedIrp.SystemBuffer;
ntStatus=MakeWritable((PVOID)(UINT_PTR)PInputBuf->StartAddress,PInputBuf->Size,(PInputBuf->CopyOnWrite==1)) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
#endif
break;
}
case IOCTL_CE_QUERY_VIRTUAL_MEMORY:
{
struct InputBuf
{
UINT64 ProcessID;
UINT64 StartAddress;
} *PInputBuf;
struct OutputBuf
{
UINT64 length;
DWORD protection;
} *POutputBuf;
UINT_PTR BaseAddress;
UINT_PTR length;
BOOL ShowResult=0;
ntStatus=STATUS_SUCCESS;
PInputBuf=Irp->AssociatedIrp.SystemBuffer;
POutputBuf=Irp->AssociatedIrp.SystemBuffer;
if (PInputBuf->StartAddress==(UINT64)0x12000)
ShowResult=1;
__try
{
ntStatus = GetMemoryRegionData((DWORD)PInputBuf->ProcessID, NULL, (PVOID)(UINT_PTR)(PInputBuf->StartAddress), &(POutputBuf->protection), &length, &BaseAddress);
}
__except(1)
{
DbgPrint("GetMemoryRegionData error");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
POutputBuf->length=(UINT64)length;
if (ShowResult)
{
DbgPrint("GetMemoryRegionData returned %x\n",ntStatus);
DbgPrint("protection=%x\n",POutputBuf->protection);
DbgPrint("length=%p\n",POutputBuf->length);
DbgPrint("BaseAddress=%p\n", BaseAddress);
}
break;
}
case IOCTL_CE_TEST: //just a test to see it's working
{
UNICODE_STRING test;
PVOID x;
QWORD a, b;
_disable();
a = __rdtsc();
b = __rdtsc();
_enable();
DbgPrint("%d\n", (int)(b - a));
break;
}
case IOCTL_CE_GETPETHREAD:
{
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)getPEThread((UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer);
ntStatus= STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETPEPROCESS:
{
DWORD processid=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS selectedprocess;
if (processid==0)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
else
{
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid),&selectedprocess)==STATUS_SUCCESS)
{
#ifdef AMD64
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)selectedprocess;
#else
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(DWORD)selectedprocess;
#endif
//DbgPrint("PEProcess=%llx\n", *(PUINT64)Irp->AssociatedIrp.SystemBuffer);
ObDereferenceObject(selectedprocess);
}
else
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
}
ntStatus= STATUS_SUCCESS;
break;
}
case IOCTL_CE_READPHYSICALMEMORY:
{
struct input
{
UINT64 startaddress;
UINT64 bytestoread;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_READPHYSICALMEMORY:pinp->startaddress=%x, pinp->bytestoread=%d", pinp->startaddress, pinp->bytestoread);
ntStatus = ReadPhysicalMemory((PVOID)(UINT_PTR)pinp->startaddress, (UINT_PTR)pinp->bytestoread, pinp);
break;
}
case IOCTL_CE_WRITEPHYSICALMEMORY:
{
HANDLE physmem;
UNICODE_STRING physmemString;
OBJECT_ATTRIBUTES attributes;
WCHAR physmemName[] = L"\\device\\physicalmemory";
UCHAR* memoryview;
RtlInitUnicodeString( &physmemString, physmemName );
InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );
ntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );
if (ntStatus==STATUS_SUCCESS)
{
//hey look, it didn't kill it
struct input
{
UINT64 startaddress;
UINT64 bytestoread;
} *pinp;
UCHAR* pinp2;
SIZE_T length;
PHYSICAL_ADDRESS viewBase;
UINT_PTR offset;
UINT_PTR toread;
pinp=Irp->AssociatedIrp.SystemBuffer;
pinp2=(UCHAR *)pinp;
viewBase.QuadPart = (ULONGLONG)(pinp->startaddress);
length=0x2000;//pinp->bytestoread;
toread=(UINT_PTR)pinp->bytestoread;
memoryview=NULL;
ntStatus=ZwMapViewOfSection(
physmem, //sectionhandle
NtCurrentProcess(), //processhandle
&memoryview, //BaseAddress
0L, //ZeroBits
length, //CommitSize
&viewBase, //SectionOffset
&length, //ViewSize
ViewShare,
0,
PAGE_READWRITE);
if (ntStatus==STATUS_SUCCESS)
{
offset=(UINT_PTR)(pinp->startaddress)-(UINT_PTR)viewBase.QuadPart;
RtlCopyMemory(&memoryview[offset],&pinp2[16],toread);
ZwUnmapViewOfSection(
NtCurrentProcess(), //processhandle
memoryview);
}
ZwClose(physmem);
}
break;
}
case IOCTL_CE_GETPHYSICALADDRESS:
{
struct input
{
UINT64 ProcessID;
UINT64 BaseAddress;
} *pinp;
PEPROCESS selectedprocess;
PHYSICAL_ADDRESS physical;
physical.QuadPart = 0;
ntStatus=STATUS_SUCCESS;
pinp=Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_GETPHYSICALADDRESS. ProcessID(%p)=%x BaseAddress(%p)=%x\n",&pinp->ProcessID, pinp->ProcessID, &pinp->BaseAddress, pinp->BaseAddress);
__try
{
//switch to the selected process
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(pinp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess,&apc_state);
__try
{
physical=MmGetPhysicalAddress((PVOID)(UINT_PTR)pinp->BaseAddress);
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
ObDereferenceObject(selectedprocess);
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
if (ntStatus==STATUS_SUCCESS)
{
//DbgPrint("physical.LowPart=%x",physical.LowPart);
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&physical.QuadPart,8);
}
break;
}
case IOCTL_CE_GETMEMORYRANGES:
{
struct output
{
UINT64 address;
UINT64 size;
} *poutp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_GETMEMORYRANGES\n");
if (PhysicalMemoryRanges==0)
{
__try
{
PPHYSICAL_MEMORY_RANGE mr=MmGetPhysicalMemoryRanges();
if (mr)
{
//find the end
int i;
PhysicalMemoryRanges=(UINT64)mr;
for (i=0; mr[i].NumberOfBytes.QuadPart || mr[i].BaseAddress.QuadPart; i++);
PhysicalMemoryRangesListSize=(UINT64)(&mr[i])-(UINT64)(&mr[0]);
}
}
__except(1)
{
//just in case this function decides to bug out in the future
}
}
poutp->address=PhysicalMemoryRanges;
poutp->size=PhysicalMemoryRangesListSize;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETSDTADDRESS:
{
DbgPrint("Obsolete\n");
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
case IOCTL_CE_GETCR0:
{
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=getCR0();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETCR4:
{
//seems CR4 isn't seen as a register...
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=(UINT64)getCR4();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETCR4:
{
//seems CR4 isn't seen as a register...
ULONG cr4reg=*(ULONG*)Irp->AssociatedIrp.SystemBuffer;
setCR4((UINT64)cr4reg);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETCR3:
{
UINT_PTR cr3reg=0;
PEPROCESS selectedprocess;
ntStatus=STATUS_SUCCESS;
//switch context to the selected process. (processid is stored in the systembuffer)
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(*(ULONG*)Irp->AssociatedIrp.SystemBuffer),&selectedprocess)==STATUS_SUCCESS)
{
__try
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess,&apc_state);
__try
{
cr3reg=(UINT_PTR)getCR3();
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
DbgPrint("cr3reg=%p\n",cr3reg);
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=cr3reg;
break;
}
case IOCTL_CE_GETSDT:
{
//returns the address of KeServiceDescriptorTable
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
case IOCTL_CE_GETIDT:
{
//returns the address of the IDT of the current CPU
IDT idt;
RtlZeroMemory(&idt,sizeof(IDT));
GetIDT(&idt);
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); //so that the 32-bit version doesn't have to deal with garbage at the end
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&idt,sizeof(IDT)); //copy idt
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETGDT:
{
//returns the address of the IDT of the current CPU
GDT gdt;
RtlZeroMemory(&gdt,sizeof(GDT));
GetGDT(&gdt);
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8);
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&gdt,sizeof(GDT)); //copy gdt
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_LAUNCHDBVM:
{
struct intput
{
UINT64 dbvmimgpath;
DWORD32 cpuid;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_LAUNCHDBVM\n");
initializeDBVM((PCWSTR)(UINT_PTR)pinp->dbvmimgpath);
if (pinp->cpuid == 0xffffffff) {
forEachCpu(vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);
cleanupDBVM();
}
else
forOneCpu((CCHAR)pinp->cpuid, vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);
DbgPrint("Returned from vmxoffload()\n");
break;
}
case IOCTL_CE_HOOKINTS: //hooks the DEBUG interrupts
{
DbgPrint("IOCTL_CE_HOOKINTS\n");
forEachCpu(debugger_initHookForCurrentCPU_DPC, NULL, NULL, NULL, NULL);
ntStatus=STATUS_SUCCESS;
/*
DbgPrint("IOCTL_CE_HOOKINTS for cpu %d\n", cpunr());
if (debugger_initHookForCurrentCPU())
ntStatus=STATUS_SUCCESS;
else
ntStatus=STATUS_UNSUCCESSFUL;*/
break;
}
case IOCTL_CE_USERDEFINEDINTERRUPTHOOK:
{
struct intput
{
UINT64 interruptnumber;
UINT64 newCS;
UINT64 newRIP;
UINT64 addressofjumpback;
} *pinp;
DbgPrint("IOCTL_CE_USERDEFINEDINTERRUPTHOOK\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
inthook_HookInterrupt((unsigned char)(pinp->interruptnumber), (int)pinp->newCS, (ULONG_PTR)pinp->newRIP, (PJUMPBACK)(UINT_PTR)(pinp->addressofjumpback));
DbgPrint("After the hook\n");
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_UNHOOKALLINTERRUPTS:
{
int i;
DbgPrint("IOCTL_CE_UNHOOKALLINTERRUPTS for cpu %d\n",cpunr());
for (i=0; i<256; i++)
inthook_UnhookInterrupt((unsigned char)i);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETGLOBALDEBUGSTATE:
{
struct intput
{
BOOL newstate;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
debugger_setGlobalDebugState(pinp->newstate);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_DEBUGPROCESS:
{
struct input
{
DWORD ProcessID;
} *pinp;
DbgPrint("IOCTL_CE_DEBUGPROCESS\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
debugger_startDebugging(pinp->ProcessID);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_STOPDEBUGGING:
{
debugger_stopDebugging();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_STARTPROCESSWATCH:
{
NTSTATUS r = STATUS_SUCCESS;
DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");
ProcessWatcherOpensHandles = *(char *)Irp->AssociatedIrp.SystemBuffer != 0;
if (CreateProcessNotifyRoutineEnabled && WatcherProcess)
{
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
//still here
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
ProcessEventCount=0;
ExReleaseResourceLite(&ProcesslistR);
//DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");
CleanProcessList();
if ((r == STATUS_SUCCESS) && (CreateProcessNotifyRoutineEnabled == FALSE))
{
DbgPrint("calling PsSetCreateProcessNotifyRoutine\n");
#if (NTDDI_VERSION >= NTDDI_VISTASP1)
r=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx, FALSE);
CreateProcessNotifyRoutineEnabled = r== STATUS_SUCCESS;
#else
CreateProcessNotifyRoutineEnabled = (PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,FALSE)==STATUS_SUCCESS);
#endif
if (CreateProcessNotifyRoutineEnabled)
CreateThreadNotifyRoutineEnabled = (PsSetCreateThreadNotifyRoutine(CreateThreadNotifyRoutine) == STATUS_SUCCESS);
}
ntStatus=(CreateProcessNotifyRoutineEnabled) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
if (ntStatus==STATUS_SUCCESS)
DbgPrint("CreateProcessNotifyRoutineEnabled worked\n");
else
DbgPrint("CreateProcessNotifyRoutineEnabled failed (r=%x)\n",r);
break;
}
case IOCTL_CE_GETPROCESSEVENTS:
{
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ProcessEventCount;
RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ProcessEventdata[0],ProcessEventCount*sizeof(ProcessEventdta));
ProcessEventCount=0; //there's room for new events
ExReleaseResourceLite(&ProcesslistR);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETTHREADEVENTS:
{
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ThreadEventCount;
RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ThreadEventData[0],ThreadEventCount*sizeof(ThreadEventDta));
ThreadEventCount=0; //there's room for new events
ExReleaseResourceLite(&ProcesslistR);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_CREATEAPC:
{
struct input
{
UINT64 threadid;
UINT64 addresstoexecute;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
CreateRemoteAPC((ULONG)inp->threadid,(PVOID)(UINT_PTR)inp->addresstoexecute);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SUSPENDTHREAD:
{
struct input
{
ULONG threadid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("CE_SUSPENDTHREAD\n");
DBKSuspendThread(inp->threadid);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_RESUMETHREAD:
{
struct input
{
ULONG threadid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("CE_RESUMETHREAD\n");
DBKResumeThread(inp->threadid);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SUSPENDPROCESS:
{
struct input
{
ULONG processid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_SUSPENDPROCESS\n");
if (PsSuspendProcess)
{
PEPROCESS selectedprocess;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = PsSuspendProcess(selectedprocess);
ObDereferenceObject(selectedprocess);
}
else
ntStatus = STATUS_NOT_FOUND;
}
else
ntStatus = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_CE_RESUMEPROCESS:
{
struct input
{
ULONG processid;
} *inp;
inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_RESUMEPROCESS\n");
if (PsResumeProcess)
{
PEPROCESS selectedprocess;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = PsResumeProcess(selectedprocess);
ObDereferenceObject(selectedprocess);
}
else
ntStatus = STATUS_NOT_FOUND;
}
else
ntStatus = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_CE_ALLOCATEMEM:
{
struct input
{
UINT64 ProcessID;
UINT64 BaseAddress;
UINT64 Size;
UINT64 AllocationType;
UINT64 Protect;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp=Irp->AssociatedIrp.SystemBuffer;
BaseAddress=(PVOID)(UINT_PTR)inp->BaseAddress;
RegionSize=(SIZE_T)(inp->Size);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
{
__try
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeAttachProcess((PVOID)selectedprocess); //local process is much more fun!!!!
DbgPrint("Switched Process\n");
__try
{
DbgPrint("Calling ZwAllocateVirtualMemory\n");
DbgPrint("Before call: BaseAddress=%p\n", BaseAddress);
DbgPrint("Before call: RegionSize=%x\n", RegionSize);
ntStatus=ZwAllocateVirtualMemory((HANDLE)-1, &BaseAddress, 0, &RegionSize, (ULONG)inp->AllocationType, (ULONG)inp->Protect);
if ((ntStatus==STATUS_SUCCESS) && (HiddenDriver))
{
//initialize the memory with crap so it becomes paged
int i;
char *x;
x=BaseAddress;
for (i=0; i < (int)RegionSize;i++)
x[i]=(unsigned char)i;
}
DbgPrint("ntStatus=%x\n", ntStatus);
DbgPrint("BaseAddress=%p\n",BaseAddress);
DbgPrint("RegionSize=%x\n",RegionSize);
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)BaseAddress;
}
__finally
{
KeDetachProcess();
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
break;
}
case IOCTL_CE_ALLOCATEMEM_NONPAGED:
{
struct input
{
ULONG Size;
} *inp;
PVOID address;
int size;
inp=Irp->AssociatedIrp.SystemBuffer;
size=inp->Size;
address=ExAllocatePool(NonPagedPool,size);
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)address;
if (address==0)
ntStatus=STATUS_UNSUCCESSFUL;
else
{
DbgPrint("Alloc success. Cleaning memory... (size=%d)\n",size);
DbgPrint("address=%p\n", address);
RtlZeroMemory(address, size);
ntStatus=STATUS_SUCCESS;
}
break;
}
case IOCTL_CE_FREE_NONPAGED:
{
struct input
{
UINT64 Address;
} *inp;
inp = Irp->AssociatedIrp.SystemBuffer;
ExFreePool((PVOID)(UINT_PTR)inp->Address);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_MAP_MEMORY:
{
struct input
{
UINT64 FromPID;
UINT64 ToPID;
UINT64 address;
DWORD size;
} *inp;
struct output
{
UINT64 FromMDL;
UINT64 Address;
} *outp;
KAPC_STATE apc_state;
PEPROCESS selectedprocess;
PMDL FromMDL=NULL;
inp = Irp->AssociatedIrp.SystemBuffer;
outp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_MAP_MEMORY\n");
DbgPrint("address %x size %d\n", inp->address, inp->size);
ntStatus = STATUS_UNSUCCESSFUL;
if (inp->FromPID)
{
//switch
DbgPrint("From PID %d\n", inp->FromPID);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->FromPID), &selectedprocess) == STATUS_SUCCESS)
{
__try
{
RtlZeroMemory(&apc_state, sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess, &apc_state);
__try
{
FromMDL=IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
if (FromMDL)
MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except (1)
{
DbgPrint("Exception\n");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
}
else
{
DbgPrint("From kernel or self\n", inp->FromPID);
__try
{
FromMDL = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
if (FromMDL)
{
DbgPrint("IoAllocateMdl success\n");
MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
}
}
__except (1)
{
DbgPrint("Exception\n");
if (FromMDL)
{
IoFreeMdl(FromMDL);
FromMDL = NULL;
}
}
}
if (FromMDL)
{
DbgPrint("FromMDL is valid\n");
if (inp->ToPID)
{
//switch
DbgPrint("To PID %d\n", inp->ToPID);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ToPID), &selectedprocess) == STATUS_SUCCESS)
{
__try
{
RtlZeroMemory(&apc_state, sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess, &apc_state);
__try
{
outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
outp->FromMDL = (UINT64)FromMDL;
ntStatus = STATUS_SUCCESS;
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except (1)
{
DbgPrint("Exception part 2\n");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
}
else
{
DbgPrint("To kernel or self\n", inp->FromPID);
__try
{
outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
outp->FromMDL = (UINT64)FromMDL;
ntStatus = STATUS_SUCCESS;
}
__except (1)
{
DbgPrint("Exception part 2\n");
}
}
}
else
DbgPrint("FromMDL==NULL\n");
break;
}
case IOCTL_CE_UNMAP_MEMORY:
{
struct output
{
UINT64 FromMDL;
UINT64 Address;
} *inp;
PMDL mdl;
inp = Irp->AssociatedIrp.SystemBuffer;
mdl = (PMDL)(UINT_PTR)inp->FromMDL;
MmUnmapLockedPages((PMDL)(UINT_PTR)inp->Address, mdl);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
ntStatus = STATUS_SUCCESS; //no BSOD means success ;)
break;
}
case IOCTL_CE_LOCK_MEMORY:
{
struct
{
UINT64 ProcessID;
UINT64 address;
UINT64 size;
} *inp;
struct
{
UINT64 mdl;
} *outp;
KAPC_STATE apc_state;
PEPROCESS selectedprocess;
DbgPrint("IOCTL_CE_LOCK_MEMORY");
inp = Irp->AssociatedIrp.SystemBuffer;
outp = Irp->AssociatedIrp.SystemBuffer;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
PMDL mdl = NULL;
KeStackAttachProcess(selectedprocess, &apc_state);
__try
{
mdl = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, (ULONG)inp->size, FALSE, FALSE, NULL);
if (mdl)
{
__try
{
MmProbeAndLockPages(mdl, UserMode, IoReadAccess);
DbgPrint("MmProbeAndLockPages succeeded");
}
__except (1)
{
DbgPrint("MmProbeAndLockPages failed");
IoFreeMdl(mdl);
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
}
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
outp->mdl = (UINT_PTR)mdl;
DbgPrint("Locked the page\n");
ntStatus = STATUS_SUCCESS;
}
break;
}
case IOCTL_CE_UNLOCK_MEMORY:
{
struct
{
UINT64 mdl;
} *inp;
DbgPrint("IOCTL_CE_UNLOCK_MEMORY");
inp = Irp->AssociatedIrp.SystemBuffer;
MmUnlockPages((PMDL)(UINT_PTR)inp->mdl);
IoFreeMdl((PMDL)(UINT_PTR)inp->mdl);
break;
}
case IOCTL_CE_GETPROCADDRESS:
{
struct input
{
UINT64 s;
} *inp;
UNICODE_STRING y;
UINT64 result;
PVOID x;
inp=Irp->AssociatedIrp.SystemBuffer;
RtlInitUnicodeString(&y, (PCWSTR)(UINT_PTR)(inp->s));
x=MmGetSystemRoutineAddress(&y);
result=(UINT64)x;
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&result,8);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETPROCESSNAMEADDRESS:
{
struct input
{
UINT64 PEPROCESS;
} *inp;
struct output
{
UINT64 Address;
} *outp;
UNICODE_STRING temp;
inp=Irp->AssociatedIrp.SystemBuffer;
outp=Irp->AssociatedIrp.SystemBuffer;
RtlInitUnicodeString(&temp, L"PsGetProcessImageFileName");
PsGetProcessImageFileName=(GET_PROCESS_IMAGE_NAME)MmGetSystemRoutineAddress(&temp);
if (PsGetProcessImageFileName!=NULL)
{
outp->Address=(UINT_PTR)PsGetProcessImageFileName((PEPROCESS)((UINT_PTR)(inp->PEPROCESS)));
ntStatus=STATUS_SUCCESS;
}
else
{
DbgPrint("PsGetProcessImageFileName==NULL");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
/*x
case IOCTL_CE_MAKEKERNELCOPY:
{
struct input
{
ULONG Base;
ULONG KernelSize;
} *inp;
DbgPrint("IOCTL_CE_MAKEKERNELCOPY");
inp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=makeKernelCopy(inp->Base, inp->KernelSize);
break;
}
*/
case IOCTL_CE_CONTINUEDEBUGEVENT:
{
struct input
{
BOOL handled;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_CONTINUEDEBUGEVENT\n");
ntStatus=debugger_continueDebugEvent(inp->handled);
break;
}
case IOCTL_CE_WAITFORDEBUGEVENT:
{
struct input
{
ULONG timeout;
} *inp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=debugger_waitForDebugEvent(inp->timeout);
break;
}
case IOCTL_CE_GETDEBUGGERSTATE:
{
DbgPrint("IOCTL_CE_GETDEBUGGERSTATE\n");
__try
{
ntStatus=debugger_getDebuggerState((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer));
}
__except(1)
{
DbgPrint("Exception happened\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
DbgPrint("ntStatus=%x rax=%x\n",ntStatus, ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
break;
}
case IOCTL_CE_SETDEBUGGERSTATE:
{
DbgPrint("IOCTL_CE_SETDEBUGGERSTATE: state->rax=%x\n", ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
__try
{
ntStatus=debugger_setDebuggerState((PDebugStackState)Irp->AssociatedIrp.SystemBuffer);
}
__except(1)
{
DbgPrint("Exception happened\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_SETKERNELSTEPABILITY:
{
struct input
{
int state;
} *inp=Irp->AssociatedIrp.SystemBuffer;
KernelCodeStepping=inp->state;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_WRITESIGNOREWP:
{
KernelWritesIgnoreWP = *(BYTE*)Irp->AssociatedIrp.SystemBuffer;
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_GD_SETBREAKPOINT:
{
struct input
{
BOOL active;
int debugregspot;
UINT64 address;
DWORD breakType;
DWORD breakLength;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("sizeof(struct input)=%d\n",sizeof(struct input));
//DbgPrint("address=%llx breakType=%d breakLength=%d\n",inp->address, inp->breakType,inp->breakLength);
if (inp->active)
{
DbgPrint("activating breapoint %d\n", inp->debugregspot);
ntStatus=debugger_setGDBreakpoint(inp->debugregspot, (UINT_PTR)inp->address, (BreakType)inp->breakType, (BreakLength)inp->breakLength);
}
else
{
DbgPrint("Deactivating breakpoint :%d\n", inp->debugregspot);
ntStatus=debugger_unsetGDBreakpoint(inp->debugregspot);
}
break;
}
case IOCTL_CE_TOUCHDEBUGREGISTER: //used after setting a global debug breakpoint
{
debugger_touchDebugRegister(0);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETSTORELBR:
{
BOOL newstate=*(PBOOL)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("Calling debugger_setStoreLBR(%d)\n", newstate);
debugger_setStoreLBR(newstate);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_EXECUTE_CODE:
{
typedef NTSTATUS (*PARAMETERLESSFUNCTION)(UINT64 parameters);
PARAMETERLESSFUNCTION functiontocall;
struct input
{
UINT64 functionaddress; //function address to call
UINT64 parameters;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_EXECUTE_CODE\n");
functiontocall=(PARAMETERLESSFUNCTION)(UINT_PTR)(inp->functionaddress);
__try
{
ntStatus=functiontocall(inp->parameters);
DbgPrint("Still alive\n");
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
DbgPrint("Exception occured\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_GETVERSION:
{
DbgPrint("IOCTL_CE_GETVERSION. Version=%d\n",dbkversion);
*(PULONG)Irp->AssociatedIrp.SystemBuffer=dbkversion;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_READMSR:
{
DWORD msr=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_READMSR: msr=%x\n", msr);
__try
{
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=__readmsr(msr);
//DbgPrint("Output: %llx\n",*(PUINT64)Irp->AssociatedIrp.SystemBuffer);
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_WRITEMSR:
{
struct input
{
UINT64 msr;
UINT64 value;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_WRITEMSR:\n");
DbgPrint("msr=%llx\n", inp->msr);
DbgPrint("value=%llx\n", inp->value);
__try
{
__writemsr(inp->msr, inp->value );
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
DbgPrint("Error while writing value\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_ULTIMAP2:
{
struct input
{
UINT32 PID;
UINT32 Size;
UINT32 RangeCount;
UINT32 NoPMI;
UINT32 UserMode;
UINT32 KernelMode;
URANGE Ranges[8];
WCHAR OutputPath[200];
} *inp = Irp->AssociatedIrp.SystemBuffer;
int i;
DbgPrint("IOCTL_CE_ULTIMAP2");
for (i = 0; i < (int)(inp->RangeCount); i++)
DbgPrint("%d=%p -> %p", i, (PVOID)(UINT_PTR)inp->Ranges[i].StartAddress, (PVOID)(UINT_PTR)inp->Ranges[i].EndAddress);
SetupUltimap2(inp->PID, inp->Size, inp->OutputPath, inp->RangeCount, inp->Ranges, inp->NoPMI, inp->UserMode, inp->KernelMode);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_WAITFORDATA:
{
ULONG timeout = *(ULONG *)Irp->AssociatedIrp.SystemBuffer;
PULTIMAP2DATAEVENT output = Irp->AssociatedIrp.SystemBuffer;
output->Address = 0;
ntStatus = ultimap2_waitForData(timeout, output);
break;
}
case IOCTL_CE_ULTIMAP2_LOCKFILE:
{
int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
ultimap2_LockFile(cpunr);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_RELEASEFILE:
{
int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
ultimap2_ReleaseFile(cpunr);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_GETTRACESIZE:
{
*(UINT64*)Irp->AssociatedIrp.SystemBuffer = ultimap2_GetTraceFileSize();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_RESETTRACESIZE:
{
ultimap2_ResetTraceFileSize();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_CONTINUE:
{
int cpunr=*(int*)Irp->AssociatedIrp.SystemBuffer;
ntStatus = ultimap2_continue(cpunr);
break;
}
case IOCTL_CE_ULTIMAP2_FLUSH:
{
ntStatus = ultimap2_flushBuffers();
break;
}
case IOCTL_CE_ULTIMAP2_PAUSE:
{
ntStatus = ultimap2_pause();
break;
}
case IOCTL_CE_ULTIMAP2_RESUME:
{
ntStatus = ultimap2_resume();
break;
}
case IOCTL_CE_DISABLEULTIMAP2:
{
DisableUltimap2();
break;
}
case IOCTL_CE_ULTIMAP:
{
#pragma pack(1)
struct input
{
UINT64 targetCR3;
UINT64 dbgctl;
UINT64 dsareasize;
BOOL savetofile;
int HandlerCount;
WCHAR filename[200];
} *inp=Irp->AssociatedIrp.SystemBuffer;
#pragma pack()
DbgPrint("IOCTL_CE_ULTIMAP:\n");
DbgPrint("ultimap(%I64x, %I64x, %d):\n", (UINT64)inp->targetCR3, (UINT64)inp->dbgctl, inp->dsareasize);
if (inp->savetofile)
DbgPrint("filename=%S\n", &inp->filename[0]);
ntStatus=ultimap(inp->targetCR3, inp->dbgctl, (int)inp->dsareasize, inp->savetofile, &inp->filename[0], inp->HandlerCount);
break;
}
case IOCTL_CE_ULTIMAP_DISABLE:
{
ultimap_disable();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_WAITFORDATA:
{
ULONG timeout=*(ULONG *)Irp->AssociatedIrp.SystemBuffer;
PULTIMAPDATAEVENT output=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ultimap_waitForData(timeout, output);
break;
}
case IOCTL_CE_ULTIMAP_CONTINUE:
{
PULTIMAPDATAEVENT input=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ultimap_continue(input);
break;
}
case IOCTL_CE_ULTIMAP_FLUSH:
{
ultimap_flushBuffers();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_PAUSE:
{
ultimap_pause();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_RESUME:
{
ultimap_resume();
ntStatus = STATUS_SUCCESS;
break;
}
/*
case IOCTL_CE_GETCPUIDS:
{
CPULISTFILLSTRUCT x;
forEachCpuPassive(GetCPUIDS_all,&x);
}*/
case IOCTL_CE_STARTACCESMONITOR:
{
//this is used instead of writeProcessMemory for speed reasons (the reading out is still done with readProcessMemory because of easier memory management)
struct input
{
UINT64 ProcessID;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_STARTACCESMONITOR(%d)\n", inp->ProcessID);
ntStatus = STATUS_UNSUCCESSFUL;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = markAllPagesAsNeverAccessed(selectedprocess);
ObDereferenceObject(selectedprocess);
}
break;
}
case IOCTL_CE_ENUMACCESSEDMEMORY:
{
struct input
{
UINT64 ProcessID;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_ENUMACCESSEDMEMORY(%d)\n", inp->ProcessID);
ntStatus = STATUS_UNSUCCESSFUL;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
*(int *)Irp->AssociatedIrp.SystemBuffer = enumAllAccessedPages(selectedprocess);
ObDereferenceObject(selectedprocess);
}
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETACCESSEDMEMORYLIST:
{
int ListSizeInBytes = *(int *)Irp->AssociatedIrp.SystemBuffer;
PPRANGE List = (PPRANGE)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_GETACCESSEDMEMORYLIST\n");
getAccessedPageList(List, ListSizeInBytes);
DbgPrint("return from IOCTL_CE_GETACCESSEDMEMORYLIST\n");
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_INITIALIZE:
{
//find the KeServiceDescriptorTableShadow
struct input
{
UINT64 AddressOfWin32K;
UINT64 SizeOfWin32K;
UINT64 NtUserBuildHwndList_callnumber;
UINT64 NtUserQueryWindow_callnumber;
UINT64 NtUserFindWindowEx_callnumber;
UINT64 NtUserGetForegroundWindow_callnumber;
UINT64 ActiveLinkOffset;
UINT64 ProcessNameOffset;
UINT64 DebugportOffset;
UINT64 ProcessEvent;
UINT64 ThreadEvent;
} *pinp;
DbgPrint("IOCTL_CE_INITIALIZE\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=STATUS_SUCCESS;
//referencing event handles to objects
ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ProcessEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ProcessEvent, NULL);
ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ThreadEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ThreadEvent, NULL);
*(UINT_PTR*)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)0;
break;
}
case IOCTL_CE_VMXCONFIG:
{
#pragma pack(1)
struct input
{
ULONG Virtualization_Enabled;
QWORD Password1;
ULONG Password2;
QWORD Password3;
} *pinp;
#pragma pack()
DbgPrint("IOCTL_CE_VMXCONFIG called\n");
ntStatus=STATUS_SUCCESS;
pinp=Irp->AssociatedIrp.SystemBuffer;
if (pinp->Virtualization_Enabled)
{
vmx_password1=pinp->Password1;
vmx_password2=pinp->Password2;
vmx_password3=pinp->Password3;
DbgPrint("new passwords are: %p-%x-%p\n", (void*)vmx_password1, vmx_password2, (void*)vmx_password3);
__try
{
vmx_version=vmx_getversion();
DbgPrint("Still here, so vmx is loaded. vmx_version=%x\n",vmx_version);
vmxusable = 1;
}
__except(1)
{
DbgPrint("Exception happened. This means no vmx installed, or one of the passwords is wrong\n");
ntStatus = STATUS_UNSUCCESSFUL;
vmxusable = 0;
};
}
else
{
DbgPrint("Virtualization_Enabled=0\n");
vmxusable=0;
}
break;
}
case IOCTL_CE_ENABLE_DRM:
{
#if (NTDDI_VERSION >= NTDDI_VISTA)
struct
{
QWORD PreferedAltitude;
QWORD ProtectedProcess;
} *inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("inp->PreferedAltitude=%p", inp->PreferedAltitude);
DbgPrint("inp->PreferedAltitude=%p", inp->ProtectedProcess);
if (DRMProcess)
{
//check if this process has been terminated
LARGE_INTEGER timeout;
timeout.QuadPart = -500000;
ntStatus=KeWaitForSingleObject(DRMProcess, UserRequest, UserMode, FALSE, &timeout);
if (ntStatus != STATUS_SUCCESS)
break;
}
DRMProcess = PsGetCurrentProcess();
if (inp->ProtectedProcess)
{
if (DRMProcess != (PEPROCESS)((UINT_PTR)inp->ProtectedProcess))
DRMProcess2 = (PEPROCESS)((UINT_PTR)inp->ProtectedProcess);
}
DbgPrint("DRMProcess=%p", DRMProcess);
DbgPrint("DRMProcess2=%p", DRMProcess2);
if (DRMHandle == NULL)
{
WCHAR wcAltitude[10];
UNICODE_STRING usAltitude;
OB_CALLBACK_REGISTRATION r;
LARGE_INTEGER tc;
OB_OPERATION_REGISTRATION obr[2];
int RandomVal = (int)(inp->PreferedAltitude);
int trycount = 0;
if (RandomVal == 0)
{
tc.QuadPart = 0;
KeQueryTickCount(&tc);
RandomVal = 1000 + (tc.QuadPart % 50000);
}
DbgPrint("Activating CE's super advanced DRM"); //yeah right....
DbgPrint("RandomVal=%d", RandomVal);
RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);
DbgPrint("wcAltitude=%S", wcAltitude);
RtlInitUnicodeString(&usAltitude, wcAltitude);
r.Version = OB_FLT_REGISTRATION_VERSION;
r.Altitude = usAltitude;
r.RegistrationContext = NULL;
obr[0].ObjectType = PsProcessType;
obr[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
obr[0].PreOperation = ProcessPreCallback;
obr[0].PostOperation = ProcessPostCallback;
obr[1].ObjectType = PsThreadType;
obr[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
obr[1].PreOperation = ThreadPreCallback;
obr[1].PostOperation = ThreadPostCallback;
r.OperationRegistration = obr;
r.OperationRegistrationCount = 2;
ntStatus = ObRegisterCallbacks(&r, &DRMHandle);
while ((ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) && (trycount<10))
{
RandomVal++;
RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);
RtlInitUnicodeString(&usAltitude, wcAltitude);
r.Altitude = usAltitude;
trycount++;
ntStatus = ObRegisterCallbacks(&r, &DRMHandle);
}
DbgPrint("ntStatus=%X", ntStatus);
}
else
ntStatus = STATUS_SUCCESS;
#else
ntStatus = STATUS_NOT_IMPLEMENTED;
#endif
break;
}
case IOCTL_CE_GET_PEB:
{
KAPC_STATE oldstate;
PEPROCESS ep = *(PEPROCESS *)Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_GET_PEB");
KeStackAttachProcess((PKPROCESS)ep, &oldstate);
__try
{
ULONG r;
PROCESS_BASIC_INFORMATION pbi;
//DbgPrint("Calling ZwQueryInformationProcess");
ntStatus = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &r);
if (ntStatus==STATUS_SUCCESS)
{
//DbgPrint("pbi.UniqueProcessId=%x\n", (int)pbi.UniqueProcessId);
//DbgPrint("pbi.PebBaseAddress=%p\n", (PVOID)pbi.PebBaseAddress);
*(QWORD *)Irp->AssociatedIrp.SystemBuffer = (QWORD)(pbi.PebBaseAddress);
}
else
DbgPrint("ZwQueryInformationProcess failed");
}
__finally
{
KeUnstackDetachProcess(&oldstate);
}
break;
}
case IOCTL_CE_QUERYINFORMATIONPROCESS:
{
struct
{
QWORD processid;
QWORD ProcessInformationAddress;
QWORD ProcessInformationClass;
QWORD ProcessInformationLength;
} *inp = Irp->AssociatedIrp.SystemBuffer;
struct
{
QWORD result;
QWORD returnLength;
char data;
} *outp = Irp->AssociatedIrp.SystemBuffer;
PEPROCESS selectedprocess;
DbgPrint("IOCTL_CE_QUERYINFORMATIONPROCESS");
if (inp->processid == 0)
{
DbgPrint("Still works\n");
ntStatus = STATUS_SUCCESS;
break;
}
__try
{
if (PsLookupProcessByProcessId((HANDLE)(UINT_PTR)inp->processid, &selectedprocess) == STATUS_SUCCESS)
{
KAPC_STATE oldstate;
KeStackAttachProcess((PKPROCESS)selectedprocess, &oldstate);
__try
{
ULONG returnLength;
if (inp->ProcessInformationAddress == 0)
{
DbgPrint("NULL ProcessInformationAddress");
outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, NULL, (ULONG)inp->ProcessInformationLength, &returnLength);
}
else
outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, &(outp->data), (ULONG)inp->ProcessInformationLength, &returnLength);
DbgPrint("outp->result=%x", outp->result);
outp->returnLength = returnLength;
DbgPrint("outp->returnLength=%x", outp->returnLength);
ntStatus = STATUS_SUCCESS;
}
__finally
{
KeUnstackDetachProcess(&oldstate);
}
ObDereferenceObject(selectedprocess);
}
else
{
DbgPrint("Failed to find pid %x", inp->processid);
ntStatus = STATUS_EXPIRED_HANDLE;
}
}
__except (1)
{
DbgPrint("Exception");
ntStatus = STATUS_EXPIRED_HANDLE;
}
break;
}
case IOCTL_CE_NTPROTECTVIRTUALMEMORY:
{
break;
}
case IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM:
{
PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
PMDL mdl;
QWORD pagecount = *(QWORD*)Irp->AssociatedIrp.SystemBuffer;
PFN_NUMBER *pfnlist;
DbgPrint("IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM(%d)\n", pagecount);
if (!vmxusable)
{
DbgPrint("This only works when DBVM is present\n");
ntStatus = STATUS_INVALID_DEVICE_STATE;
break;
}
LowAddress.QuadPart = 0;
HighAddress.QuadPart = 0xffffffffffffffffI64;
SkipBytes.QuadPart = 0;
mdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, (SIZE_T)pagecount * 4096, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED); //do not free this, EVER
if (mdl)
{
int i;
PDBVMOffloadMemInfo mi;
pagecount = MmGetMdlByteCount(mdl) / 4096;
DbgPrint("Allocated %d pages\n", pagecount);
pfnlist = MmGetMdlPfnArray(mdl);
if (pfnlist)
{
//convert the pfnlist to a list dbvm understands, and go in blocks of 32
mi = ExAllocatePool(PagedPool, sizeof(DBVMOffloadMemInfo));
if (mi)
{
mi->List = ExAllocatePool(PagedPool, sizeof(UINT64) * 32);
if (mi->List)
{
mi->Count = 0;
for (i = 0; i < pagecount; i++)
{
mi->List[mi->Count] = pfnlist[i] << 12;
mi->Count++;
if (mi->Count == 32)
{
int j;
int r = vmx_add_memory(mi->List, mi->Count);
DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);
for (j = 0; j < mi->Count; j++)
{
DbgPrint("%d : %p\n", j, (void*)((UINT_PTR)mi->List[j]));
}
mi->Count = 0;
}
}
if (mi->Count)
{
int r = vmx_add_memory(mi->List, mi->Count);
DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);
}
ExFreePool(mi->List);
}
else
DbgPrint("Failure allocating mi->List");
ExFreePool(mi);
}
else
DbgPrint("Failure allocting mi");
}
else
DbgPrint("Failure getting pfn list");
ExFreePool(mdl); //only free the mdl, the rest belongs to dbvm now
ntStatus = STATUS_SUCCESS;
}
else
{
DbgPrint("Failure allocating MDL");
ntStatus = STATUS_MEMORY_NOT_ALLOCATED;
}
break;
}
default:
DbgPrint("Unhandled IO request: %x\n", IoControlCode);
break;
}
Irp->IoStatus.Status = ntStatus;
// Set # of bytes to copy back to user-mode...
if (irpStack) //only NULL when loaded by dbvm
{
if (ntStatus == STATUS_SUCCESS)
Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
else
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return ntStatus;
}