腾讯管家攻防驱动分析-Tssyskit

Tssyskit分析

  该驱动为qq管家穿透驱动,提供文件、注册表穿透,和解锁文件、驱动加载、句柄、进程等操作,导出接口给其他驱动使用,设备名\Device\TSSysKit,符号名\DosDevices\TSSysKit。加密手段:Rabbit算法、MD5算法。

一、驱动入口DriverEntry

  • 获取系统版本_1
  • 获取EPROCESS的ObjectTypeIndex (win7以前 0x1C win8 0x1F Win8.1 0x1E)
  • 创建\Device\TSSysKit设备和\DosDevices\TSSysKit符号链接
  • 设置DeviceExtension为通信接口(Interface函数指针)
  • 注册IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJ_DEVICE_CONTROL派遣例程为DefaultDispatch
  • 获取CmpKeyObject、DeviceObject的OBJECT_TYPE_INITIALIZER GetCmpKeyObjectInitializerFunc GetDeviceObjectInitializerFunc
  • 获取ZwQueryVirtualMemory、IoVolumeDeviceToDosName、PsGetProcessSectionBaseAddress地址和NtQueryVirtualMemory的index
  • 检测加载者是否为Ntos (CheckIopLoadDriver)
  • 执行开机删除操作(DoDeleteJob) 删除ShutdownRecord.ini指定的文件

1.1 检测加载者是否为Ntos

int CheckIopLoadDriver()
{
	unsigned int IopLoadDriverNext; // esi@2
	PRTL_PROCESS_MODULES modules; // ebx@5
	int IopLoadDriver; // esi@8
	PVOID Base; // eax@9
	PVOID Callers[4]; // [sp+8h] [bp-18h]@1
	BOOL ret; // [sp+18h] [bp-8h]@1
	ULONG SystemInformationLength; // [sp+1Ch] [bp-4h]@1

	Callers[0] = 0;
	Callers[1] = 0;
	Callers[2] = 0;
	Callers[3] = 0;
	ret = 0;
	SystemInformationLength = 0;
	::IopLoadDriver = 0;
	if ( RtlWalkFrameChain(Callers, 4u, 0) == 4 ) 
		// [0]=RtlWalkFrameChain next
		// [1]=DriverEntry
		// [2]=IopLoadDriver
		// [3]=IopInitializeSystemDrivers
	{
		IopLoadDriverNext = Callers[3];
		if ( MmIsAddressValid(Callers[3]) )
		{
			if ( IopLoadDriverNext >= MmUserProbeAddress && *(IopLoadDriverNext - 5) == 0xE8u )// call ***
			{
				SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION) + 3 * sizeof(RTL_PROCESS_MODULE_INFORMATION);
				modules = ExAllocatePoolWithTag(0, SystemInformationLength, '!KIT');
				if ( modules )
				{
					memset(modules, 0, SystemInformationLength);
					if ( ZwQuerySystemInformation(SystemModuleInformation,modules,SystemInformationLength,&SystemInformationLength) >= 0 )
					{
						if ( modules->NumberOfModules )
						{
							IopLoadDriver = *(IopLoadDriverNext - 4) + IopLoadDriverNext;
							if ( MmIsAddressValid(IopLoadDriver) )
							{
								Base = modules->Modules[0].ImageBase;
								if ( IopLoadDriver >= Base && IopLoadDriver <= (Base + modules->Modules[0].ImageSize) )
								{                               // 检测IopLoadDriver是否在ntos中
									::IopLoadDriver = IopLoadDriver;
									ret = 1;
								}
							}
						}
					}
					ExFreePool(modules);
				}
			}
		}
	}
	return ret;
}

1.2 执行删除任务 DoDeleteJob

  如果腾讯安装目录存在ShutdownRecord.ini文件则删除该文件,解析文件列表中指定的文件并逐个删除,其中解析ini的api、文件操作都是自己实现的。删除方式采用NtSetInformationFile 置FileDispositionInformation。

ShutdownRecord.ini格式:
[DELETEFILECOUNT]
Count=3
[DELETEFILELIST]
0=0.txt
1=1.txt
2=2.txt

enum
{
	WIN2000=1,
	WINXP=2,
	WINXPSP3=3,
	WINVISTA=4,
	WIN7=5,
	WIN8=7,
	WIN8_1=8,
	WIN10=9,
	UNKNOWN=10,
};

二、驱动接口Interface

2.1 DeviceExtension接口

  DeviceObject->DeviceExtension(=Interface) 通过制定序号返回对应函数指针,穿透函数内部在ObOpenObjectByName前后会保存和恢复注册表Objectinitializer:

FARPROC Interface(intindex)
{//注意下面的函数都是自己实现的穿透函数
    switch(index)
    {
    case 1:
        return NtOpenKey;
    case 2:
        return NtQueryValueKey;
    case 3:
        return NtSetValueKeyEx;
    case 4:
        return NtDeleteValueKey;
    case 5:
        return NtDeleteKey;
    case 20:
        return IopCreateFile;
    case 21:
        return NtReadFile;
    case 22:
        return NtWriteFile;
    case 23:
        return NtSetInformationFile;
    case 24:
        return NtQueryInformationFile;
    case 25:
        return NtQueryDirectoryFile;
    }
}

0:NTSTATUS __stdcall NtCreateKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, PULONG Disposition)
1:NTSTATUS __stdcall NtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes)
2:NTSTATUS __stdcall NtQueryValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength)
3:NTSTATUS __stdcall NtSetValueKeyEx(HANDLE Handle, PUNICODE_STRING ValueName, ULONG Type, PVOID Data, ULONG DataSize)
和NtSetValueKey的用法类似,只是没有TitleIndex这个参数
4:NTSTATUS __stdcall NtDeleteValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName)
5:NTSTATUS __stdcall NtDeleteKey(HANDLE KeyHandle)
20:NTSTATUS __stdcall IopCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG Disposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength, CREATE_FILE_TYPE CreateFileType, PVOID ExtraCreateParameters, ULONG Options, ULONG InternalFlags, PVOID DeviceObject)
21:NTSTATUS __stdcall NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
22:NTSTATUS __stdcall NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
23:NTSTATUS __stdcall NtSetInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass, BOOL DelCurrentFile)
24:NTSTATUS __stdcall NtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass, BOOL DelCurrentFile)
25:NTSTATUS __stdcall NtQueryDirectoryFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, PUNICODE_STRING FileName, BOOLEAN RestartScan)

2.2 与WRK代码异同点

  注册表穿透操作是使用Cm函数实现Nt函数,而文件穿透操作则基本和WRK代码一致,Iop*函数最大程度的实现内联。这些实现中和WRK主要区别在于:去掉了AccessMode=UserMode分支、和ObReferenceObjectByName调用前后重置ObjectInitializer。NtReadFile实现额外处理了IoCallDriver返回文件锁定(STATUS_FILE_LOCK_CONFLICT)的处理,此时通过创建文件映射实现读取

2.3 重置/保存注册表对象ObjectInitialzer例程

enum
{
	EClose,
	EDelete,
	EParse,
	ESecurtiy,
	EQueryName,
	EOpen,
};
BOOLEAN ReplaceObjectinitializer(int Type,FARPROC* OutFunc,BOOLEAN ResetOrRestore)
{//重置/保存注册表对象ObjectInitialzer例程,用于ObOpenObjectByName执行前后
	FARPROC* Initailier = NULL;
	if(Type <0 || Type >= ECmMax)
	{
		if(!RegObjectInitialzer[Type] || !CmpKeyObjectType || !OutFunc)
			return 0;
	}
	if(VersionIndex >= WIN2000 && VersionIndex <= WINXPSP3)
	{
		switch(Type)
		{
			case EClose:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.CloseProcedure;
				break;
			case EDelete:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.DeleteProcedure;
				break;
			case EParse:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.ParseProcedure;
				break;
			case ESecurity:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.SecurityProcedure;
				break;
			case EQueryName:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.QueryNameProcedure;
				break;
			case EOpen:
				Initailier = &((POBJECT_TYPE_XP)CmpKeyObjectType)->TypeInfo.OpenProcedure;
				break;
		}
	}
	else if(VersionIndex >= WINVISTA && VersionIndex <= WIN10)
	{
		switch(Type)
		{
		case EClose:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.CloseProcedure;
			break;
		case EDelete:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.DeleteProcedure;
			break;
		case EParse:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.ParseProcedure;
			break;
		case ESecurity:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.SecurityProcedure;
			break;
		case EQueryName:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.QueryNameProcedure;
			break;
		case EOpen:
			Initailier = &((POBJECT_TYPE_WIN7)CmpKeyObjectType)->TypeInfo.OpenProcedure;
			break;
		}
	}
	if(ResetOrRestore)
	{//Get
		if(*Initailier != RegObjectInitialzer[Type])
		{
			*OutFunc = *Initailier;
			*Initailier = RegObjectInitialzer[Type];
			return TRUE;
		}
	}
	else
	{//Set
		if(*OutFunc != *Initailier)
		{
			*Initailier = *OutFunc;
			return TRUE;
		}
	}
	return FALSE;
}

2.4 NtCreateKey

NTSTATUS __stdcall NtCreateKey(PHANDLE KeyHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,ULONG TitleIndex,PUNICODE_STRING Class,ULONG CreateOptions,PULONG Disposition)
{//
	NTSTATUS            status;
	KPROCESSOR_MODE     mode;
	CM_PARSE_CONTEXT    ParseContext;
	PCM_KEY_BODY        KeyBody = NULL;
	HANDLE              Handle = 0;
	UNICODE_STRING      CapturedObjectName = {0};
	FARPROC				SavedInitializer = NULL;
	BOOL				NeedRestore = FALSE;

	RtlZeroMemory(&ParseContext,sizeof(ParseContext));
	if (ARGUMENT_PRESENT(Class)) 
	{
		ParseContext.Class = *Class;
	}
	if ((CreateOptions & (REG_LEGAL_OPTION | REG_OPTION_PREDEF_HANDLE)) != CreateOptions) 
	{
		return STATUS_INVALID_PARAMETER;
	}
	ParseContext.TitleIndex = 1;
	ParseContext.CreateOptions = CreateOptions;
	ParseContext.Disposition = 0L;
	ParseContext.CreateLink = FALSE;
	ParseContext.PredefinedHandle = NULL;
	ParseContext.CreateOperation = TRUE;
	ParseContext.OriginatingPoint = NULL;
	if(ReplaceObjectinitializer(EParse,&SavedInitializer,1))//还原为系统默认值
		NeedRestore = TRUE;
	status = ObOpenObjectByName(ObjectAttributes,CmpKeyObjectType,mode,NULL,DesiredAccess,(PVOID)&ParseContext,&Handle);
	if(NeedRestore)
		ReplaceObjectinitializer(EParse,&SavedInitializer,0);
	if (status==STATUS_PREDEFINED_HANDLE) 
	{
		if(VersionIndex < WINVISTA)
		{
			status = ObReferenceObjectByHandle(Handle,0,CmpKeyObjectType,KernelMode,(PVOID *)(&KeyBody),NULL);
			if (NT_SUCCESS(status)) 
			{
				HANDLE TempHandle;
				TempHandle = (HANDLE)LongToHandle(KeyBody->Type);
				ObDereferenceObject(KeyBody);
				ZwClose(Handle);
				*KeyHandle = TempHandle;
				status = STATUS_SUCCESS;
			}
		}
		else
		{
			TempHandle = (HANDLE)LongToHandle(KeyBody->Type);
			ObDereferenceObject((PVOID)KeyBody);
			NtClose(Handle);
			*KeyHandle = ParseContext.OriginatingPoint;
			status = STATUS_SUCCESS;
		}
	}
	if (ARGUMENT_PRESENT(Disposition)) 
	{
		*Disposition = ParseContext.Disposition;
	}
	return status;
}

2.5 NtOpenKey

NTSTATUS __stdcall NtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes)
{
	CM_PARSE_CONTEXT	ParseContext;
	PVOID				Context;
	HANDLE				Handle =0;
	NTSTATUS			status = STATUS_SUCCESS;
	PCM_KEY_BODY		KeyBody;
	FARPROC				SavedInitializer = NULL;
	BOOL				NeedRestore = FALSE;
	RtlZeroMemory(&ParseContext,sizeof(CM_PARSE_CONTEXT));
	Context = VersionIndex!=WIN2000?&ParseContext:NULL;
	ParseContext.CreateOperation = FALSE;
	if(ReplaceObjectinitializer(EParse,&SavedInitializer,1))//还原为系统默认值
		NeedRestore = TRUE;
	status = ObOpenObjectByName(ObjectAttributes,CmpKeyObjectType,KernelMode,NULL,DesiredAccess,(PVOID)&Context,&Handle);
	if(NeedRestore)
		ReplaceObjectinitializer(EParse,&SavedInitializer,0);
	if (status==STATUS_PREDEFINED_HANDLE) 
	{
		status = ObReferenceObjectByHandle(Handle,0,CmpKeyObjectType,KernelMode,(PVOID *)(&KeyBody),NULL);
		if (NT_SUCCESS(status)) 
		{
			*KeyHandle = (HANDLE)LongToHandle(KeyBody->Type);
			ObDereferenceObject((PVOID)KeyBody);
			if(*KeyHandle) 
			{
				status = STATUS_SUCCESS;
			} 
			else 
			{
				status = STATUS_OBJECT_NAME_NOT_FOUND;
			}
		}
		ZwClose(Handle);
	} 
	else if (NT_SUCCESS(status)) 
	{
		*KeyHandle = Handle;
	}
	return status;
}

2.6 NtQueryValueKey

NTSTATUS __stdcall NtQueryValueKey(HANDLE KeyHandle,PUNICODE_STRING ValueName,KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
    PVOID KeyValueInformation,ULONG Length,PULONG ResultLength)
{
    NTSTATUS    status;
    PCM_KEY_BODY   KeyBody = NULL;
    KPROCESSOR_MODE mode;
	UNICODE_STRING LocalValueName = {0};
    if(!ValueName || (KeyValueInformationClass != KeyValueBasicInformation && KeyValueInformationClass != KeyValueFullInformation
		&& KeyValueInformationClass != KeyValuePartialInformation && KeyValueInformationClass != KeyValueFullInformationAlign64 &&
		KeyValueInformationClass != KeyValuePartialInformationAlign64))
		return STATUS_INVALID_PARAMETER;
	if(CmMatchData[VersionIndex][ECmQueryValueKey].InitFlag && CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr)
	{
		mode = KeGetPreviousMode();
		status = ObReferenceObjectByHandle(KeyHandle,KEY_QUERY_VALUE,CmpKeyObjectType,mode,(PVOID *)(&KeyBody),NULL);
		LocalValueName = *ValueName;
		if (NT_SUCCESS(status)) 
		{
			switch(VersionIndex)
			{
			case WIN2000:
			case WINXP:
			case WINXPSP3:
				CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr(KeyBody->KeyControlBlock,LocalValueName,
					KeyValueInformationClass,KeyValueInformation,Length,ResultLength);
				break;
			case WINVISTA:
			case WIN7:
			case WIN7_1:
				CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr(KeyBody,KeyValueInformationClass,KeyValueInformation
					Length,ResultLength,LocalValueName);
				break;
			case WIN8:
				CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr(KeyBody,LocalValueName,KeyValueInformationClass,
					KeyValueInformation,Length,ResultLength);
				break;
			case WIN8_1:
			case WIN10:
				CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr(KeyBody,KeyValueInformationClass,KeyValueInformation,
					Length,ResultLength,LocalValueName);
				break;
			default:
				status = STATUS_NOT_SUPPORTED;
				break;
			}
		}
	}
	else
	{
		status = STATUS_NOT_SUPPORTED;
	}
	if(KeyBody)
		ObDereferenceObject(KeyBody);
	return status;
}

2.7 NtSetValueKeyEx

