⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbkdrvr.c

📁 冒险岛吸怪源码UCE的制作材料 用于冒险岛游戏的外挂
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
  Build upon the MSJDrvr.C by James M. Finnegan - Microsoft Systems Journal (1998)  
*/

#include "DBKFunc.h"
#include "rootkit.h"
#include "processlist.h"
#include "memscan.h"
#include "threads.h"

#ifdef CETC
	#include "cetc.h"
#endif

#ifdef AMD64
	#define dbkversion 2640007
#else
	#define dbkversion 2000007
#endif

#define IOCTL_UNKNOWN_BASE					FILE_DEVICE_UNKNOWN

#define IOCTL_CE_READMEMORY						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEMEMORY					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENPROCESS    				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_QUERY_VIRTUAL_MEMORY			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_TEST							CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPEPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0805, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_READPHYSICALMEMORY				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEPHYSICALMEMORY			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0807, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPHYSICALADDRESS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0808, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_PROTECTME						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0809, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR3 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETCR3 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETSDT 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_INITIALIZE     		    	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DONTPROTECTME					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETIDT 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_HOOKINTS 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0810, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DEBUGPROCESS 					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0811, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RETRIEVEDEBUGDATA				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0812, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STARTPROCESSWATCH				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0813, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCESSEVENTS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0814, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETTHREADEVENTS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0815, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETVERSION						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0816, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR4 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0817, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENTHREAD	    				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0818, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_MAKEWRITABLE					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0819, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DEBUGPROCESS_CHANGEREG			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STOPDEBUGGING					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define	IOCTL_CE_STOP_DEBUGPROCESS_CHANGEREG	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define	IOCTL_CE_USEALTERNATEMETHOD				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define	IOCTL_CE_ISUSINGALTERNATEMETHOD			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define	IOCTL_CE_ALLOCATEMEM					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_CREATEAPC						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0820, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPETHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0821, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_SUSPENDTHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0822, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMETHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0823, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SUSPENDPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0824, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMEPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0825, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ALLOCATEMEM_NONPAGED			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0826, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCADDRESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0827, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_PROTECT2						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0828, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETDC							CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0829, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)



void MSJUnloadDriver(PDRIVER_OBJECT DriverObject);

NTSTATUS MSJDispatchCreate(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp);

NTSTATUS MSJDispatchClose(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp);

NTSTATUS MSJDispatchIoctl(IN PDEVICE_OBJECT DeviceObject,
                            IN PIRP Irp);



//-----NtUserSetWindowsHookEx----- //prevent global hooks
typedef ULONG (NTUSERSETWINDOWSHOOKEX)(
    IN HANDLE hmod,
    IN PUNICODE_STRING pstrLib OPTIONAL,
    IN DWORD idThread,
    IN int nFilterType,
    IN PVOID pfnFilterProc,
    IN DWORD dwFlags
);
NTUSERSETWINDOWSHOOKEX OldNtUserSetWindowsHookEx;
ULONG NtUserSetWindowsHookEx_callnumber;
//HHOOK NewNtUserSetWindowsHookEx(IN HANDLE hmod,IN PUNICODE_STRING pstrLib OPTIONAL,IN DWORD idThread,IN int nFilterType, IN PROC pfnFilterProc,IN DWORD dwFlags);

//------------------------





typedef NTSTATUS (*ZWSUSPENDPROCESS)
(
    IN ULONG ProcessHandle  // Handle to the process
);
ZWSUSPENDPROCESS ZwSuspendProcess;




PVOID GetApiEntry(ULONG FunctionNumber);
void Unhook(void);

NTSTATUS ZwCreateThread(
	OUT PHANDLE  ThreadHandle,
	IN ACCESS_MASK  DesiredAccess,
	IN POBJECT_ATTRIBUTES  ObjectAttributes,
	IN HANDLE  ProcessHandle,
	OUT PCLIENT_ID  ClientId,
	IN PCONTEXT  ThreadContext,
	IN PVOID  UserStack,
	IN BOOLEAN  CreateSuspended);


PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow=NULL;

UNICODE_STRING  uszDeviceString;
PVOID BufDeviceString=NULL;

#define SYSTEMSERVICE(_function)		KeServiceDescriptorTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]
#define SYSTEMSERVICELINK(_function)	KeServiceDescriptorTable->ServiceTable[*((PUCHAR)(*(PULONG)*((PULONG)((PUCHAR)_function+2)))+1)]