NTSTATUS __stdcall NtSetValueKeyEx(HANDLE KeyHandle,PUNICODE_STRING ValueName,ULONG Type,PVOID Data,ULONG DataSize)
{
	NTSTATUS    status;
	PCM_KEY_BODY   KeyBody = NULL;
	KPROCESSOR_MODE mode;
	UNICODE_STRING LocalValueName = {0};
	PWSTR CapturedName=NULL;
	OBJECT_HANDLE_INFORMATION HandleInformation = {0};
	if(CmMatchData[VersionIndex][ECmQueryValueKey].InitFlag && CmMatchData[VersionIndex][ECmQueryValueKey].FuncAddr)
	{
		mode = KeGetPreviousMode();
		status = ObReferenceObjectByHandle(KeyHandle,KEY_SET_VALUE,CmpKeyObjectType,mode,(PVOID *)(&KeyBody),&HandleInformation);
		LocalValueName = *ValueName;
		if (NT_SUCCESS(status)) 
		{
			switch(VersionIndex)
			{
				switch(VersionIndex)
				{
				case WIN2000:
				case WINXP:
				case WINXPSP3:
					CmMatchData[VersionIndex][ECmSetValueKey].FuncAddr(KeyBody->KeyControlBlock,&LocalValueName,Type,Data,DataSize);
					break;
				case WINVISTA:
				case WIN7:
				case WIN7_1:
				case WIN8:
				case WIN8_1:
					CmMatchData[VersionIndex][ECmSetValueKey].FuncAddr(KeyBody,&LocalValueName,Type,Data,DataSize,0,
						HandleInformation.HandleAttributes & 4);
					break;
				case WIN10:
					CmMatchData[VersionIndex][ECmSetValueKey].FuncAddr(KeyBody,&LocalValueName,Type,Data,DataSize,0,
						HandleInformation.HandleAttributes & 4);
					break;
				default:
					status = STATUS_NOT_SUPPORTED;
					break;
			}
		}
	}
	else
	{
		status = STATUS_NOT_SUPPORTED;
	}
	if(KeyBody)
		ObDereferenceObject(KeyBody);
	return status;
}

2.8 NtDeleteValueKey

NTSTATUS __stdcall NtDeleteValueKey(HANDLE KeyHandle,PUNICODE_STRING ValueName)
{
	NTSTATUS    status;
	PCM_KEY_BODY   KeyBody = NULL;
	KPROCESSOR_MODE mode;
	UNICODE_STRING LocalValueName = {0};
	PWSTR CapturedName=NULL;
	OBJECT_HANDLE_INFORMATION HandleInformation = {0};
	if(CmMatchData[VersionIndex][ECmDeleteValueKey].InitFlag && CmMatchData[VersionIndex][ECmDeleteValueKey].FuncAddr)
	{
		mode = KeGetPreviousMode();
		status = ObReferenceObjectByHandle(KeyHandle,KEY_SET_VALUE,CmpKeyObjectType,mode,(PVOID *)(&KeyBody),&HandleInformation);
		LocalValueName = *ValueName;
		if (NT_SUCCESS(status)) 
		{
			switch(VersionIndex)
			{
				case WIN2000:
				case WINXP:
				case WINXPSP3:
					CmMatchData[VersionIndex][ECmDeleteValueKey].FuncAddr(KeyBody->KeyControlBlock,LocalValueName);
					break;
				case WINVISTA:
				case WIN7:
				case WIN7_1:
					CmMatchData[VersionIndex][ECmDeleteValueKey].FuncAddr(KeyBody,KeyHandle,HandleInformation.HandleAttributes & 4,LocalValueName);
					break;
				case WIN8:
					CmMatchData[VersionIndex][ECmDeleteValueKey].FuncAddr(KeyBody,LocalValueName,KeyHandle,HandleInformation.HandleAttributes & 4);
					break;
				case WIN8_1:
				case WIN10:
					CmMatchData[VersionIndex][ECmDeleteValueKey].FuncAddr(KeyBody,&LocalValueName,Type,Data,DataSize,0,
						HandleInformation.HandleAttributes & 4);
					break;
				default:
					status = STATUS_NOT_SUPPORTED;
					break;
			}
		}
	}
	else
	{
		status = STATUS_NOT_SUPPORTED;
	}
	if(KeyBody)
		ObDereferenceObject(KeyBody);
	return status;
}

2.9 NtDeleteKey

NTSTATUS __stdcall NtDeleteKey(HANDLE KeyHandle)
{
	NTSTATUS    status;
	PCM_KEY_BODY   KeyBody = NULL;
	KPROCESSOR_MODE mode;
	UNICODE_STRING LocalValueName = {0};
	PWSTR CapturedName=NULL;
	OBJECT_HANDLE_INFORMATION HandleInformation = {0};
	if(CmMatchData[VersionIndex][ECmDeleteKey].InitFlag && CmMatchData[VersionIndex][ECmDeleteKey].FuncAddr)
	{
		mode = KeGetPreviousMode();
		status = ObReferenceObjectByHandle(KeyHandle,KEY_SET_VALUE,CmpKeyObjectType,mode,(PVOID *)(&KeyBody),&HandleInformation);
		LocalValueName = *ValueName;
		if (NT_SUCCESS(status)) 
		{
			switch(VersionIndex)
			{
			case WIN2000:
			case WINXP:
			case WINXPSP3:
			case WINVISTA:
			case WIN7:
			case WIN7_1:
			case WIN8:
			case WIN8_1:
			case WIN10:
				CmMatchData[VersionIndex][ECmDeleteKey].FuncAddr(KeyBody);
				break;
			default:
				status = STATUS_NOT_SUPPORTED;
				break;
			}
		}
	}
	else
	{
		status = STATUS_NOT_SUPPORTED;
	}
	if(KeyBody)
		ObDereferenceObject(KeyBody);
	return status;
}

2.10 IopCreateFile

  代码基本和WRK一致,区别在于2点:

  • OPEN_PACKET结构不同
  • ObOpenObjectByName调用之前会将IoFileObjectType的ObjectInitailier重置为系统初始值
// WIN2000
// WINXP
// WINXPSP3
#pragma pack(push)
#pragma pack(8)
typedef struct _OPEN_PACKET_XP
{
	CSHORT Type;
	CSHORT Size;
	PFILE_OBJECT FileObject;
	NTSTATUS FinalStatus;
	ULONG_PTR Information;
	ULONG ParseCheck;
	PFILE_OBJECT RelatedFileObject;
	LARGE_INTEGER AllocationSize;
	ULONG CreateOptions;
	USHORT FileAttributes;
	USHORT ShareAccess;
	PVOID EaBuffer;
	ULONG EaLength;
	ULONG Options;
	ULONG Disposition;
	PFILE_BASIC_INFORMATION BasicInformation;
	PFILE_NETWORK_OPEN_INFORMATION NetworkInformation;
	CREATE_FILE_TYPE CreateFileType;
	PVOID ExtraCreateParameters;
	BOOLEAN Override;
	BOOLEAN QueryOnly;
	BOOLEAN DeleteOnly;
	BOOLEAN FullAttributes;
	PDUMMY_FILE_OBJECT LocalFileObject;
	BOOLEAN TraversedMountPoint;
	ULONG           InternalFlags;
	PDEVICE_OBJECT  TopDeviceObjectHint;
} OPEN_PACKET_XP, *POPEN_PACKET_XP;
#pragma pack(pop)

// WINVISTA
// WIN7
// WIN7_1
#pragma pack(push)
#pragma pack(8)
typedef struct _OPEN_PACKET_WIN7
{
	CSHORT Type;
	CSHORT Size;
	PFILE_OBJECT FileObject;
	NTSTATUS FinalStatus;
	ULONG_PTR Information;
	ULONG ParseCheck;
	PFILE_OBJECT RelatedFileObject;
	POBJECT_ATTRIBUTES OriginalAttributes;
	LARGE_INTEGER AllocationSize;
	ULONG CreateOptions;
	USHORT FileAttributes;
	USHORT ShareAccess;
	PVOID EaBuffer;
	ULONG EaLength;
	ULONG Options;
	ULONG Disposition;
	PFILE_BASIC_INFORMATION BasicInformation;
	PFILE_NETWORK_OPEN_INFORMATION NetworkInformation;
	CREATE_FILE_TYPE CreateFileType;
	PVOID MailslotOrPipeParameters;
	BOOLEAN Override;
	BOOLEAN QueryOnly;
	BOOLEAN DeleteOnly;
	BOOLEAN FullAttributes;
	PDUMMY_FILE_OBJECT LocalFileObject;
	ULONG           InternalFlags;
	IO_DRIVER_CREATE_CONTEXT  DriverCreateContext;
} OPEN_PACKET_WIN7, *POPEN_PACKET_WIN7;
#pragma pack(pop)
// WIN8
// WIN8_1
// WIN10
#pragma pack(push)
#pragma pack(8)
typedef struct _OPEN_PACKET_WIN8
{
	CSHORT Type;
	CSHORT Size;
	PFILE_OBJECT FileObject;
	NTSTATUS FinalStatus;
	ULONG_PTR Information;
	ULONG ParseCheck;
	union
	{
		PFILE_OBJECT RelatedFileObject;
		PDEVICE_OBJECT ReferencedDeviceObject;
	};
	POBJECT_ATTRIBUTES OriginalAttributes;
	LARGE_INTEGER AllocationSize;
	ULONG CreateOptions;
	USHORT FileAttributes;
	USHORT ShareAccess;
	PVOID EaBuffer;
	ULONG EaLength;
	ULONG Options;
	ULONG Disposition;
	PFILE_BASIC_INFORMATION BasicInformation;
	PFILE_NETWORK_OPEN_INFORMATION NetworkInformation;
	CREATE_FILE_TYPE CreateFileType;
	PVOID MailslotOrPipeParameters;
	BOOLEAN Override;
	BOOLEAN QueryOnly;
	BOOLEAN DeleteOnly;
	BOOLEAN FullAttributes;
	PDUMMY_FILE_OBJECT LocalFileObject;
	ULONG           InternalFlags;
	KPROCESSOR_MODE AccessMode;
	IO_DRIVER_CREATE_CONTEXT  DriverCreateContext;
} OPEN_PACKET_WIN8, *POPEN_PACKET_WIN8;
#pragma pack(pop)

三、控制码

  IRP_MJ_DEVICE_CONTROL => 调用DeviceIoControl派遣(DeviceIoControlDispatch),能力:

  • 解锁文件
  • 驱动加载
  • 句柄操作
  • 进程打开、结束
  • 注册表穿透操作

3.1 TSSysKit x86 IoControlCode对应表

0x221C00
    解锁文件
    buffer=     sizeof=0x804
    +00 NTSTATUS status     out
    +04 WCHAR FileName[1024]    in
0x221C04
0x221C08
0x221C0C
0x221C10
0x221C14
    尚未实现
0x222004
    普通结束进程
    buffer=     sizeof=4
    +00 DWORD ProcessId
0x222008
    穿透NtDeleteKey
    buffer=     sizeof=8
    +00 NTSTATUS status     out
    +04 HANDLE  KeyHandle   in
0x22200C
    穿透NtDeleteValueKey        成员含义见NtDeleteValueKey
    buffer=     sizeof=0xC
    +00 NTSTATUS status     out
    +04 HANDLE  KeyHandle   in
    +08 PUNICODE_STRING ValueName   in
0x222010
    通过进程id或进程对象名(只能选一)穿透打开进程NtOpenProcess   成员含义见NtOpenProcess
    buffer=     sizeof=0x18
    +00 NTSTATUS status     out
    +04 HANDLE ProcessHandle    out
    +08 ACCESS_MASK DesiredAccess in
    +0C POBJECT_ATTRIBUTES ObjectAttributes in
    +10 PCLIENT_ID ClientId
0x222404
    普通关闭句柄NtClose
    buffer=     sizeof=8
    +00 NTSTATUS status     out
    +04 HANDLE Handle   in
0x222408
    穿透创建注册表项NtCreateKey         成员含义见NtCreateKey
    buffer=     sizeof=0x20
    +00 HANDLE  KeyHandle   out
    +04 NTSTATUS status     out     注意status不是第一成员了!!
    +08 ULONG Disposition   out
    +0C ACCESS_MASK DesiredAccess   in
    +10 POBJECT_ATTRIBUTES ObjectAttributes in
    +14 ULONG TitleIndex    in
    +18 PUNICODE_STRING Class   in
    +1C ULONG CreateOptions in
0x22240C
    穿透打开注册表项NtOpenKey           成员含义见NtOpenKey
    buffer=     sizeof=0x10
    +00 HANDLE  KeyHandle   out
    +04 NTSTATUS status     out     注意status不是第一成员了!!
    +08 ACCESS_MASK DesiredAccess   in
    +0C POBJECT_ATTRIBUTES ObjectAttributes in
0x222410
    同0x222008  NtDeleteKey
	buffer=		sizeof=8
	+00	NTSTATUS status
	+04	HANDLE KeyHandle
0x222414
    穿透删除注册表项NtDeleteValueKey	成员含义见NtDeleteValueKey
	buffer=		sizeof=0xC
	+00	NTSTATUS status     out 
	+04	HANDLE  KeyHandle   in
	+08	PUNICODE_STRING ValueName	in
0x222418
    穿透设置注册表项NtSetValueKeyEx     成员含义见NtSetValueKey
    buffer=     sizeof=0x1C
    +00 NTSTATUS status     out 
    +04 HANDLE  KeyHandle   in
    +08 PUNICODE_STRING ValueName	in
    +0C ULONG TitleIndex	未使用
    +10 ULONG   Type	in
    +14 PVOID   Data	in
    +18 ULONG   DataSize	in
0x22241C
    穿透设置注册表项NtQueryValueKey     成员含义见NtQueryValueKey
    buffer=     sizeof=0x1C
    +00 DWORD ResultLength  out
    +04 NTSTATUS status     out     注意status不是第一成员了!!
    +08 HANDLE  KeyHandle   in
    +0C PUNICODE_STRING ValueName
    +10 ULONG Type          out     KeyValueInformation->DataLength
    +14 PVOID Data          out     KeyValueInformation->Data
    +18 ULONG DataLength    out     KeyValueInformation->DataLength
0x222420
    穿透枚举注册表项NtEnumerateKey      成员含义见NtEnumerateKey
    buffer=     sizeof=0x1C
    +00 NTSTATUS status     out
    +04 DWORD ResultLength  out
    +08 HANDLE KeyHandle        in
    +0C ULONG Index             in
    +10 KEY_INFORMATION_CLASS KeyInformationClass   in
    +14 PVOID KeyInformation    in
    +18 ULONG Length
0x222424
    NtEnumerateValueKey     成员含义见NtEnumerateValueKey
    buffer=		sizeof=0x1C
    +00 NTSTATUS status     out
    +04 ULONG ResultLength  out
    +08 HANDLE KeyHandle    in
    +0C ULONG Index     in
    +10 KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass    in
    +14 PVOID KeyValueInformation   out
    +18 ULONG Length    in
0x222428
    TsSysKit驱动是否初始化
    *(DWORD*)buffer => SomeFlag
    *(DWORD*)buffer <= IsTsSysKitInit 
0x22242C
    穿透创建服务加载驱动
    buffer=     sizeof=0x91C
    +000    WCHAR ImagePath[260] 驱动文件路径
    +208    DWORD Type  驱动注册表Type项
    +20C    DWORD Start 驱动注册表项Start类型
    +210    DWORD flag  (决定是否设置注册表Tag和Group信息)
    +214    ???
    +468    DWORD Tag 驱动注册表Tag项
    +46C    WCHAR DisplayName[300] 驱动注册表项DisplayName
    +6C4    WCHAR ServiceName[300] 驱动服务名
0x222430
    获取操作系统版本
    buffer=RTL_OSVERSIONINFOEXW     sizeof=0x11C
0x222800
0x222804
    2个初始化TSSysKit的通道
0x224008
	+00	DWORD Tag=0x20120502
	+04	DWORD =0
0x22400C
	穿透创建文件
	Buffer=	sizeof=0x30	具体参数含义见NtCreateFile
	+00	NTSTATUS status     out
	+04	PHANDLE FileHandle 
	+08	ACCESS_MASK DesiredAccess 
	+0C	POBJECT_ATTRIBUTES ObjectAttributes 
	+10	PIO_STATUS_BLOCK IoStatusBloc
	+14	PLARGE_INTEGER AllocationSize 
	+18	ULONG FileAttributes
	+1C	ULONG ShareAccess
	+20	ULONG CreateDisposition
	+24	ULONG CreateOptions
	+28	PVOID EaBuffer 
	+2C	ULONG EaLength 
0x224010
	穿透打开文件
	Buffer=	sizeof=0x1C 	具体参数含义见NtOpenFile
	+00	NTSTATUS status     out
	+04	PHANDLE FileHandle
	+08	PHANDLE FileHandle
	+0C	POBJECT_ATTRIBUTES ObjectAttributes
	+10	PIO_STATUS_BLOCK IoStatusBlock
	+14	ULONG ShareAccess
	+18	ULONG OpenOptions
0x224014
	穿透读取文件
	Buffer=	sizeof=0x28		具体参数含义见NtReadFile
	+00	NTSTATUS status     out
	+04	HANDLE FileHandle	in
	+08	HANDLE Event		in
	+0C	PIO_APC_ROUTINE ApcRoutine	in
	+10	PVOID ApcContext			in
	+14	PIO_STATUS_BLOCK IoStatusBlock	in
	+18	PVOID Buffer		out
	+1C	ULONG Length		in
	+20	PLARGE_INTEGER ByteOffset	
	+24	PULONG Key
0x224018
	穿透写入文件
	Buffer=	sizeof=0x28		具体参数含义见NtWriteFile
	+00	NTSTATUS status     out
	+04	HANDLE FileHandle	in
	+08	HANDLE Event		in
	+0C	PIO_APC_ROUTINE ApcRoutine	in
	+10	PVOID ApcContext			in
	+14	PIO_STATUS_BLOCK IoStatusBlock	in
	+18	PVOID Buffer		out
	+1C	ULONG Length		in
	+20	PLARGE_INTEGER ByteOffset	
	+24	PULONG Key
0x22401C
    普通关闭句柄NtClose
    buffer=     sizeof=8
    +00 NTSTATUS status     out
    +04 HANDLE Handle   in
0x224020
	穿透设置文件
	Buffer=	sizeof=0x1C       具体参数含义见NtSetInformationFile
	+00	NTSTATUS status;
	+04	HANDLE FileHandle			in
	+08	PIO_STATUS_BLOCK IoStatus		out	
	+0C	PVOID FileInformation		in
	+10	ULONG Length			in
	+14	FILE_INFORMATION_CLASS FileInformationClass	in
	+18	BOOL DelCurrentFile		in
0x224024
	穿透查询文件
	Buffer=	sizeof=0x1C       具体参数含义见NtQueryInformationFile
	+00	NTSTATUS status				out
	+04	HANDLE FileHandle			in
	+08	PIO_STATUS_BLOCK IoStatus		out	
	+0C	PVOID FileInformation		in
	+10	ULONG Length			in
	+14	FILE_INFORMATION_CLASS FileInformationClass	in
	+18	BOOL DelCurrentFile		in
0x224028
	尚未实现
0x22402C
	穿透查询目录
	Buffer=	sizeof=0x30	具体参数含义见NtQueryDirectoryFile
	+00	NTSTATUS status		out
	+04	HANDLE FileHandle	in
	+08	HANDLE Event		in
	+0C 	PIO_APC_ROUTINE ApcRoutine	未使用
	+10	PVOID ApcContext	未使用
	+14 	PIO_STATUS_BLOCK IoStatus		out
	+18	PVOID FileInformation	in
	+1C	ULONG Length		in
	+20	FILE_INFORMATION_CLASS FileInformationClass	in
	+24	BOOLEAN ReturnSingleEntry		in
	+28	PUNICODE_STRING FileName	in
	+2C	BOOLEAN RestartScan	in
0x228404
	穿透查询文件属性
	Buffer=	sizeof=0xC		具体参数含义见NtQueryAttributesFile
	+0	NTSTATUS status		out
	+4	POBJECT_ATTRIBUTES ObjectAttributes		in			路径前缀匹配\??\c:
	+8	FILE_NETWORK_OPEN_INFORMATION networkInformation	out
0x221C00解锁文件
见3.13 解锁文件

0x222004普通结束进程
BOOLEAN TerminateProcessById(HANDLE ProcessId)
{
	BOOLEAN Result = FALSE;
	PEPROCESS Process = NULL;
	HANDLE ProcessHandle = NULL;
	if(NT_SUCCESS(PsLookupProcessByProcessId(ProcessId,&Process)) &&
		NT_SUCCESS(ObOpenObjectByPointer(Process,0,NULL,PROCESS_ALL_ACCESS,NULL,KernelMode,&ProcessHandle)) &&
		NT_SUCCESS(ZwTerminateProcess(ProcessHandle,0)))
	{
		Result = TRUE;
	}
	if(Process)
	{
		ObDereferenceObject(Process);
		Process = NULL;
	}
	if(ProcessHandle)
		ZwClose(ProcessHandle);
	return Result;
}

0x22242C穿透创建服务加载驱动

struct LOADDRIVERSTRUCT
{
	WCHAR ImagePath[260]; //驱动文件路径
	DWORD Type;  //驱动注册表Type项
	DWORD Start; //驱动注册表项Start类型
	WCHAR Group[300];//驱动注册表Group名
	DWORD Tag; //驱动注册表Tag项
	WCHAR DisplayName[300]; //驱动注册表项DisplayName
	WCHAR ServiceName[300]; //驱动服务名
};

#define MakeUnicodeString(X) {sizeof(X),sizeof(X)+2,X}
UNICODE_STRING UImagePath=MakeUnicodeString(L"ImagePath");
UNICODE_STRING UType=MakeUnicodeString(L"Type");
UNICODE_STRING UStart=MakeUnicodeString(L"Start");
UNICODE_STRING UGroup=MakeUnicodeString(L"Group");
UNICODE_STRING UDisplayName=MakeUnicodeString(L"DisplayName");
UNICODE_STRING UErrorControl=MakeUnicodeString(L"ErrorControl");
UNICODE_STRING UTag=MakeUnicodeString(L"Tag");
UNICODE_STRING UZwLoadDriver=MakeUnicodeString(L"ZwLoadDriver");

struct LOADDRIVERPARAM
{
	WORK_QUEUE_ITEM WorkItem;
	KEVENT Event;
	ULONG mem1;
	PUNICODE_STRING DriverServiceName;
	NTSTATUS Status;
};

void LoadDriverWorker(LOADDRIVERPARAM* WorkItem)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL,outstatus;
	HANDLE KeyHandle = NULL;
	OBJECT_ATTRIBUTES Oa;
	if(WorkItem)
	{
		InitializeObjectAttributes(&Oa,WorkItem->DriverServiceName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL);
		status = NtOpenKey(&KeyHandle,KEY_READ,&Oa);//穿透
		if(NT_SUCCESS(status))
		{//xp win7的IopLoadDriver 为不同的调用方式
			if(VersionInfo < WINVISTA)
			{//NTSTATUS __stdcall IopLoadDriver(HANDLE KeyHandle, BOOLEAN CheckForSafeBoot, BOOLEAN IsFilter, NTSTATUS *DriverEntryStatus)
				IopLoadDriver(KeyHandle,HANDLE_FLAG_INHERIT,FALSE,&outstatus);
				if(status == STATUS_FAILED_DRIVER_ENTRY)
					status = outstatus;
				else if(status == STATUS_DRIVER_FAILED_PRIOR_UNLOAD)
					status = STATUS_OBJECT_NAME_NOT_FOUND;
			}
			else
			{//NTSTATUS __userpurge IopLoadDriver<eax>(HANDLE KeyHandle<ecx>, BOOLEAN CheckForSafeBoot, BOOLEAN IsFilter, NTSTATUS *DriverEntryStatus)  第一参用ecx传值

				status = IopLoadDriver(KeyHandle,HANDLE_FLAG_INHERIT,FALSE,&outstatus);////事先获取的函数指针,见1.1
			}
		}
	}
	WorkItem->Status = status;
	KeSetEvent(WorkItem->Event,0,FALSE);
}

NTSTATUS LoadDriverEx(PUNICODE_STRING DriverServiceName)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	LOADDRIVERPARAM LoadDriver;
	if(IopLoadDriver)//事先获取的函数指针,见1.1
	{
		LoadDriver.DriverServiceName = DriverServiceName;
		LoadDriver.mem1 = 0;
		KeInitializeEvent(&LoadDriver.Event,NotificationEvent,FALSE);
		ExInitializeWorkItem(&LoadDriver,LoadDriverWorker,&LoadDriver);
		ExQueueWorkItem(&LoadDriver.WorkItem,DelayedWorkQueue);
		KeWaitForSingleObject(&LoadDriver.Event,UserRequest,KernelMode,FALSE,NULL);
		return LoadDriver.Status;
	}
	else
	{
		FARPROC ZwLoadDriver = MmGetSystemRoutineAddress(&UZwLoadDriver);
		if(ZwLoadDriver)
			return ZwLoadDriver(DriverServiceName);
	}
	return status;
}

NTSTATUS CreateServiceAndLoadDriver(DWORD InLen,LOADDRIVERSTRUCT* Data)
{//InLen = IrpSp->Parameters.DeviceIoControl.InputBufferLength
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	UNICODE_STRING DriverServicePath;
	UNICODE_STRING ServiceName;
	OBJECT_ATTRIBUTES Oa;
	WCHAR* Buf = NULL;
	HANDLE KeyHandle = NULL;
	const int BufLen = 520;
	ULONG ErrorControl = SERVICE_ERROR_NORMAL;
	ULONG Disposition = REG_OPENED_EXISTING_KEY;
	if(!SeSinglePrivilegeCheck(SE_LOAD_DRIVER_PRIVILEGE,UserMode))
		return STATUS_PRIVILEGE_NOT_HELD;
	if(VersionInfo < WINXP)
		return STATUS_NOT_SUPPORTED;
	if((Data->Type & SERVICE_DRIVER) && Data->ServiceName && Data->ImagePath && Data->DisplayName)
	{
		RtlInitUnicodeString(&ServiceName,Data->ServiceName);
		Buf = (WCHAR*)ExAllocatePool(NonPagedPool,BufLen);
		RtlZeroMemory(Buf,BufLen);
		wcscpy(Buf,L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
		DriverServicePath.Length = 2*wcslen(Buf);
		DriverServicePath.MaximumLength = BufLen;
		DriverServicePath.Buffer = Buf;
		status = RtlAppendUnicodeStringToString(&DriverServicePath, &ServiceName);
		if(NT_SUCCESS(status))
		{
			InitializeObjectAttributes(&Oa,&DriverServicePath,OBJ_CASE_INSENSITIVE,NULL,NULL);
			status = ZwCreateKey(&KeyHandle,KEY_READ|KEY_SET_VALUE, &Oa, 0,NULL, 0, &Disposition);//穿透
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UImagePath,REG_SZ,Data->ImagePath,2*wcslen(Data->ImagePath)+2);//穿透
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UType,REG_DWORD,Data->Type,sizeof(DWORD));
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UStart,REG_DWORD,Data->Start,sizeof(DWORD));
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UDisplayName,REG_SZ,Data->DisplayName,2*wcslen(Data->DisplayName)+2);
		}
		if(NT_SUCCESS(status))
		{//此处q管源码有bug
			status = ZwSetValueKeyEx(KeyHandle,&UGroup,REG_SZ,Data->Group,2*wcslen(Data->Group)+2);
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UTag,REG_DWORD,Data->Tag,sizeof(DWORD));
		}
		if(NT_SUCCESS(status))
		{
			status = ZwSetValueKeyEx(KeyHandle,&UErrorControl,REG_DWORD,ErrorControl,sizeof(DWORD));
		}
		if(NT_SUCCESS(status))
		{
			ZwFlushKey(KeyHandle);
			status = LoadDriverEx(&DriverServicePath);
		}
	}
	if(KeyHandle)
	{
		ZwClose(KeyHandle);
		KeyHandle = NULL;
	}
	if(Buf)
		ExFreePool(Buf);
}

3.2 TSSysKit x64 IoControlCode对应表

0x22200C
	穿透创建文件
	Buffer=	sizeof=0x50	具体参数含义见NtCreateFile
	+00	NTSTATUS status     out
	+08	PHANDLE FileHandle 
	+10	ACCESS_MASK DesiredAccess 
	+18	POBJECT_ATTRIBUTES ObjectAttributes 
	+20	PIO_STATUS_BLOCK IoStatusBloc
	+28	PLARGE_INTEGER AllocationSize 
	+30	ULONG FileAttributes
	+34	ULONG ShareAccess
	+38	ULONG CreateDisposition
	+3C	ULONG CreateOptions
	+40	PVOID EaBuffer 
	+48	ULONG EaLength 
0x222010
	穿透打开文件
	Buffer=	sizeof=0x30 	具体参数含义见NtOpenFile
	+00	NTSTATUS status     out
	+08	PHANDLE FileHandle
	+10	PHANDLE FileHandle
	+18	POBJECT_ATTRIBUTES ObjectAttributes
	+20	PIO_STATUS_BLOCK IoStatusBlock
	+28	ULONG ShareAccess
	+2C	ULONG OpenOptions
0x222014
	穿透读取文件
	Buffer=	sizeof=0x50		具体参数含义见NtReadFile
	+00	NTSTATUS status     out
	+08	HANDLE FileHandle	in
	+10	HANDLE Event		in
	+18	PIO_APC_ROUTINE ApcRoutine	in
	+20	PVOID ApcContext			in
	+28	PIO_STATUS_BLOCK IoStatusBlock	in
	+30	PVOID Buffer		out
	+38	ULONG Length		in
	+40	PLARGE_INTEGER ByteOffset	
	+48	PULONG Key
0x222018
	穿透写入文件
	Buffer=	sizeof=0x50		具体参数含义见NtWriteFile
	+00	NTSTATUS status     out
	+08	HANDLE FileHandle	in
	+10	HANDLE Event		in
	+18	PIO_APC_ROUTINE ApcRoutine	in
	+20	PVOID ApcContext			in
	+28	PIO_STATUS_BLOCK IoStatusBlock	in
	+30	PVOID Buffer		out
	+38	ULONG Length		in
	+40	PLARGE_INTEGER ByteOffset	
	+48	PULONG Key
0x22201C
    普通关闭句柄NtClose
    buffer=     sizeof=0x10
    +00 NTSTATUS status     out
    +04 HANDLE Handle   in
0x222020
	穿透设置文件
	Buffer=	sizeof=0x30       具体参数含义见NtSetInformationFile
	+00	NTSTATUS status;
	+08	HANDLE FileHandle			in
	+10	PIO_STATUS_BLOCK IoStatus		out	
	+18	PVOID FileInformation		in
	+20	ULONG Length			in
	+24	FILE_INFORMATION_CLASS FileInformationClass	in
	+28	BOOL DelCurrentFile		in
0x222024
	穿透查询文件
	Buffer=	sizeof=0x30       具体参数含义见NtQueryInformationFile
	+00	NTSTATUS status				out
	+08	HANDLE FileHandle			in
	+10	PIO_STATUS_BLOCK IoStatus		out	
	+18	PVOID FileInformation		in
	+20	ULONG Length			in
	+24	FILE_INFORMATION_CLASS FileInformationClass	in
	+28	BOOL DelCurrentFile		in
0x222028
	尚未实现
0x22202C	
	穿透查询目录
	Buffer=	sizeof=0x58	具体参数含义见NtQueryDirectoryFile
	+00	NTSTATUS status		out
	+08	HANDLE FileHandle	in
	+10	HANDLE Event		in
	+18 	PIO_APC_ROUTINE ApcRoutine	未使用
	+20	PVOID ApcContext	未使用
	+28 	PIO_STATUS_BLOCK IoStatus		out
	+30	PVOID FileInformation	in
	+38	ULONG Length		in
	+3C	FILE_INFORMATION_CLASS FileInformationClass	in
	+40	BOOLEAN ReturnSingleEntry		in
	+48	PUNICODE_STRING FileName	in
	+50	BOOLEAN RestartScan	in
0x222030
	获取内部版本号
	buffer=		sizeof=8
	+0	<=	0x20110929i64
0x222034	
	穿透查询文件属性
	Buffer=	sizeof=0x18		具体参数含义见NtQueryAttributesFile
	+00	NTSTATUS status		out
	+08	POBJECT_ATTRIBUTES ObjectAttributes		in			路径前缀匹配\??\c:
	+10	FILE_NETWORK_OPEN_INFORMATION networkInformation	out
0x222038	
    解锁文件
    buffer=     sizeof=0x804
    +00 NTSTATUS status     out
    +04 WCHAR FileName[1024]    in
0x222144
	普通关闭句柄NtClose
    buffer=     sizeof=0x10
    +00 NTSTATUS	status out
    +08 HANDLE		Handle in
0x222148
    穿透创建注册表项NtCreateKey         成员含义见NtCreateKey
    buffer=     sizeof=0x20
    +00 HANDLE  KeyHandle   out
    +04 NTSTATUS status     out     注意status不是第一成员了!!
    +08 ULONG Disposition   out
    +0C ACCESS_MASK DesiredAccess   in
    +10 POBJECT_ATTRIBUTES ObjectAttributes in
    +14 ULONG TitleIndex    in
    +18 PUNICODE_STRING Class   in
    +1C ULONG CreateOptions in