void hideme(PDRIVER_OBJECT DriverObject)
{
	typedef struct _MODULE_ENTRY {
	LIST_ENTRY le_mod;
	DWORD  unknown[4];
	DWORD  base;
	DWORD  driver_start;
	DWORD  unk1;
	UNICODE_STRING driver_Path;
	UNICODE_STRING driver_Name;
} MODULE_ENTRY, *PMODULE_ENTRY;

	PMODULE_ENTRY pm_current;

	pm_current =  *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14)); //eeeeew

	*((PDWORD)pm_current->le_mod.Blink)        = (DWORD) pm_current->le_mod.Flink;
	pm_current->le_mod.Flink->Blink            = pm_current->le_mod.Blink;
	HiddenDriver=TRUE;
}

void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
	ExFreePool(Apc);
	DbgPrint("My second kernelmode apc!!!!\n");
	DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument1);
}

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!!!!\n");
	
	DbgPrint("NormalRoutine=%x\n",*(PULONG)NormalRoutine);
	DbgPrint("NormalContext=%x\n",*(PULONG)NormalContext);
	DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument1);
	DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument2);
	
	
	KeInitializeApc(kApc,
		            (PKTHREAD)PsGetCurrentThread(),
                    0,
                    (PKKERNEL_ROUTINE)mykapc2,
                    NULL,
                    (PKNORMAL_ROUTINE)*(PULONG)SystemArgument1,
                    UserMode,
                    (PVOID)*(PULONG)NormalContext
                    );

	KeInsertQueueApc (kApc, (PVOID)*(PULONG)SystemArgument1, (PVOID)*(PULONG)SystemArgument2, 0);


	//wait in usermode (to 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",kThread);


   
	KeInitializeApc(kApc,
		            kThread,
                    0,
                    (PKKERNEL_ROUTINE)mykapc,
                    NULL,
                    (PKNORMAL_ROUTINE)nothing,
                    KernelMode,
                    0
                    );

	KeInsertQueueApc (kApc, addresstoexecute, addresstoexecute, 0);
}


PVOID GetApiEntry(ULONG FunctionNumber)
{
#ifndef AMD64
	int direction=0; //0=down 1=up
	PUCHAR x;
	//Get the start address of a known function (ZwOpenProcess)
	ULONG LastFunctionNumber=*(PULONG)((PUCHAR)ZwOpenProcess+1);  //0x7a in xp pro sp1
	
	x=(PUCHAR)ZwOpenProcess;

	if (FunctionNumber==LastFunctionNumber) //If you're retarded this is usefull
		return (PVOID)ZwOpenProcess;

	if (FunctionNumber<LastFunctionNumber)
		direction=1;
	else
		direction=0;

    //now search for e8,functionnumber,  (and perhaps also 8d,54,24,04
	if (direction==1)
	{
		return (PVOID)0x12345678;
		//go back in the list
		while (LastFunctionNumber>0)
		{
			if (*x==0xb8)
			{
				//it's a mov eax,........
				//now get the function number if this address

				//make sure it's not function e8
				if (*(PULONG)((ULONG)(x)-1)==0xb8)
					x--;
				
				LastFunctionNumber=*(PULONG)((ULONG)(x)+1);

				if (LastFunctionNumber==FunctionNumber)
					return x; //found it				
			}
			x--;
		}
	}
	else
	{
		x++;		
		while (1)
		{
			//move forward
			if (*x==0xb8)
			{
				if (*(PULONG)((ULONG)(x)+1)==0xb8) //the previous byte was also a 0xb8, so this has to be the identifier
				{
					x++; //next;
					continue;
				}				
				
				LastFunctionNumber=*(PULONG)((ULONG)x+1);

				if (LastFunctionNumber==FunctionNumber)
					return x;
			}
			x++;
		}		
	}

#endif //amd64
	return NULL;
}

int testfunction(int p1,int p2)
{
	DbgPrint("Hello\nParam1=%d\nParam2=%d\n",p1,p2);
	return 0x666;
}


void* functionlist[1];
char  paramsizes[1];
int registered=0;