0x22214C
    穿透打开注册表项NtOpenKey           成员含义见NtOpenKey
    buffer=     sizeof=0x20
    +00 HANDLE  KeyHandle   out
    +08 NTSTATUS status     out     注意status不是第一成员了!!
    +10 ACCESS_MASK DesiredAccess   in
    +18 POBJECT_ATTRIBUTES ObjectAttributes in
0x222150
	穿透删除注册表项NtDeleteKey			成员含义见NtDeleteKey
	buffer=		sizeof=0x10
	+00	NTSTATUS status
	+08	HANDLE KeyHandle
0x222154
    穿透删除注册表项NtDeleteValueKey	成员含义见NtDeleteValueKey
	buffer=		sizeof=0x18
	+00	NTSTATUS status     out 
	+08	HANDLE  KeyHandle   in
	+10	PUNICODE_STRING ValueName	in
0x222158
	穿透设置注册表项NtSetValueKeyEx     成员含义见NtSetValueKey
    buffer=     sizeof=0x30
    +00 NTSTATUS status     out 
    +08 HANDLE  KeyHandle   in
    +10 PUNICODE_STRING ValueName	in
    +18 ULONG TitleIndex	未使用
    +1C ULONG   Type	in
    +20 PVOID   Data	in
    +28 ULONG   DataSize	in
0x22215C
    穿透设置注册表项NtQueryValueKey     成员含义见NtQueryValueKey
    buffer=     sizeof=0x30
    +00 DWORD ResultLength  out
    +04 NTSTATUS status     out     注意status不是第一成员了!!
    +08 HANDLE  KeyHandle   in
    +10 PUNICODE_STRING ValueName
    +18 ULONG Type          out     KeyValueInformation->DataLength
    +20 PVOID Data          out     KeyValueInformation->Data
    +28 ULONG DataLength    out     KeyValueInformation->DataLength
0x222160
	穿透枚举注册表项NtEnumerateKey      成员含义见NtEnumerateKey
	buffer=		sizeof=0x28
    +00 NTSTATUS status     out
    +04 ULONG ResultLength  out
    +08 HANDLE KeyHandle    in
    +10 ULONG Index     in
    +14 KEY_INFORMATION_CLASS KeyValueInformationClass    in
    +18 PVOID KeyInformation   out
    +20 ULONG Length    in
0x222164
    穿透枚举注册表项NtEnumerateValueKey     成员含义见NtEnumerateValueKey
    buffer=		sizeof=0x28
    +00 NTSTATUS status     out
    +04 ULONG ResultLength  out
    +08 HANDLE KeyHandle    in
    +10 ULONG Index     in
    +14 KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass    in
    +18 PVOID KeyValueInformation   out
    +20 ULONG Length    in
0x222284
    通过进程id或进程对象名(只能选一)穿透打开进程NtOpenProcess   成员含义见NtOpenProcess
    buffer=     sizeof=0x30
    +00 NTSTATUS status     out
    +08 HANDLE ProcessHandle    out
    +10 ACCESS_MASK DesiredAccess in
    +18 POBJECT_ATTRIBUTES ObjectAttributes in
    +20 PCLIENT_ID ClientId
0x222288
	buffer=     sizeof=4
    +00 DWORD ProcessId
0x222430
    获取操作系统版本
    buffer=RTL_OSVERSIONINFOEXW     sizeof=0x11C
0x222800
0x222804
    2个初始化TSSysKit的通道
0x222808
	获取CPUID信息
	buffer=		sizeof=0x38
	+00	ULONG Fn0000_0000_EBX	EBX EDX ECX 组成"GenuineIntel"或"AuthenticAMD"
	+04	ULONG Fn0000_0000_EDX
	+08 ULONG Fn0000_0000_ECX
	+10	ULONG CpuType   0:未知    1:INTEL    2:AMD
	+14	BOOLEAN VMBit	是否支持vm   Intel Virutalization Technology / AMD Secure Virtual Machine
	+18	ULONGLONG MSR3A  Intel  IA32_FEATURE_CONTROL   MSR(0x3A)  / AMD Read NX support 
	+20	ULONGLONG  NXsupport        Intel CR4  / AMD Msr(0xC0000080)
	+28 ULONGLONG VMXONBit  Intel MSR(0x3A) activate VMXON outside of SMX mode  /  AMD Msr(0xC0010114)
	+30	ULONG NRIP    Fn8000_000A_EDX&4

四、默认派遣例程

  • 检查当前所属进程是否有腾讯标记 (CheckDriverLoaderValid)
  • 重置驱动注册表项信息 (ResetRegServiceInfo)
  • 随机化EPROCESS的ImageFileName(RandomImageNameToHide)

4.1 根据进程id结束进程

void TerminateProcessById(HANDLE ProcessId)
{
	PEPROCESS Process = NULL;
	HANDLE ProcessHandle = NULL;
	NTSTATUS status = PsLookupProcessByProcessId(ProcessId,&Process);
	if(NT_SUCCESS(status))
	{
		status = ObOpenObjectByPointer(Process,0,NULL,PROCESS_ALL_ACCESS,0,NULL,&ProcessHandle);
		if(NT_SUCCESS(status))
		{
			status = ZwTerminateProcess(ProcessHandle,0);
		}
	}
	if(Process)
	{
		ObDereferenceObject(Process);
		Process = NULL;
	}
	if(ProcessHandle)
		ZwClose(ProcessHandle);


检测PE格式合法性

bool CheckNtImageValid(LPVOID ImageAddress)
{
	if(ImageAddress && MmIsAddressValid(ImageAddress))
	{
		PIMAGE_DOS_HEADER DosHeader = (IMAGE_DOS_HEADER)ImageAddress;
		if(MmIsAddressValid(&DosHeader->e_lfanew) && DosHeader->e_magic == 'ZM')
		{
			PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
			if(NtHeader && MmIsAddressValid(NtHeader) && NtHeader->Signature == 'EP')
				return true;
		}
	}
}

4.2 获取当前进程进程名

typedef ULONG DWORD;
typedef struct _MEMORY_BASIC_INFORMATION 
{
	PVOID BaseAddress;
	PVOID AllocationBase;
	DWORD AllocationProtect;
	SIZE_T RegionSize;
	DWORD State;
	DWORD Protect;
	DWORD Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
typedef struct _MEMORY_SECTION_NAME
{
	UNICODE_STRING SectionFileName;
	WCHAR NameBuffer[0];
} MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME;

extern "C" PVOID __stdcall PsGetProcessSectionBaseAddress(PEPROCESS Process);
extern "C" NTSTATUS __stdcall ZwQueryVirtualMemory(HANDLE ProcessHandle,PVOID BaseAddress,MEMORY_INFORMATION_CLASS MemoryInformationClass,
	PVOID MemoryInformation,SIZE_T MemoryInformationLength,PSIZE_T ReturnLength);
#define MEM_IMAGE 0x1000000 

bool GetCurrentProcessName(PVOID Buffer,SIZE_T Length)
 {
	 NTSTATUS status;
	if(!Buffer || !Length)
		return;
	UNICODE_STRING UIoVolumeDeviceToDosName;
	PVOID ImageBase = PsGetProcessSectionBaseAddress(IoGetCurrentProcess());
	PVOID SectionName = ExAllocatePool(NonPagedPool,Length + sizeof(MEMORY_SECTION_NAME));
	if(!SectionName)
		return;
	if(ImageBase)
	{
		MEMORY_BASIC_INFORMATION BasicInfo;
		status = ZwQueryVirtualMemory(NtCurrentProcess(),ImageBase,MemoryBasicInformation,&BasicInfo,sizeof(BasicInfo),NULL);
		if(NT_SUCCESS(status) && BasicInfo.Type == MEM_IMAGE)
		{
			status = ZwQueryVirtualMemory(NtCurrentProcess(),ImageBase,MemorySectionName,SectionName,Length + sizeof(MEMORY_SECTION_NAME),NULL);
			if(NT_SUCCESS(status))
			{
				wcsncpy((WCHAR*)Buffer,((PMEMORY_SECTION_NAME)SectionName)->SectionFileName.Buffer,Length);
				return true;
			}
		}
	}
	return false;
 }

4.3 由进程ID获取进程设备名

bool GetProcessNameById(HANDLE ProcessId,PVOID Buffer,SIZE_T Length)
{
	NTSTATUS status;
	if(ProcessId == (HANDLE)4)
	{
		wcsncpy((WCHAR*)Buffer,L"System",Length);
	}
	else if(ProcessId == PsGetCurrentProcessId())
	{
		GetCurrentProcessName(Buffer,Length);
	}
	else
	{
		PEPROCESS Process = NULL;
		if(NT_SUCCESS(PsLookupProcessByProcessId(ProcessId,&Process)))
		{
			KAPC_STATE KApc;
			KeStackAttachProcess(Process,&KApc);
			GetCurrentProcessName(Buffer,Length);
			KeUnstackDetachProcess(&KApc);
			ObDereferenceObject(&Process);
		}
		
	}
	return true;
}

4.4 设备名转DOS路径

NTSTATUS GetDeviceDosName(WCHAR* DeviceName,WCHAR* DosName,DWORD Len)
{
	NTSTATUS status;
	//检查设备路径
	if(!DeviceName || !DosName)
		return STATUS_INVALID_PARAMETER;
	if(wcsnicmp(DeviceName, L"\\Device\\", 8u))
		return STATUS_INVALID_PARAMETER_1;
	WCHAR* ptr = wcsstr(DeviceName + 8,L"\\");
	if(!ptr)
		return STATUS_UNSUCCESSFUL;
	int len = ptr - DeviceName;
	PVOID Buffer = ExAllocatePool(NonPagedPool,2*len+2);
	if(!Buffer)
		return;
	wcsncpy((WCHAR*)Buffer,DeviceName,len);
	//根据设备名获取设备对象
	PDEVICE_OBJECT DeviceObject;
	UNICODE_STRING UDeviceName;
	PFILE_OBJECT FileObject;
	RtlInitUnicodeString(&UDeviceName,(WCHAR*)Buffer);
	//GetDeviceObjectByName
	status = IoGetDeviceObjectPointer(&UDeviceName,0,&FileObject,&DeviceObject);
	if(NT_SUCCESS(status))
	{
		if(DeviceObject->Type == FILE_DEVICE_DISK)
		{
			UNICODE_STRING RootDeviceDosName;
			status = IoVolumeDeviceToDosName(DeviceObject,&RootDeviceDosName);
			if(NT_SUCCESS(status))
			{
				wcsncpy(DosName,RootDeviceDosName.Buffer,RootDeviceDosName.Length);
				ExFreePool(RootDeviceDosName.Buffer);
				int len2 = wcslen((WCHAR*)Buffer);//拼接全路径
				wcsncat(DosName,DeviceName+len2,Len);
			}
		}
		else if(DeviceObject->Type == FILE_DEVICE_NETWORK_FILE_SYSTEM)
		{
			wcsncpy(DosName,L"\\",Len);
			int len2 = wcslen((WCHAR*)Buffer);
			wcsncat(DosName,DeviceName+len2,Len);
		}
		else
		{
			status = STATUS_DEVICE_DATA_ERROR;
		}
		ObReferenceObject(FileObject);
		ObReferenceObject(DeviceObject);
	}
	ExFreePool(Buffer);
}

4.5 得到EPROCESS对应ImageDosPath

void GetProcessDosPathByObject(PEPROCESS Process,LPVOID Buffer,ULONG Len)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	HANDLE ProcessHandle = NULL;
	HANDLE FileHandle = NULL;
	const int FileBufSize = 4096;
	PUNICODE_STRING pFilePath = ExAllocatePoolWithTag(NonPagedPool,FileBufSize);
	if(!pFilePath)
		return;
	status = ObOpenObjectByPointer(Process,OBJ_KERNEL_HANDLE,NULL,0,NULL,KernelMode,&ProcessHandle);
	if(NT_SUCCESS(status))
	{
		status = NtQueryInformationProcess(ProcessHandle,ProcessImageFileName,pFilePath,FileBufSize,NULL);
		if(NT_SUCCESS(status) && MmIsAddressValid(pFilePath->Buffer))
		{
			OBJECT_ATTRIBUTES oa;
			IO_STATUS_BLOCK IoStatusBlock;
			InitializeObjectAttributes(&oa,pFilePath,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
			status = IoCreateFile(&FileHandle,GENERIC_READ | SYNCHRONIZE,&oa,&IoStatusBlock,NULL,FILE_ATTRIBUTE_NORMAL,
				FILE_SHARE_READ,FILE_OPEN,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,NULL,0,CreateFileTypeNone,
				NULL,IO_NO_PARAMETER_CHECKING);
			if(NT_SUCCESS(status))
			{// GetProcessDosPathByHandle
				OBJECT_HANDLE_INFORMATION HandleInformation;
				PFILE_OBJECT FileObject = NULL;
				UNICODE_STRING DriveDosName = {0};
				status = ObReferenceObjectByHandle(FileHandle,0,NULL,KernelMode,(PVOID*)&FileObject,&HandleInformation);
				if(NT_SUCCESS(status) && FileObject != NULL && MmIsAddressValid(FileObject) && MmIsAddressValid(FileObject->FileName.Buffer))
				{
					if(IoGetRelatedDeviceObject(FileObject))
					{
						status = RtlVolumeDeviceToDosName(FileObject->DeviceObject,&DriveDosName);//获取盘符
						if(NT_SUCCESS(status) && DriveDosName.Buffer && DriveDosName.Length + FileObject->FileName.Length < Len)
						{
							memcpy(Buffer,DriveDosName.Buffer,DriveDosName.Length);
							memcpy((char*)Buffer+DriveDosName.Length,FileObject->FileName.Buffer,FileObject->FileName.Length);
						}
					}
					ObDereferenceObject(FileObject);
					if(DriveDosName.Buffer)
						ExFreePool(DriveDosName.Buffer);
				}
			}
		}
	}

	if(FileHandle)
		NtClose(FileHandle);
	if(ProcessHandle)
		NtClose(ProcessHandle);
	ExFreePool(pFilePath);
}

4.6 随机化程序名机制

Void RandomImageNameToHide()
{
ANSI_STRING QQEXEA,IMAGENAMEA;
	char* ImageName;
	RtlInitAnsiString(&QQEXEA,"QQPCRTP.EXE");
	ImageName = PsGetProcessImageFileName(IoGetCurrentProcess());
	RtlInitAnsiString(&IMAGENAMEA,ImageName);
	if(!RtlCompareString(&IMAGENAMEA,&QQEXEA,TRUE))
	{
		LARGE_INTEGER Time,LocalTime;
		TIME_FIELDS TimeFields;
		KeQuerySystemTime(&Time);
		ExSystemTimeToLocalTime(&Time,&LocalTime);
		RtlTimeToTimeFields(&LocalTime,&TimeFields);
		ImageName[TimeFields.Second % 5] = (TimeFields.Second % 26) + 'A';
	}
}

4.7 根据进程文件名获取进程信息

Bool GetProcessInfoByFileName(char* FileName, PVOID Buffer,int Size)
{
	ULONG InfoLen;
	PVOID Modules;
	NTSTATUS status;
	BOOL Find = FALSE;
	ZwQuerySystemInformation(SystemModuleInformation,&InfoLen,0,&InfoLen);
	modules = ExAllocatePool(PagedPool,InfoLen);
	If(!modules)
		Return FALSE;
	status = ZwQuerySystemInformation(SystemModuleInformation, modules,InfoLen);
	If(NT_SUCCESS(status))
	{
		For(int i=0;i<modules-> NumberOfModules;i++)
		{
			Int offset = modules->Modules[i].OffsetToFileName;
			If(!stricmp(modules->Modules[i].FullPathName[offset],FileName)
			{
				Memcpy(Buffer, &modules->Modules[i],Size);
				Find = TRUE;
				Break;
			}
		}
}
ExFreePool(modules);
Return FALSE;
}

4.8 两种方式调用内核函数

法一:以ZwQueryVirtualMemory为例
UNICODE_STRING FuncName;
FARPROC fZwQueryVirtualMemory;
RtiInitUnicodeString(&FuncName, L”ZwQueryVirtualMemory”);
fZwQueryVirtualMemory = MmGetSystemRoutineAddress(&FuncName);

法二:
RTL_PROCESS_MODULE_INFORMATION ImageInfo;
RtlZeroMemory(&ImageInfo,sizeof(ImageInfo));
If(GetProcessInfoByFileName(“ntdll.dll”,&ImageInfo,sizeof(ImageInfo)))
NtQueryVirtualMemorySSDTIndex = GetSSDTApiIndex(ImageInfo.ImageBase,"NtQueryVirtualMemory");

用法:
ZwQueryVirtualMemoryEx(...)
{
	_asm
	{
		Push ebp
		Mov ebp,esp
		Mov eax, fZwQueryVirtualMemory
		Test eax,eax
		Jz $+3
		Pop ebp
		Jmp eax
		Cmp NtQueryVirtualMemorySSDTIndex,-1
		Jz $+6
		Pop ebp
		Jmp TAG
		Mov eax,C0000001h
		Pop ebp
		Retn 18h
TAG:
		Mov eax, NtQueryVirtualMemorySSDTIndex
		Lea edx,dword ptr [esp+4]
		Int 2Eh
		Retn 18h
	}
}

判断一段地址有效性
BOOLEAN  CheckAddressValid(PVOID VirtualAddress, int Length)
{
	int result;
	if ( VirtualAddress )
		result = MmIsAddressValid(VirtualAddress) && MmIsAddressValid(VirtualAddress + Length);
	else
		result = 0;
	return result;
}

4.9 获取对象类型

POBJECT_TYPE GetTypeFromObject(PVOID Object)
{//从对象获取对象类型
	UNICODE_STRING UObGetObjectType;
	POBJECT_TYPE ObjectType;
	RtlInitUnicodeString(&UObGetObjectType,L"ObGetObjectType");
	PVOID ObGetObjectType = MmGetSystemRoutineAddress(&UObGetObjectType);
	if(ObGetObjectType)
	{
		ObjectType = ((POBJECT_TYPE (__stdcall*)(PVOID ))ObGetObjectType)(Object);
	}
	else//Vista以前
	{
		ObjectType = ((OBJECT_HEADER*)OBJECT_TO_OBJECT_HEADER(Object))->Type;
	}
}

4.10 基础库功能——检测腾讯程序合法性

  对当加载驱动的进程进行md5校验,如果校验失败则拒绝加载,从\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\TSKSP\InstallDir获取q管安装目录

void CheckTsFileValid(PEPROCESS Process)
{
	NTSTATUS status;
	const int BufSize = 522;
	WCHAR CurProcFileDosName[260];
	WCHAR* FileDosName = (WCHAR*)ExAllocatePool(NonPagedPool,BufSize);
	WCHAR* FileFullName = (WCHAR*)ExAllocatePool(NonPagedPool,520);
	if(FileDosName && FileFullName)
	{
		memset(FileDosName,0,BufSize);
		if(GetProcessDosPathByObject(Process,FileDosName,520))
		{
			status = GetProcessNameById(PsGetCurrentProcessId(),CurProcFileDosName,520);
			if(NT_SUCCESS(status) && !wcsicmp(CurProcFileDosName,FileDosName))
			{
				UNICODE_STRING UFileFullName;
				OBJECT_ATTRIBUTES oa;
				HANDLE FileHandle;
				IO_STATUS_BLOCK IoStatusBlock;
				RtlZeroMemory(FileFullName,520);
				wnsprintfW(FileFullName,259,L"\\??\\%ws",FileDosName);
				InitializeObjectAttributes(&oa,FileFullName,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
				status = IoCreateFile(&FileHandle,GENERIC_READ | SYNCHRONIZE,&oa,&IoStatusBlock,NULL,FILE_ATTRIBUTE_NORMAL,
					FILE_SHARE_READ,FILE_OPEN,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,NULL,0,CreateFileTypeNone,
					NULL,IO_NO_PARAMETER_CHECKING);
				if(NT_SUCCESS(status))
				{
					FILE_STANDARD_INFORMATION FileInformation;
					status = ZwQueryInformationFile(FileHandle,&IoStatusBlock,&FileInformation,sizeof(FileInformation),FileStandardInformation);
					if(NT_SUCCESS(status) && FileInformation.EndOfFile.LowPart < 0xA00000)
					{
						PVOID Buffer = ExAllocatePool(NonPagedPool,FileInformation.EndOfFile.LowPart);
						if(Buffer)
						{
							status = ZwReadFile(FileHandle,NULL,NULL,NULL,&IoStatusBlock,Buffer,FileInformation.EndOfFile.LowPart,NULL,NULL);
							if(NT_SUCCESS(status) && CheckNtImageValid(Buffer))
							{
								ULONG SecretDataOffset = *(ULONG*)((PIMAGE_DOS_HEADER)Buffer)->e_res2;
								/************************************************************************/
								/* 下面将Buffer+SecretDataOffset处的128字节数据进行md5校验,原始数据如下*/
								// b8 92 77 ac 41 ee 20 b1-0d 0c ce d7 a2 95 b3 96
								// 46 3f 16 ba 72 4d b9 df-2c 2f a5 f9 d2 63 3c 35
								// 06 45 a2 dc bf 5c a7 6f-89 d5 45 e2 2b db 30 75
								// d3 76 93 84 9b fc e4 62-ed 21 d5 6a db 90 84 df
								// fc 1f ba 07 8d fd 7f 6d-f8 67 41 34 cc f3 e2 4a
								// 04 73 8b 8a f6 7c 2c d5-10 21 cf 25 80 18 fc be
								// 9f 5f c8 ea 47 c8 95 5a-79 07 be 54 9c 0d 12 36
								// 0c f6 9a e6 71 0d c1 27-29 c2 9d e8 7e f0 b7 05
								/************************************************************************/
								//.........................省略md5计算过程
							}
							ExFreePool(Buffer);
						}
					}
					ZwClose(FileHandle);
				}
			}
		}
	}
	if(FileDosName)
		ExFreePool(FileDosName);
	if(FileFullName)
		ExFreePool(FileFullName);
}

4.11 解锁文件

  • 设置文件属性为FILE_ATTRIBUTE_NORMAL
  • 执行IopCloseFile IRP_MJ_LOCK_CONTROL IRP_MN_UNLOCK_ALL
  • 从句柄表中找到所有文件对象,如果路径匹配则关闭句柄CmCloseHandle
typedef NTSTATUS EndSetFileAttributes ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
	Irp->UserIosb->Status = Irp->IoStatus.Status;
	Irp->UserIosb->Information = Irp->IoStatus.Information;
	KeSetEvent(Irp->UserEvent, 0, FALSE);
	IoFreeIrp(Irp);
	return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS ResetFileAttributes(HANDLE FileHandle)
{//设置文件属性为NORMAL
	NTSTATUS status;
	PDEVICE_OBJECT pDevObj = NULL;
	PIRP pIrp = NULL;
	KEVENT Event;
	IO_STATUS_BLOCK ios = {0};
	FILE_BASIC_INFORMATION BasicInfo;
	PIO_STACK_LOCATION IrpSp;
	status = ObReferenceObjectByHandle(FileHandle,0,*IoFileObjectType,KernelMode,&FileObject,NULL);
	if(NT_SUCCESS(status))
	{
		pDevObj = IoGetRelatedDeviceObject(FileObject);//穿透
		pIrp = IoAllocateIrp(pDevObj->StackSize,TRUE);
		if(pIrp)
		{
			KeInitializeEvent(&Event,SynchronizationEvent,FALSE);
			RtlZeroMemory(&BasicInfo,sizeof(BasicInfo));
			BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
			pIrp->AssociatedIrp.SystemBuffer = (PVOID)&BasicInfo;
			pIrp->UserEvent = &Event;
			pIrp->UserIosb = &ios;
			pIrp->Tail.Overlay.OriginalFileObject = FileObject;
			pIrp->Tail.Overlay.Thread = KeGetCurrentThread();
			pIrp->RequestorMode = 0;
			IrpSp = IoGetNextIrpStackLocation( pIrp );
			IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
			IrpSp->DeviceObject = pDevObj;
			IrpSp->FileObject = FileObject;
			IrpSp->Parameters.SetFile.Length = sizeof(BasicInfo);
			IrpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
			IrpSp->Parameters.SetFile.FileObject = FileObject;
			IrpSp->CompletionRoutine = EndSetFileAttributes;
			IrpSp->Context = NULL;
			IrpSp->Control = SL_INVOKE_ON_CANCEL|SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
			IoCallDriver(pDevObj,Irp);
			KeWaitForSingleObject(&Event,0,KernelMode,FALSE,NULL);
			ObDereferenceObject(FileObject);
		}
		else
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
		}
	}
	if ( FileObject )
		ObDereferenceObject(FileObject);
	return status;
}

void UnlockFileThread(PVOID StartContext)
{//关闭系统对象句柄
	CmpSetHandleProtection(&Ohfi,FALSE);
	if(StartContext)
		NtClose(StartContext);
	PsTerminateSystemThread(0);
}

void TryUnlockFile(PFILE_OBJECT FileObject)
{//解锁文件
	SYSTEM_HANDLE_INFORMATION HandleInformation1;
	ULONG RetLen = 0;
	PVOID Buffer;
	ZwQuerySystemInformation(SystemHandleInformation,&HandleInformation1,sizeof(HandleInformation1),&RetLen);
	if(RetLen)
	{
		POBJECT_NAME_INFORMATION ObjectNameInfo1 = (POBJECT_NAME_INFORMATION)ExAllocatePool(NonPagedPool,2056);
		POBJECT_NAME_INFORMATION ObjectNameInfo2 = (POBJECT_NAME_INFORMATION)ExAllocatePool(NonPagedPool,2056);
		ObjectNameInfo1->Name.Length = 2048;
		ObjectNameInfo2->Name.Length = 2048;
		Buffer = ExAllocatePool(PagedPool,RetLen+4096);

		status = ObQueryNameString(FileObject,ObjectNameInfo2,ObjectNameInfo2->Name.Length,&RetLen);
		if(NT_SUCCESS(status) && Buffer && ObjectNameInfo1)
		{
			status = ZwQuerySystemInformation(SystemHandleInformation,Buffer,RetLen+4096,&RetLen);
			if(NT_SUCCESS(status))
			{
				UCHAR ObjectTypeIndex = 0;
				PSYSTEM_HANDLE_INFORMATION HandleInformation2 = (PSYSTEM_HANDLE_INFORMATION)Buffer;
				for(int i=0;i<HandleInformation2->NumberOfHandles;i++)
				{
					if(HandleInformation2->Handles[i].Object == FileObject)
					{
						ObjectTypeIndex = HandleInformation2->Handles[i].ObjectTypeIndex;
						Break;
					}
				}
				if(ObjectTypeIndex)
				{
					for(int i=0;i<HandleInformation2->NumberOfHandles;i++)
					{
						if(HandleInformation2->Handles[i].ObjectTypeIndex == ObjectTypeIndex)
						{
							CLIENT_ID ClientId;
							HANDLE TargetProcessHandle = NULL;
							HANDLE CurrentProcessHandle = NULL;
							HANDLE TargetHandle = NULL;
							PVOID TargetFileObject = NULL;
							OBJECT_ATTRIBUTES oa;
							ULONG RetLen;
							InitializeObjectAttributes(&oa,NULL,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
							ClientId.UniqueProcess = HandleInformation2->Handles[i].UniqueProcessId;
							ClientId.UniqueThread = 0;
							status = ZwOpenProcess(&CurrentProcessHandle,PROCESS_ALL_ACCESS, &oa, &ClientId);
							if(NT_SUCCESS(status))
							{
								InitializeObjectAttributes(&oa,NULL,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
								ClientId.UniqueProcess = PsGetCurrentProcessId();
								ClientId.UniqueThread = 0;
								status = ZwOpenProcess(&TargetProcessHandle,PROCESS_ALL_ACCESS, &oa, &ClientId);
								if(NT_SUCCESS(status))
								{//从引用到该对象的进程复制一份句柄到当前进程
									status = ZwDuplicateObject(CurrentProcessHandle,HandleInformation2->Handles[i].HandleValue,TargetProcessHandle,&TargetHandle,0,0,DUPLICATE_SAME_ACCESS);
									if(NT_SUCCESS(status) && TargetHandle)
									{
										status = ObReferenceObjectByHandle(TargetHandle,GENERIC_READ,IoFileObjectType,0,&TargetFileObject,0);
										if(NT_SUCCESS(status) && MmIsAddressValid(TargetFileObject) && TargetFileObject->DeviceObject->DeviceType == FILE_DEVICE_DISK)
										{
											status = ObQueryNameString(TargetFileObject,ObjectNameInfo1,ObjectNameInfo1->Name.Length,&RetLen);
											if(NT_SUCCESS(status))
											{
												__try
												{
													if(RtlEqualUnicodeString(ObjectNameInfo1,ObjectNameInfo2,TRUE))
													{
														PEPROCESS Process = NULL;
														KAPC_STATE ApcState;
														HANDLE ProcessId = HandleInformation2->Handles[i].UniqueProcessId;
														HANDLE ObjectHandle = HandleInformation2->Handles[i].HandleValue;
														OBJECT_HANDLE_FLAG_INFORMATION Ohfi;
														if(ProcessId != 0 && ProcessId != 4 && ProcessId != 8)
														{
															status = PsLookupProcessByProcessId(ProcessId,&Process);
															if(NT_SUCCESS(status))
															{
																KeStackAttachProcess(Process,&ApcState);
																CmpSetHandleProtection(&Ohfi,FALSE);
																ZwClose(ObjectHandle);
																KeUnstackDetachProcess(&ApcState);
																if(Process)
																{
																	ObDereferenceObject(Process);
																	Process = NULL;
																}
															}
														}
													}
													else
													{
														HANDLE ThreadHandle = DecodeKernelHandle(HandleInformation2->Handles[i].HandleValue);
														PsCreateSystemThread(&ThreadHandle,THREAD_ALL_ACCESS,NULL,NULL,NULL,UnlockFileThread,ThreadHandle);
														ZwWaitForSingleObject(ThreadHandle,FALSE,NULL);
														ZwClose(ThreadHandle);
													}
												}
												__finally
												{
												}
											}
										}
									}
								}
							}


							if (TargetProcessHandle)
							{
								ZwClose(TargetProcessHandle);
								TargetProcessHandle = 0;
							}
							if ( CurrentProcessHandle )
							{
								ZwClose(CurrentProcessHandle);
								CurrentProcessHandle = 0;
							}
							if ( TargetHandle )
							{
								ZwClose(TargetHandle);
								TargetHandle = 0;
							}
							if ( TargetFileObject )
							{
								ObfDereferenceObject(TargetFileObject);
								TargetFileObject = 0;
							}
						}
					}
				}
			}
		}
		if(Buffer)
			ExFreePool(Buffer);
		if(ObjectNameInfo1)
			ExFreePool(ObjectNameInfo1);
		if(ObjectNameInfo2)
			ExFreePool(ObjectNameInfo2);
	}
}

NTSTATUS UnlockFile(PUNICODE_STRING FileDosPath)
{//关闭句柄、解除引用、解锁文件
	IO_STATUS_BLOCK IoStatusBlock = {0};
	OBJECT_ATTRIBUTES oa;
	NTSTATUS status;
	HANDLE FileHandle = NULL;
	PFILE_OBJECT FileObject = NULL;
	InitializeObjectAttributes(&oa,FileDosPath,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
	//穿透IopCreateFile得到FileHandle
	status = ResetFileAttributes(FileHandle);
	if(NT_SUCCESS(status) )
	{
		status = ObReferenceObjectByHandle(FileHandle,0,*IoFileObjectType,KernelMode,&FileObject,NULL);
		if(NT_SUCCESS(status))
		{
			IopDeleteFile(FileObject);
			TryUnlockFile(FileObject);
			FileHandle = NULL;
			ObDereferenceObject(FileObject);
		}
	}
	else if(status == STATUS_DELETE_PENDING)
	{
		TryUnlockFile(FileObject);
		status = STATUS_SUCCESS;
		FileHandle = NULL;
	}
	if(FileHandle)
		ZwClose(FileHandle);
	return status;
}

五、获取ObjectInitializer

  获取RegObjectInitializer:

  • 1.获取操作系统版本并转化为数组下标[0-9]
  • 2.获取\Registry\Machine\SYSTEM对应KeyObject,得到其POBJECT_TYPE,判断是否为”Key”类型
  • 3.获取Ntos地址,获取CmpKeyObjectType的ParseProcedure,检测是否在Ntos中
  • 4.获取PCM_KEY_BODY->KeyControlBlock-> KeyHive的偏移,为获取GetCellRoutine
  • 5.Hook GetCellRoutine为NewGetCellRoutine
  • 6.创建线程依次执行ZwSetValueKey ZwQueryValueKey ZwEnumerateValueKey ZwEnumerateKey ZwDeleteValueKey ZwDeleteKey,触发GetCellRoutine
  • 7.NewGetCellRoutine中在回溯栈中查找对应Zw匹配机器码,符合则取得相应Cm地址
  • 8.解除Hook

  获取DriverObjectInitializer和DeviceObjectInitializer:

  • 1.获取操作系统版本并转化为数组下标[0-9]
  • 2.获取DriverObject,得到其POBJECT_TYPE,判断是否为”Device”类型
  • 3.分别获取DriverObjectType和DeviceObjectType的ObjectInitializer

  VersionIndex对照表

major   minor   build   out
*       *               10
5       1               1
5       2               2/3
5       *               10
6       0               4
6       1               5
6       2       8102    7
6       2       9200    8
6       2       *       10      
6       3       9600    9
6       3       *       10  

5.1 获取注册表OBJECT_TYPE,匹配对象类型

  使用\Registry\Machine\SYSTEM注册表对象

POBJECT_TYPE GetRegKeyType()
{
	UNICODE_STRING RegPath,FuncName;
	OBJECT_ATTRIBUTES Oa;
	HANDLE KeyHandle = NULL;
	ULONG Disposition;
	PCM_KEY_BODY KeyBody;
	POBJECT_TYPE ObjType = NULL;
	FARPROC ObGetObjectType;
	NTSTATUS status;
	RtlInitUnicodeString(&RegPath,L"\\Registry\\Machine\\SYSTEM");
	InitializeObjectAttributes(&Oa,&RegPath,ExGetPreviousMode() != KernelMode?OBJ_CASE_INSENSITIVE :
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);		
	status = ZwCreateKey(&KeyHandle,KEY_QUERY_VALUE,&Oa,0,NULL,REG_OPTION_NON_VOLATILE,&Disposition);
	if(NT_SUCCESS(status))
	{
		status = ObReferenceObjectByHandle(KeyHandle,GENERIC_READ,NULL,KernelMode,&KeyBody,NULL);
		if(NT_SUCCESS(status))
		{
			RtlInitUnicodeString(&FuncName,L"ObGetObjectType");
			ObGetObjectType = MmGetSystemRoutineAddress(&FuncName);
			if(ObGetObjectType)
			{
				ObjType = ((POBJECT_TYPE (__stdcall*)(PVOID))ObGetObjectType)(KeyBody);
			}
			else if(VersionIndex < 5)//win7 之前
			{
				ObjType = ((OBJECT_HEADER*)OBJECT_TO_OBJECT_HEADER(Object))->Type;
			}
			ObDereferenceObject(KeyBody);
		}
		ZwClose(KeyHandle);
	}
	return ObjType;
}

typedef struct _OBJECT_TYPE_XP
{
	ERESOURCE Mutex;
	LIST_ENTRY TypeList;
	UNICODE_STRING Name;  
	PVOID DefaultObject;
	ULONG Index;
	ULONG TotalNumberOfObjects;
	ULONG TotalNumberOfHandles;
	ULONG HighWaterNumberOfObjects;
	ULONG HighWaterNumberOfHandles;
	OBJECT_TYPE_INITIALIZER TypeInfo;
	ERESOURCE ObjectLocks[ OBJECT_LOCK_COUNT ];
} OBJECT_TYPE_XP, *POBJECT_TYPE_XP;

typedef struct _OBJECT_TYPE_WIN7
{
	LIST_ENTRY TypeList;
	UNICODE_STRING Name;
	PVOID DefaultObject;
	ULONG Index;
	ULONG TotalNumberOfObjects;
	ULONG TotalNumberOfHandles;
	ULONG HighWaterNumberOfObjects;
	ULONG HighWaterNumberOfHandles;
	OBJECT_TYPE_INITIALIZER TypeInfo;
	EX_PUSH_LOCK TypeLock;
	ULONG Key;
	LIST_ENTRY CallbackList;
} OBJECT_TYPE_WIN7, *POBJECT_TYPE_WIN7;

BOOLEAN CmpRegKeyType(POBJECT_TYPE ObjType)
{
	UNICODE_STRING ObjTypeName;
	RtlInitUnicodeString(&ObjTypeName,L"Key");
	PUNICODE_STRING SrcTypeName;
	if(VersionIndex >= 1 && VersionIndex <= 3)//xp 2000
	{
		POBJECT_TYPE_XP _ObjType = (POBJECT_TYPE_XP)ObjType;
		if(!IsAddressRegionValid(&_ObjType->Name,sizeof(UNICODE_STRING)))
			return FALSE;
		SrcTypeName = &ObjType->Name;
	}
	else if(VersionIndex >= 4 && VersionIndex <= 9)//vista及之后
	{
		POBJECT_TYPE_WIN7 _ObjType = (POBJECT_TYPE_WIN7)ObjType;
		if(!IsAddressRegionValid(&_ObjType->Name,sizeof(UNICODE_STRING)))
			return FALSE;
		SrcTypeName = &ObjType->Name;
	}
	else
	{
		return FALSE;
	}
	if(IsAddressRegionValid(SrcTypeName->Buffer,SrcTypeName->Length))
		return RtlCompareUnicodeString(&ObjTypeName,SrcTypeName,TRUE) == 0;
	return FALSE;
}

5.2获取ParseProcedure

FARPROC RegObjectInitialzer[6];
FARPROC FileObjectInitialzer[6];
// 0 CloseProcedure
// 1 DeleteProcedure
// 2 ParseProcedure
// 3 SecurityProcedure
// 4 QueryNameProcedure
// 5 OpenProcedure

BOOLEAN GetParseProcedure(POBJECT_TYPE ObjectType)
{
	PVOID modules;
	ULONG InfoLen = 0;
	OB_PARSE_METHOD Proc = NULL;
	ULONG_PTR NtosBegin = 0;
	ULONG_PTR NtosEnd = 0;
	RtlZeroMemory(RegObjectInitialzer,sizeof(RegObjectInitialzer));
	if(!ObjectType)
		return FALSE;
	ZwQuerySystemInformation(SystemModuleInformation,&InfoLen,0,&InfoLen);
	if(InfoLen == 0)
		return FALSE;
	modules = ExAllocatePool(PagedPool,InfoLen);
	if(!modules)
		return FALSE;
	status = ZwQuerySystemInformation(SystemModuleInformation,modules,&InfoLen);
	if(NT_SUCCESS(status) && modules->NumberOfModules)
	{
		NtosBegin = modules->Modules[0].ImageBase;
		NtosEnd = NtosBegin + modules->Modules[0].ImageSize;
		if(VersionIndex >= 1 && VersionIndex <= 3)//xp 2000
		{
			POBJECT_TYPE_XP _ObjType = (POBJECT_TYPE_XP)ObjType;
			Proc = _ObjType->TypeInfo.ParseProcedure;
		}
		else if(VersionIndex >= 4 && VersionIndex <= 9)//vista及之后
		{
			POBJECT_TYPE_WIN7 _ObjType = (POBJECT_TYPE_WIN7)ObjType;
			Proc = _ObjType->TypeInfo.ParseProcedure;
		}
	}
	ExFreePool(Modules);
	if(Proc && Proc >= NtosBegin && Proc <= NtosEnd)
	{
		RegObjectInitialzer[2] = Proc;
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

5.3 获取GetCellRoutine偏移,Hook GetCellRoutine

BOOLEAN GetCellRoutineOffset()
{
  ULONG result = 0;
  switch ( VersionIndex )
  {
    case WIN2000:
    case WINXP:
    case WINXPSP3:
    case WINVISTA:
    case 6:
      CellRoutineOffset = 16;
      Return true;
    case WIN7:
    case WIN8:
    case WIN8_1:
    case WIN10:
      CellRoutineOffset = 20;
	Return true;
    default:
      return result;
  }
  return result;
}

5.4 Hook和UnHook GetCellRoutine

volatile ULONG HookCellRoutineRefCount = 0;
volatile ULONG EnterCellRoutineRefCount = 0;
ULONG_PTR OldGetCellRoutine = 0;
BOOLEAN IsGetCell = FALSE;
ULONG_PTR pGetCellRoutine = 0;

BOOLEAN HookCellRoutine(BOOLEAN Hook)
{

	OBJECT_ATTRIBUTES Oa;
	UNICODE_STRING RegPath;
	NTSTATUS status;
	HANDLE KeyHandle = NULL;
	PCM_KEY_BODY KeyBody = NULL;
	BOOLEAN success = FALSE;

	while(InterlockedCompareExchange(&HookCellRoutineRefCount,1,0))//同步
	{
		LARGE_INTEGER Interval;
		Interval.QuadPart = -10000i64 * 100;
		KeDelayExecutionThread(KernelMode,FALSE,&Interval);
	}

	if(Hook)
	{
		if((CellRoutineBit & 0x111111) == 0x111111)
		{
			RtlInitUnicodeString(&RegPath);
			InitializeObjectAttributes(&Oa,&RegPath,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);
			status = ZwOpenKey(&KeyHandle,KEY_ALL_ACCESS,&Oa);
			if(NT_SUCCESS(status))
			{
				status = ObReferenceObjectByHandle(KeyHandle,KEY_SET_VALUE,*CmKeyObjectType,KernelMode,&KeyBody,NULL);
				if(NT_SUCCESS(status))
				{
					ULONG_PTR pGetCellRoutine = (ULONG_PTR)&((HHIVE*)((BYTE*)KeyBody->KeyControlBlock + CellRoutineOffset))->GetCellRoutine;
					OldGetCellRoutine = InterlockedExchange(pGetCellRoutine,NewGetCellRoutine);
					IsGetCell = TRUE;
					success = TRUE;
				}
			}
			if(KeyBody)
				ObReferenceObjectByHandle(KeyBody);
			if(KeyHandle)
				ZwClose(KeyHandle);
		}
	}
	else//UnHook
	{
		if(IsGetCell && OldGetCellRoutine && pGetCellRoutine)
		{
			int count = 0;
			InterlockedExchange(pGetCellRoutine,OldGetCellRoutine);
			do 
			{
				LARGE_INTEGER Interval;
				Interval.QuadPart = -10000i64 * 50;
				KeDelayExecutionThread(KernelMode,FALSE,&Interval);
				InterlockedExchange(&count,EnterCellRoutineRefCount);
			} while (count);
			OldGetCellRoutine = 0;
			pGetCellRoutine = 0;
			IsGetCell = FALSE;
			success = TRUE;
		}
	}
	InterlockedExchange(&HookCellRoutineRefCount,0);
	return success;
}

5.5 创建系统线程获取 Cm*函数

int CmIndex;
/*
	CmQueryValueKey 0
	CmSetValueKey 1
	CmDeleteValueKey 2
	CmDeleteKey 3
	CmEnumerateKey 4
	CmEnumerateValueKey 5
*/
BOOLEAN SetCmTrap()
{//通过注册表操作触发已经Hook的ObjectInitializer
	WCHAR ValueName[] = L"100000";
	WCHAR KeyPath[] = L"\\Registry\\Machine\\SYSTEM\\00000";
	OBJECT_ATTRIBUTES Oa;
	UNICODE_STRING UKeyPath,UValueName;
	LARGE_INTEGER CurrentTime,LocalTime;
	HANDLE KeyHandle = NULL;;
	NTSTATUS status;
	DWORD RetLen;
	TIME_FIELDS TimeFields;
	ULONG Disposition;
	BOOLEAN result = FALSE;
	KeQuerySystemTime(&CurrentTime);
	ExSystemTimeToLocalTime(&CurrentTime,LocalTime);
	RtlTimeToTimeFields(&LocalTime,&TimeFields);
	ValueName[0] += TimeFields.Milliseconds % 9;
	ValueName[1] += TimeFields.Second % 8;
	ValueName[3] += TimeFields.Minute % 7;
	ValueName[4] += TimeFields.Milliseconds % 9;
	ValueName[5] += TimeFields.Second % 8;
	KeyPath[25] += TimeFields.Second % 9;
	KeyPath[26] += TimeFields.Milliseconds % 8;
	KeyPath[27] += TimeFields.Second % 7;
	KeyPath[28] += TimeFields.Milliseconds % 9;
	KeyPath[29] += TimeFields.Minute % 8;
	RtlInitUnicodeString(&UKeyPath,KeyPath);
	InitializeObjectAttributes(&Oa,UKeyPath,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL);
	status = ZwCreateKey(&KeyHandle,KEY_ALL_ACCESS,&Oa,0,NULL,REG_OPTION_NON_VOLATILE,&Disposition);
	if(NT_SUCCESS(status))
	{
		RtlInitUnicodeString(&UValueName,ValueName);
//和NewGetCellRoutine配合使用
		CmIndex = ECmSetValueKey;
		ZwSetValueKey(KeyHandle,&UValueName,0,REG_SZ,ValueName,wcslen(ValueName)+2);
		CmIndex = ECmQueryValueKey;
		ZwQueryValueKey(KeyHandle,&UValueName,KeyValuePartialInformation,NULL,0,&RetLen);
		CmIndex = ECmEnumerateValueKey;
		ZwEnumerateValueKey(KeyHandle,0,KeyValueBasicInformation,NULL,0,&RetLen);
		CmIndex = ECmEnumerateKey;
		ZwEnumerateKey(KeyHandle,0,KeyValueBasicInformation,NULL,0,&RetLen);
		CmIndex = ECmDeleteValueKey;
		ZwDeleteValueKey(KeyHandle,&UValueName);
		CmIndex = ECmDeleteKey;
		ZwDeleteKey(KeyHandle);
		result = TRUE;
	}
	CmIndex = ECmMax;
	if(KeyHandle)
		ZwClose(KeyHandle);
	return result;
}

BOOLEAN CheckAndGetCmInnerFunc(ULONG Address,int CmIndex)							--
{//通过回溯查找cm*地址
/*
对比call   nt!CmSetValueKey之前偏移0x25的机器码:
80619a1f 7c1f            jl      nt!NtSetValueKey+0x234 (80619a40)
80619a21 53              push    ebx
80619a22 ff7518          push    dword ptr [ebp+18h]
80619a25 ff7514          push    dword ptr [ebp+14h]
80619a28 8d45c4          lea     eax,[ebp-3Ch]
80619a2b 50              push    eax
80619a2c ff7704          push    dword ptr [edi+4]
80619a2f e88e0b0100      call    nt!CmSetValueKey (8062a5c2)

CmInnerFuncs
b2e4c640  00 00 00 00 00 00 00 00-7c 00 53 ff 75 00 ff 75  ........|.S.u..u
b2e4c650  00 8d 45 00 50 ff 77 00-01 00 00 00 02 00 00 00  ..
*/
	UCHAR Code[32];
	if(!Address || Address - 0x2F <= 0x7FFFFFFF || !IsAddressRegionValid(Address-0x2F,0x2F))
		return FALSE;
	if(CmMatchData[VersionIndex][CmIndex].CodeMask)
	{
		RtlCopyMemory(Code,Address-0x25,sizeof(Code));
		for(int i=31;i>=0;i--)
		{
			ULONG bit = CmMatchData[VersionIndex][CmIndex].CodeMask >> (31-i);
			if(bit & 1)
			{
				if(CmMatchData[VersionIndex][CmIndex].ByteCode[i] != Code[i])
					return FALSE;
			}
			else if(bit == 0)
			{
				CmMatchData[VersionIndex][CmIndex].FuncAddr = Address+*(ULONG_PTR*)(Address-1);
				CellRoutineBit |= CmMatchData[VersionIndex][CmIndex].CmFlag;
				CmMatchData[VersionIndex][CmIndex].InitFlag = TRUE;
				return TRUE;
			}
		}
	}

	return FALSE;
}

BOOLEAN GetCmFuncsByIndex(ULONG Esp,int CmIndex)
{
	if(!Esp)
		return FALSE;
	for(int i=0;i<100;i++)
	{
		if(!IsAddressRegionValid(Esp,4))
			break;
		if(Esp >= NtosBegin && Esp <= NtosEnd && CheckAndGetCmInnerFunc(Esp,CmIndex))
			return TRUE;
		Esp += 4;
	}
	return FALSE;
}

--x64 下的情况 
CM_MATCH_DATA Ano[]=
{
	{7, 1},
	0, NULL, NCmSetValueKey, 0xFFFFFFFF,
	{
		0x90,0x00,0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x44,0x89,0x74,0x24,0x20,0x4C,0x8B,
		0x4C,0x24,0x60,0x44,0x8B,0xC7,0x48,0x8D,0x54,0x24,0x50,0x48,0x8B,0x4C,0x24,0x48,
	},
	{9, 0},
	0, NULL, 0, 0,
	{
		0,
	}
}

BOOLEAN CheckAndGetCmInnerFunc(ULONG Address,int CmIndex)							
{//通过回溯查找cm*地址
	UCHAR Code[32];
	if(!Address || Address - 0x2F <= 0x7FFFFFFF || !IsAddressRegionValid(Address-0x2F,0x2F))
		return FALSE;
	if(CmMatchData[VersionIndex][CmIndex].CodeMask)
	{
		RtlCopyMemory(Code,Address-0x25,sizeof(Code));
		for(int i=31;i>=0;i--)
		{
			ULONG bit = CmMatchData[VersionIndex][CmIndex].CodeMask >> (31-i);
			if(bit & 1)
			{
				if(CmMatchData[VersionIndex][CmIndex].ByteCode[i] != Code[i])
					goto CompareAnother;
			}
			else if(bit == 0)
			{
				CmMatchData[VersionIndex][CmIndex].FuncAddr = Address+*(ULONG_PTR*)(Address-1);
				CellRoutineBit |= CmMatchData[VersionIndex][CmIndex].CmFlag;
				CmMatchData[VersionIndex][CmIndex].InitFlag = TRUE;
				return TRUE;
			}
		}
	}
	return FALSE;
CompareAnother:

	for(int j=0;Ano[j].Version[0] != 9;j++)
	{
		if(Ano[j].Version[0] == VersionIndex && Ano[j].Version[1] == CmIndex)
		{
			for(int i=31;i>=0;i--)
			{
				ULONG bit = Ano[j].CodeMask >> (31-i);
				if(bit & 1)
				{
					if(Ano[j].ByteCode[i] != Code[i])
						goto CompareAnother;
				}
				else if(bit == 0)
				{
					CmMatchData[VersionIndex][CmIndex].FuncAddr = Address+*(ULONG_PTR*)(Address-1);
					CellRoutineBit |= CmMatchData[VersionIndex][CmIndex].CmFlag;
					CmMatchData[VersionIndex][CmIndex].InitFlag = TRUE;
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}

NTSTATUS __stdcall NewGetCellRoutine(HHIVE Hive,HCELL Cell)
{
	NTSTATUS status;
	ULONG_PTR _Esp = 0;
	_asm
	{
		mov _Esp,esp;
	}
	InterlockedExchangeAdd(&EnterCellRoutineRefCount,1);
	if(PsGetCurrentThreadId() == GetCmRegFuncsThreadId && CmIndex < 6)
	{
		if(CmMatchData[VersionIndex][CmIndex].InitFlag && CmMatchData[VersionIndex][CmIndex].FuncAddr)
		{
			if(!(CmMatchData[VersionIndex][CmIndex].CmFlag & CellRoutineBit))
				CellRoutineBit |= CmMatchData[VersionIndex][CmIndex].CmFlag;
		}
		else
		{
			switch(CmIndex)
			{
			case ECmQueryValueKey:
				GetCmFuncsByIndex();
				break;
			case ECmSetValueKey:
				GetCmFuncsByIndex();
				break;
			case ECmDeleteValueKey:
				GetCmFuncsByIndex();
				break;
			case ECmDeleteKey:
				GetCmFuncsByIndex();
				break;
			case ECmEnumerateKey:
				GetCmFuncsByIndex();
				break;
			case ECmEnumerateValueKey:
				GetCmFuncsByIndex();
				break;
			}

		}
	}
	status = OldGetCellRoutine(Hive,Cell);
	InterlockedExchangeAdd(&EnterCellRoutineRefCount,-1);
	return status;
}

5.6 匹配结构

X86的情况:

  用于匹配cm*函数调用周围的机器码

#define MaxVersion 10
enum
{
	ECmQueryValueKey=0,
	ECmSetValueKey,
	ECmDeleteValueKey,
	ECmDeleteKey,
	ECmEnumerateKey,
	ECmEnumerateValueKey,
	ECmMax,
	NCmQueryValueKey=1,
	NCmSetValueKey=0x10,
	NCmDeleteValueKey=0x100,
	NCmDeleteKey=0x1000,
	NCmEnumerateKey=0x10000,
	NCmEnumerateValueKey=0x100000,
};

#pragma pack(4)
struct CM_MATCH_DATA
{
	ULONG Version[2];//版本
	ULONG InitFlag;//是否初始化
	ULONG FuncAddr;//获取到的cm函数地址
	ULONG CmFlag;//cm函数类型,1~0x100000 对应于各个cm函数
	ULONG CodeMask;//32bit对应于BYTE ByteCode[32]的掩码,决定是否比较
	UCHAR ByteCode[32];//用于比较cm函数的机器码
};
CM_MATCH_DATA CmMatchData[MaxVersion][ECmMax]=
{
{//NON
	{
		{0, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
{//WIN2000
	{
		{1, 0},
		0, NULL, NCmQueryValueKey, 0x00176DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x57,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x76,0x00,
		},
	},
	{
		{1, 1},
		0, NULL, NCmSetValueKey, 0x0000BB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x7C,0x00,0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x77,0x00,
		},
	},
	{
		{1, 2},
		0, NULL, NCmDeleteValueKey, 0x00003DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x39,0x75,0xE4,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{1, 3},
		0, NULL, NCmDeleteKey, 0x0006DB6D,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x46,0x00,
			0xF6,0x40,0x00,0x80,0x75,0x00,0x8B,0x40,0x00,0xF6,0x40,0x00,0x80,0x75,0x00,0x56,
		},
	},
	{
		{1, 4},
		0, NULL, NCmEnumerateKey, 0x001AEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x5D,0x00,0x7C,0x00,
			0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{1, 5},
		0, NULL, NCmEnumerateValueKey, 0x001AEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x5D,0x00,0x7C,0x00,
			0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
},
{//WINXPSP1
	{
		{2, 0},
		0, NULL, NCmQueryValueKey, 0x003B6DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8B,0x7D,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{2, 1},
		0, NULL, NCmSetValueKey, 0x0000BB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x7C,0x00,0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x76,0x00,
		},
	},
	{
		{2, 2},
		0, NULL, NCmDeleteValueKey, 0x00001DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{2, 3},
		0, NULL, NCmDeleteKey, 0x0000DB6D,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0xF6,0x40,0x00,0x80,0x75,0x00,0x8B,0x40,0x00,0xF6,0x40,0x00,0x80,0x75,0x00,0x56,
		},
	},
	{
		{2, 4},
		0, NULL, NCmEnumerateKey, 0x000EEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,
			0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{2, 5},
		0, NULL, NCmEnumerateValueKey, 0x000EEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,
			0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
},
{//WINXPSP3
	{
		{3, 0},
		0, NULL, NCmQueryValueKey, 0x00176DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x56,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{3, 1},
		0, NULL, NCmSetValueKey, 0x0000BB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x7C,0x00,0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x76,0x00,
		},
	},
	{
		{3, 2},
		0, NULL, NCmDeleteValueKey, 0x00001DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{3, 3},
		0, NULL, NCmDeleteKey, 0x0000DB6D,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0xF6,0x40,0x00,0x80,0x75,0x00,0x8B,0x40,0x00,0xF6,0x40,0x00,0x80,0x75,0x00,0x56,
		},
	},
	{
		{3, 4},
		0, NULL, NCmEnumerateKey, 0x000EEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,
			0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
	{
		{3, 5},
		0, NULL, NCmEnumerateValueKey, 0x000EEDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xF6,0x7C,0x00,
			0x53,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x77,0x00,
		},
	},
},
{//WINVISTA
	{
		{4, 0},
		0, NULL, NCmQueryValueKey, 0x01DB6DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0xC7,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{4, 1},
		0, NULL, NCmSetValueKey, 0x0003BB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFF,
			0x75,0x00,0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x75,0x00,
		},
	},
	{
		{4, 2},
		0, NULL, NCmDeleteValueKey, 0x00037FF6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x45,
			0x00,0xC1,0xE8,0x02,0x25,0x01,0xFF,0xFF,0xFF,0x50,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{4, 3},
		0, NULL, NCmDeleteKey, 0x000003FD,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0x22,0x00,0x00,0xC0,0x3B,0xDE,0x7C,0x00,0x57,
		},
	},
	{
		{4, 4},
		0, NULL, NCmEnumerateKey, 0x0016DBB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0xFF,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8B,0x4D,0x00,
		},
	},
	{
		{4, 5},
		0, NULL, NCmEnumerateValueKey, 0x0002DB76,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
},
{//WIN7
	{
		{5, 0},
		0, NULL, NCmQueryValueKey, 0x01DB6DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0xC7,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{5, 1},
		0, NULL, NCmSetValueKey, 0x007FBB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x01,0x0F,0xB6,0xC0,0x50,0xFF,
			0x75,0x00,0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x75,0x00,
		},
	},
	{
		{5, 2},
		0, NULL, NCmDeleteValueKey, 0x00007FF6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0xC1,0xE8,0x02,0x24,0x01,0x0F,0xB6,0xC0,0x50,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{5, 3},
		0, NULL, NCmDeleteKey, 0x00067E61,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC7,0x44,0x00,
			0x00,0x22,0x00,0x00,0xC0,0x39,0x5C,0x00,0x00,0x0F,0x8C,0x00,0x00,0x00,0x00,0x57,
		},
	},
	{
		{5, 4},
		0, NULL, NCmEnumerateKey, 0x0016DBB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0xFF,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0x8B,0x4D,0x00,0x8B,0x55,0x00,
		},
	},
	{
		{5, 5},
		0, NULL, NCmEnumerateValueKey, 0x0002DB76,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
},
{//WIN7SP1
	{
		{6, 0},
		0, NULL, NCmQueryValueKey, 0x01DB6DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0xC7,0x7C,0x00,0xFF,0x75,0x00,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{6, 1},
		0, NULL, NCmSetValueKey, 0x0003BB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFF,
			0x75,0x00,0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x75,0x00,
		},
	},
	{
		{6, 2},
		0, NULL, NCmDeleteValueKey, 0x00037FF6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x45,
			0x00,0xC1,0xE8,0x02,0x25,0x01,0xFF,0xFF,0xFF,0x50,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{6, 3},
		0, NULL, NCmDeleteKey, 0x000003FD,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0x22,0x00,0x00,0xC0,0x3B,0xDE,0x7C,0x00,0x57,
		},
	},
	{
		{6, 4},
		0, NULL, NCmEnumerateKey, 0x0016DBB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0xFF,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8B,0x4D,0x00,
		},
	},
	{
		{6, 5},
		0, NULL, NCmEnumerateValueKey, 0x0002DB76,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
},
{//WIN8
	{
		{7, 0},
		0, NULL, NCmQueryValueKey, 0x001DA7A6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xC0,0x78,0x00,0xFF,
			0x75,0x00,0xFF,0x75,0x00,0x56,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{7, 1},
		0, NULL, NCmSetValueKey, 0x00FFFB6E,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xE8,0x02,0x24,0x01,0x0F,0xB6,0xC0,
			0x50,0x56,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0xFF,0x75,0x00,
		},
	},
	{
		{7, 2},
		0, NULL, NCmDeleteValueKey, 0x001FFDB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xE8,0x02,0x24,0x01,
			0x0F,0xB6,0xC0,0x50,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{7, 3},
		0, NULL, NCmDeleteKey, 0x000003FD,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0x22,0x00,0x00,0xC0,0x85,0xDB,0x78,0x00,0x56,
		},
	},
	{
		{7, 4},
		0, NULL, NCmEnumerateKey, 0x07DB6DB6,
		{
			0x00,0x00,0x00,0x00,0x00,0x8B,0xF0,0x85,0xF6,0x78,0x00,0xFF,0x75,0x00,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8B,0x45,0x00,
		},
	},
	{
		{7, 5},
		0, NULL, NCmEnumerateValueKey, 0x0036DB76,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x7D,0x00,0x00,0x75,0x00,
			0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x57,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
},
{//WIN8.1
	{
		{8, 0},
		0, NULL, NCmQueryValueKey, 0x00786DBE,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xC0,0x0F,0x85,0x00,0x00,0x00,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x56,0x57,0x53,0xFF,0x75,0x00,
		},
	},
	{
		{8, 1},
		0, NULL, NCmSetValueKey, 0x0E1F76DD,
		{
			0x00,0x00,0x00,0x00,0x04,0x0F,0x85,0x00,0x00,0x00,0x00,0x33,0xC0,0x50,0xFF,0x75,
			0x00,0x56,0xFF,0x75,0x00,0xFF,0x75,0x00,0x8D,0x45,0x00,0x50,0x8B,0x5D,0x00,0x53,
		},
	},
	{
		{8, 2},
		0, NULL, NCmDeleteValueKey, 0x1B87FB76,
		{
			0x00,0x00,0x00,0x88,0x5D,0x00,0x0F,0xB6,0x85,0x00,0x00,0x00,0x00,0xC1,0xE8,0x02,
			0x83,0xE0,0x01,0xFF,0x75,0x00,0xFF,0x75,0x00,0x50,0xFF,0x75,0x00,0xFF,0x75,0x00,
		},
	},
	{
		{8, 3},
		0, NULL, NCmDeleteKey, 0x0F0F879C,
		{
			0x00,0x00,0x00,0x00,0x40,0x66,0x89,0x81,0x00,0x00,0x00,0x00,0x66,0x85,0xC0,0x0F,
			0x84,0x00,0x00,0x00,0x00,0x33,0xDB,0x8B,0x74,0x00,0x00,0x56,0x88,0x5C,0x00,0x00,
		},
	},
	{
		{8, 4},
		0, NULL, NCmEnumerateKey, 0x37876DBB,
		{
			0x00,0x00,0x8B,0x75,0x00,0x85,0xDB,0x0F,0x88,0x00,0x00,0x00,0x00,0x57,0xFF,0x75,
			0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0xFF,0x75,0x00,0x56,0x8B,0x7D,0x00,0x8B,0xC7,
		},
	},
	{
		{8, 5},
		0, NULL, NCmEnumerateValueKey, 0x3F0EEDDD,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xF6,0x0F,0x85,0x00,0x00,0x00,0x00,
			0x57,0xFF,0x75,0x00,0x53,0xFF,0x75,0x00,0x8B,0x5D,0x00,0x53,0x8B,0x7D,0x00,0x57,
		},
	},
},
{//WIN10
	{
		{9, 0},
		0, NULL, NCmQueryValueKey, 0xFFFFFFFF,
		{
			0x00,0x00,0x85,0xF6,0x0F,0x85,0x0A,0xD7,0x10,0x00,0x8B,0x7D,0xB8,0xFF,0x75,0xCC,
			0xFF,0x75,0xC8,0xFF,0x75,0xB4,0x53,0x57,0x8B,0x5D,0x10,0x8B,0xD3,0x8B,0x4D,0xBC,
		},
	},
	{
		{9, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0x5D,0xCB,0x0F,0xB6,0x85,0x74,0xFF,0xFF,0xFF,0xC1,0xE8,0x02,0x83,0xE0,0x01,0x50,
			0xFF,0x75,0x88,0x57,0xFF,0x75,0xAC,0xFF,0x75,0x14,0x8D,0x55,0xB8,0x8B,0x4D,0xB4,
		},
	},
	{
		{9, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFFFFFF,
		{
			0xC4,0x0D,0x00,0x88,0x5D,0xCB,0x0F,0xB6,0x85,0x7C,0xFF,0xFF,0xFF,0xC1,0xE8,0x02,
			0x83,0xE0,0x01,0xFF,0x75,0xBC,0xFF,0x75,0xB8,0x50,0x8B,0x55,0xA8,0x8B,0x4D,0xB4,
		},
	},
	{
		{9, 3},
		0, NULL, NCmDeleteKey, 0xFFFFFFFF,
		{
			0x01,0x00,0x00,0x40,0x66,0x89,0x81,0x3C,0x01,0x00,0x00,0x66,0x85,0xC0,0x0F,0x84,
			0x9E,0x00,0x00,0x00,0x33,0xDB,0x8B,0x74,0x24,0x10,0x8B,0xCE,0x88,0x5C,0x24,0x2C,
		},
	},
	{
		{9, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0xE8,0x5A,0xB1,0xFF,0xFF,0x8B,0xF0,0x85,0xF6,0x78,0x1C,0xFF,0x75,0xB8,0xFF,0x75,
			0x18,0xFF,0x75,0xBC,0xFF,0x75,0x10,0xFF,0x75,0x0C,0x8B,0x55,0xC4,0x8B,0x4D,0xC8,
		},
	},
	{
		{9, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x8B,0xF0,0x85,0xF6,0x78,0x21,0x8B,0x4D,0xCC,0x83,0x7D,0xC8,0x00,0x0F,0x85,0x84,
			0xCA,0x0D,0x00,0xFF,0x75,0xC0,0xFF,0x75,0x18,0xFF,0x75,0xC4,0x57,0x8B,0x55,0x0C,
		},
	},
},
};

X64的情况

#pragma pack(8)
struct CM_MATCH_DATA
{
	ULONG Version[2];//版本
	ULONG InitFlag;//是否初始化
	ULONG _gap;//8字节对齐
	ULONGLONG FuncAddr;//获取到的cm函数地址
	ULONG CmFlag;//cm函数类型,1~0x100000 对应于各个cm函数
	ULONG CodeMask;//32bit对应于BYTE ByteCode[32]的掩码,决定是否比较
	UCHAR ByteCode[32];//用于比较cm函数的机器码
};
CM_MATCH_DATA CmMatchData[MaxVersion][ECmMax]=
{
{//NON
	{
		{0, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{0, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
{//WIN2000
	{
		{1, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{1, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{1, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{1, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{1, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{1, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
{//WINXPSP1
	{
		{2, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{2, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{2, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{2, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{2, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{2, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
{//WINXPSP3
	{
		{3, 0},
		0, NULL, NCmQueryValueKey, 0xFFFFFFFF,
		{
			0x44,0x89,0x64,0x24,0x20,0x4D,0x8B,0xCE,0x44,0x8B,0xC3,0x48,0x8D,0x94,0x24,0x30,
			0x01,0x00,0x00,0x4C,0x8B,0x64,0x24,0x48,0x4C,0x89,0x64,0x24,0x40,0x49,0x8B,0xCC,
		},
	},
	{
		{3, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0x01,0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x44,0x89,0x74,0x24,0x20,0x4D,0x8B,0xCD,
			0x44,0x8B,0x84,0x24,0x58,0x01,0x00,0x00,0x48,0x8D,0x54,0x24,0x48,0x48,0x8B,0xCE,
		},
	},
	{
		{3, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFFFFFF,
		{
			0x28,0x44,0x24,0x40,0x66,0x0F,0x7F,0x84,0x24,0xC0,0x00,0x00,0x00,0x4C,0x8B,0x84,
			0x24,0x10,0x01,0x00,0x00,0x48,0x8D,0x94,0x24,0xC0,0x00,0x00,0x00,0x48,0x8B,0xCE,
		},
	},
	{
		{3, 3},
		0, NULL, NCmDeleteKey, 0xFFFFFFFF,
		{
			0x49,0x3B,0xCD,0x74,0x0A,0xF6,0x41,0x04,0x80,0x0F,0x85,0xE2,0x44,0x0B,0x00,0x41,
			0x3A,0xF5,0x0F,0x85,0x93,0x44,0x0B,0x00,0x41,0x3B,0xFD,0x7C,0x0F,0x48,0x8B,0xCB,
		},
	},
	{
		{3, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0x4C,0x89,0x74,0x24,0x20,0x45,0x8B,0xCC,0x44,0x8B,0x84,0x24,0x58,0x01,0x00,0x00,
			0x4C,0x8B,0x64,0x24,0x50,0x49,0x8B,0xD4,0x48,0x8B,0x74,0x24,0x40,0x48,0x8B,0xCE,
		},
	},
	{
		{3, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x00,0x00,0x89,0x44,0x24,0x20,0x4C,0x8B,0x8C,0x24,0x38,0x01,0x00,0x00,0x44,0x8B,
			0xC6,0x8B,0x94,0x24,0x28,0x01,0x00,0x00,0x4C,0x8B,0x64,0x24,0x50,0x49,0x8B,0xCC,
		},
	},
},
{//WINVISTA
	{
		{4, 0},
		0, NULL, NCmQueryValueKey, 0xFFFFFFFF,
		{
			0x4C,0x89,0x6C,0x24,0x28,0x44,0x89,0x64,0x24,0x20,0x4D,0x8B,0xCE,0x44,0x8B,0xC7,
			0x48,0x8D,0x94,0x24,0x40,0x01,0x00,0x00,0x4C,0x8B,0x64,0x24,0x60,0x49,0x8B,0xCC,
		},
	},
	{
		{4, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0x48,0x8B,0x84,0x24,0x20,0x01,0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x44,0x89,0x6C,
			0x24,0x20,0x4D,0x8B,0xCC,0x44,0x8B,0xC6,0x48,0x8D,0x54,0x24,0x48,0x48,0x8B,0xCF,
		},
	},
	{
		{4, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFFFFFF,
		{
			0x28,0x44,0x24,0x40,0x66,0x0F,0x7F,0x84,0x24,0xB0,0x00,0x00,0x00,0x4C,0x8B,0x84,
			0x24,0x00,0x01,0x00,0x00,0x48,0x8D,0x94,0x24,0xB0,0x00,0x00,0x00,0x48,0x8B,0xCF,
		},
	},
	{
		{4, 3},
		0, NULL, NCmDeleteKey, 0xFFE7F3FF,
		{
			0x49,0x3B,0xCD,0x74,0x0A,0xF6,0x41,0x04,0x80,0x0F,0x85,0x58,0x38,0x0E,0x00,0x41,
			0x3A,0xF5,0x0F,0x85,0x06,0x38,0x0E,0x00,0x41,0x3B,0xDD,0x7C,0x1D,0x48,0x8B,0xCF,
		},
	},
	{
		{4, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0x30,0x89,0x74,0x24,0x28,0x4C,0x89,0x74,0x24,0x20,0x45,0x8B,0xCD,0x45,0x8B,0xC7,
			0x48,0x8B,0x7C,0x24,0x50,0x48,0x8B,0xD7,0x48,0x8B,0x74,0x24,0x40,0x48,0x8B,0xCE,
		},
	},
	{
		{4, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x24,0x28,0x44,0x89,0x64,0x24,0x20,0x4C,0x8B,0xCE,0x45,0x8B,0xC7,0x44,0x8B,0xAC,
			0x24,0x68,0x01,0x00,0x00,0x41,0x8B,0xD5,0x48,0x8B,0x74,0x24,0x50,0x48,0x8B,0xCE,
		},
	},
},
{//WIN7
	{
		{5, 0},
		0, NULL, NCmQueryValueKey, 0xFFFFFFFF,
		{
			0x4C,0x89,0x6C,0x24,0x28,0x44,0x89,0x64,0x24,0x20,0x4D,0x8B,0xCE,0x44,0x8B,0xC7,
			0x48,0x8D,0x94,0x24,0x40,0x01,0x00,0x00,0x4C,0x8B,0x64,0x24,0x60,0x49,0x8B,0xCC,
		},
	},
	{
		{5, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0x48,0x8B,0x84,0x24,0x30,0x01,0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x44,0x89,0x6C,
			0x24,0x20,0x4D,0x8B,0xCC,0x44,0x8B,0xC6,0x48,0x8D,0x54,0x24,0x48,0x48,0x8B,0xCF,
		},
	},
	{
		{5, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFFFFFF,
		{
			0x28,0x44,0x24,0x40,0x66,0x0F,0x7F,0x84,0x24,0xB0,0x00,0x00,0x00,0x4C,0x8B,0x84,
			0x24,0x00,0x01,0x00,0x00,0x48,0x8D,0x94,0x24,0xB0,0x00,0x00,0x00,0x48,0x8B,0xCF,
		},
	},
	{
		{5, 3},
		0, NULL, NCmDeleteKey, 0xFFE7F3FF,
		{
			0x49,0x3B,0xCD,0x74,0x0A,0xF6,0x41,0x04,0x80,0x0F,0x85,0x7A,0x55,0x0D,0x00,0x41,
			0x3A,0xF5,0x0F,0x85,0x28,0x55,0x0D,0x00,0x41,0x3B,0xDD,0x7C,0x1D,0x48,0x8B,0xCF,
		},
	},
	{
		{5, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0x44,0x89,0x64,0x24,0x28,0x48,0x89,0x7C,0x24,0x20,0x45,0x8B,0xCE,0x45,0x8B,0xC7,
			0x48,0x8B,0x7C,0x24,0x50,0x48,0x8B,0xD7,0x48,0x8B,0x74,0x24,0x40,0x48,0x8B,0xCE,
		},
	},
	{
		{5, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x24,0x28,0x44,0x89,0x64,0x24,0x20,0x4C,0x8B,0xCE,0x45,0x8B,0xC7,0x44,0x8B,0xAC,
			0x24,0x68,0x01,0x00,0x00,0x41,0x8B,0xD5,0x48,0x8B,0x74,0x24,0x50,0x48,0x8B,0xCE,
		},
	},
},
{//WIN7SP1
	{
		{6, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x48,0x8D,0x94,0x24,0x30,0x01,0x00,0x00,0x4C,0x8B,0x64,0x24,0x48,0x4C,0x89,0x64,
			0x24,0x40,0x49,0x8B,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{6, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x4D,0x8B,0xCD,0x44,0x8B,0x84,0x24,0x58,0x01,0x00,0x00,0x48,0x8D,0x54,0x24,0x48,
			0x48,0x8B,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{6, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x4C,0x8B,0x84,0x24,0x10,0x01,0x00,0x00,0x48,0x8D,0x94,0x24,0xC0,0x00,0x00,0x00,
			0x48,0x8B,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{6, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x41,0x3A,0xF5,0x0F,0x85,0x4B,0x37,0x0D,0x00,0x41,0x3B,0xFD,0x7C,0x0F,0x48,0x8B,
			0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{6, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{6, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
{//WIN8
	{
		{7, 0},
		0, NULL, NCmQueryValueKey, 0xDFF7FFFF,
		{
			0x4C,0x89,0x7C,0x24,0x28,0x44,0x89,0x74,0x24,0x20,0x4D,0x8B,0xCC,0x44,0x8B,0xC7,
			0x48,0x8D,0x94,0x24,0x70,0x01,0x00,0x00,0x4C,0x8B,0x74,0x24,0x50,0x49,0x8B,0xCE,
		},
	},
	{
		{7, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x89,0x5C,0x24,0x20,0x4C,0x8B,0x4C,0x24,0x60,
			0x45,0x8B,0xC5,0x48,0x8D,0x54,0x24,0x50,0x48,0x8B,0x7C,0x24,0x48,0x48,0x8B,0xCF,
		},
	},
	{
		{7, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFF7FFE,
		{
			0xE1,0x01,0x0F,0x28,0x44,0x24,0x40,0x66,0x0F,0x7F,0x84,0x24,0xE0,0x00,0x00,0x00,
			0x4C,0x8B,0xC6,0x48,0x8D,0x94,0x24,0xE0,0x00,0x00,0x00,0x48,0x8B,0x4C,0x24,0x50,
		},
	},
	{
		{7, 3},
		0, NULL, NCmDeleteKey, 0x009887FF,
		{
			0xE4,0x01,0x00,0x00,0xFF,0xC0,0x66,0x89,0x81,0xE4,0x01,0x00,0x00,0x66,0x85,0xC0,
			0x0F,0x84,0xB8,0x00,0x00,0x00,0x48,0x8B,0x7D,0xA7,0x45,0x8A,0xFD,0x48,0x8B,0xCF,
		},
	},
	{
		{7, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0x30,0x89,0x74,0x24,0x28,0x48,0x89,0x7C,0x24,0x20,0x45,0x8B,0xCC,0x45,0x8B,0xC6,
			0x48,0x8B,0x7C,0x24,0x50,0x48,0x8B,0xD7,0x48,0x8B,0x74,0x24,0x48,0x48,0x8B,0xCE,
		},
	},
	{
		{7, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x00,0x4C,0x89,0x64,0x24,0x28,0x89,0x74,0x24,0x20,0x4D,0x8B,0xCE,0x45,0x8B,0xC7,
			0x44,0x8B,0x74,0x24,0x50,0x41,0x8B,0xD6,0x48,0x8B,0x74,0x24,0x58,0x48,0x8B,0xCE,
		},
	},
},
{//WIN8.1
	{
		{8, 0},
		0, NULL, NCmQueryValueKey, 0xFFFFFFFF,
		{
			0x01,0x00,0x00,0x4C,0x89,0x6C,0x24,0x28,0x44,0x89,0x7C,0x24,0x20,0x4D,0x8B,0xCC,
			0x44,0x8B,0x44,0x24,0x48,0x48,0x8D,0x94,0x24,0x60,0x01,0x00,0x00,0x49,0x8B,0xCE,
		},
	},
	{
		{8, 1},
		0, NULL, NCmSetValueKey, 0xFFFFFFFF,
		{
			0xB8,0x00,0x00,0x00,0x48,0x89,0x44,0x24,0x28,0x44,0x89,0x74,0x24,0x20,0x4C,0x8B,
			0x4C,0x24,0x68,0x44,0x8B,0xC7,0x48,0x8D,0x54,0x24,0x50,0x48,0x8B,0x4C,0x24,0x60,
		},
	},
	{
		{8, 2},
		0, NULL, NCmDeleteValueKey, 0xFFFFFFFF,
		{
			0xE1,0x01,0x0F,0x28,0x44,0x24,0x40,0x66,0x0F,0x7F,0x84,0x24,0xE0,0x00,0x00,0x00,
			0x4C,0x8B,0xC6,0x48,0x8D,0x94,0x24,0xE0,0x00,0x00,0x00,0x48,0x8B,0x4C,0x24,0x50,
		},
	},
	{
		{8, 3},
		0, NULL, NCmDeleteKey, 0xFFFFFFFF,
		{
			0xE4,0x01,0x00,0x00,0xFF,0xC0,0x66,0x89,0x81,0xE4,0x01,0x00,0x00,0x66,0x85,0xC0,
			0x0F,0x84,0xBC,0x00,0x00,0x00,0x48,0x8B,0x7D,0xB7,0x45,0x8A,0xFD,0x48,0x8B,0xCF,
		},
	},
	{
		{8, 4},
		0, NULL, NCmEnumerateKey, 0xFFFFFFFF,
		{
			0x8B,0x84,0x24,0xA0,0x01,0x00,0x00,0x89,0x44,0x24,0x28,0x4C,0x89,0x74,0x24,0x20,
			0x45,0x8B,0xCF,0x45,0x8B,0xC5,0x48,0x8B,0x54,0x24,0x58,0x48,0x8B,0x4C,0x24,0x48,
		},
	},
	{
		{8, 5},
		0, NULL, NCmEnumerateValueKey, 0xFFFFFFFF,
		{
			0x4C,0x24,0x58,0x48,0x39,0x5C,0x24,0x60,0x0F,0x85,0x7E,0xC0,0x19,0x00,0x4C,0x89,
			0x6C,0x24,0x28,0x89,0x44,0x24,0x20,0x4D,0x8B,0xCE,0x44,0x8B,0xC6,0x41,0x8B,0xD7,
		},
	},
},
{//WIN10
	{
		{9, 0},
		0, NULL, NCmQueryValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{9, 1},
		0, NULL, NCmSetValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{9, 2},
		0, NULL, NCmDeleteValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{9, 3},
		0, NULL, NCmDeleteKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{9, 4},
		0, NULL, NCmEnumerateKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
	{
		{9, 5},
		0, NULL, NCmEnumerateValueKey, 0x00000000,
		{
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
			0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		},
	},
},
},

5.8 获取DeviceObject对象类型

POBJECT_TYPE GetDeviceObjectType()
{
	UNICODE_STRING UAcpi;
	UNICODE_STRING UFilePath;
	NTSTATUS status;
	PDRIVER_OBJECT pDrvObj = NULL;
	PDEVICE_OBJECT pDevObj = NULL;
	HANDLE FileHandle = NULL;
	POBJECT_TYPE ObjectType = NULL;
	RtlInitUnicodeString(&UAcpi,L"\\Driver\\ACPI");
	status = ObReferenceObjectByName(&UAcpi,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,0,*IoDriverObjectType,KernelMode,NULL,&pDrvObj);
	if(NT_SUCCESS(status) && pDrvObj && pDrvObj->DeviceObject)
	{
		pDevObj = pDrvObj->DeviceObject;
	}
	if(pDevObj)
	{
		ObjectType = (POBJECT_TYPE)((PUCHAR)pDevObj-16);
	}
	if(pDrvObj)
	{
		ObDereferenceObject(pDrvObj);
		pDrvObj = NULL;
	}
	if(FileHandle)
	{
		ZwClose(FileHandle);
		FileHandle = NULL;
	}
	return ObjectType;
}
Show Disqus Comments

Search

    Table of Contents