void AddSystemServices(void)
{
	if (registered)
		return; //no need to register again

	DbgPrint("Registering SystemServiceTable\n");
	
	
	functionlist[0] = (void *)&testfunction;
	paramsizes[0] = 2*4;

	if (KeServiceDescriptorTableShadow)
	{
		//override if any other exists
		KeServiceDescriptorTableShadow[1].ArgumentTable=NULL;
		KeServiceDescriptorTableShadow[1].CounterTable=NULL;
		KeServiceDescriptorTableShadow[1].ServiceTable=NULL;
		KeServiceDescriptorTableShadow[1].TableSize=0;

		KeServiceDescriptorTable[2].ArgumentTable=NULL;
		KeServiceDescriptorTable[2].CounterTable=NULL;
		KeServiceDescriptorTable[2].ServiceTable=NULL;
		KeServiceDescriptorTable[2].TableSize=0;
	}

  
	if (KeAddSystemServiceTable((PULONG_PTR)functionlist, 0, 1, (PUCHAR)paramsizes, 2))
	{
		registered=1;
		DbgPrint("Register successfull\n");
	}
	else
	{
		DbgPrint("Register failed.\n");
	}

	

	DbgPrint("KeServiceDescriptorTable[0]=%p",&KeServiceDescriptorTable[0]);
	DbgPrint("KeServiceDescriptorTable[1]=%p",&KeServiceDescriptorTable[1]);
	DbgPrint("KeServiceDescriptorTable[2]=%p",&KeServiceDescriptorTable[2]);
	DbgPrint("KeServiceDescriptorTable[3]=%p",&KeServiceDescriptorTable[3]);

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                     IN PUNICODE_STRING RegistryPath)
/*++

Routine Description:

    This routine is called when the driver is loaded by NT.

Arguments:

    DriverObject - Pointer to driver object created by system.
    RegistryPath - Pointer to the name of the services node for this driver.

Return Value:

    The function value is the final status from the initialization operation.

--*/
{
    NTSTATUS        ntStatus;
	PVOID			BufDriverString=NULL,BufProcessEventString=NULL,BufThreadEventString=NULL;
    UNICODE_STRING  uszDriverString;
    
    UNICODE_STRING  uszProcessEventString;
	UNICODE_STRING	uszThreadEventString;
    PDEVICE_OBJECT  pDeviceObject;
	int				i;
	ULONG cr4reg;

	HANDLE reg;
	OBJECT_ATTRIBUTES oa;

        
	DbgPrint("Loading driver\n");
	DbgPrint("Registry path = %S\n", RegistryPath->Buffer);

	InitializeObjectAttributes(&oa,RegistryPath,OBJ_KERNEL_HANDLE ,NULL,NULL);
	ntStatus=ZwOpenKey(&reg,KEY_QUERY_VALUE,&oa);
	if (ntStatus == STATUS_SUCCESS)
	{
		UNICODE_STRING A,B,C,D;
		PVOID buf;
		PKEY_VALUE_PARTIAL_INFORMATION bufA,bufB,bufC,bufD;
		ULONG ActualSize;

		DbgPrint("Opened the key\n");

		BufDriverString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100);
		BufDeviceString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100);
		BufProcessEventString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100);
		BufThreadEventString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100);

		bufA=BufDriverString;
		bufB=BufDeviceString;
		bufC=BufProcessEventString;
		bufD=BufThreadEventString;

		RtlInitUnicodeString(&A, L"A");
		RtlInitUnicodeString(&B, L"B");
		RtlInitUnicodeString(&C, L"C");
		RtlInitUnicodeString(&D, L"D");

		if (ntStatus == STATUS_SUCCESS)
			ntStatus=ZwQueryValueKey(reg,&A,KeyValuePartialInformation ,bufA,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize);
		if (ntStatus == STATUS_SUCCESS)
			ntStatus=ZwQueryValueKey(reg,&B,KeyValuePartialInformation ,bufB,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize);
		if (ntStatus == STATUS_SUCCESS)
			ntStatus=ZwQueryValueKey(reg,&C,KeyValuePartialInformation ,bufC,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize);
		if (ntStatus == STATUS_SUCCESS)
			ntStatus=ZwQueryValueKey(reg,&D,KeyValuePartialInformation ,bufD,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize);

		if (ntStatus == STATUS_SUCCESS)
		{
			DbgPrint("Read ok\n");
			RtlInitUnicodeString(&uszDriverString,(PCWSTR) bufA->Data);
			RtlInitUnicodeString(&uszDeviceString,(PCWSTR) bufB->Data);
			RtlInitUnicodeString(&uszProcessEventString,(PCWSTR) bufC->Data);
			RtlInitUnicodeString(&uszThreadEventString,(PCWSTR) bufD->Data);
		}
		else
		{
			ExFreePool(bufA);
			ExFreePool(bufB);
			ExFreePool(bufC);
			ExFreePool(bufD);

			DbgPrint("Failed reading the value\n");
			ZwClose(reg);
			return STATUS_UNSUCCESSFUL;;
		}

	}
	else
	{
		DbgPrint("Failed opening the key\n");
		return STATUS_UNSUCCESSFUL;;
	}

	ntStatus = STATUS_SUCCESS;

    // Point uszDriverString at the driver name
#ifndef CETC
	
	
	// Create and initialize device object
    ntStatus = IoCreateDevice(DriverObject,
                              0,
                              &uszDriverString,
                              FILE_DEVICE_UNKNOWN,
                              0,
                              FALSE,
                              &pDeviceObject);

    if(ntStatus != STATUS_SUCCESS)
	{
		ExFreePool(BufDriverString);
		ExFreePool(BufDeviceString);
		ExFreePool(BufProcessEventString);
		ExFreePool(BufThreadEventString);
		
		ZwClose(reg);
        return ntStatus;
	}

    // Point uszDeviceString at the device name
	
    // Create symbolic link to the user-visible name

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -