C语言驱动开发内核特征码扫描PE代码段

C/C++
242
0
0
2023-06-08
目录
  • 正文
  • 特征码字符串解析与扫描实现
  • UtilLySharkSearchPattern如何定位特征
  • RtlImageNtHeader对其PE头部解析

正文

在笔者上一篇文章《驱动开发:内核特征码搜索函数封装》中为了定位特征的方便我们封装实现了一个可以传入数组实现的SearchSpecialCode定位函数,该定位函数其实还不能算的上简单,本章LyShark将对特征码定位进行简化,让定位变得更简单,并运用定位代码实现扫描内核PE的.text代码段,并从代码段中得到某个特征所在内存位置。

老样子为了后续教程能够继续,先来定义一个lyshark.h头文件,该头文件中包含了我们本篇文章所必须要使用到的结构体定义,这些定义的函数如果不懂请去看LyShark以前的文章,这里就不罗嗦了。

#include <ntifs.h>
#include <ntimage.h>
typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	ULONG __Undefined1;
	ULONG __Undefined2;
	ULONG __Undefined3;
	ULONG NonPagedDebugInfo;
	ULONG DllBase;
	ULONG EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG   Flags;
	USHORT  LoadCount;
	USHORT  __Undefined;
	ULONG __Undefined6;
	ULONG   CheckSum;
	ULONG   __padding;
	ULONG   TimeDateStamp;
	ULONG   __padding;
}KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
	HANDLE Section;
	PVOID MappedBase;
	PVOID ImageBase;
	ULONG ImageSize;
	ULONG Flags;
	USHORT LoadOrderIndex;
	USHORT InitOrderIndex;
	USHORT LoadCount;
	USHORT OffsetToFileName;
	UCHAR  FullPathName[];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
	ULONG NumberOfModules;
	RTL_PROCESS_MODULE_INFORMATION Modules[];
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
typedef enum _SYSTEM_INFORMATION_CLASS
{
	SystemBasicInformation =x0,
	SystemProcessorInformation =x1,
	SystemPerformanceInformation =x2,
	SystemTimeOfDayInformation =x3,
	SystemPathInformation =x4,
	SystemProcessInformation =x5,
	SystemCallCountInformation =x6,
	SystemDeviceInformation =x7,
	SystemProcessorPerformanceInformation =x8,
	SystemFlagsInformation =x9,
	SystemCallTimeInformation =xa,
	SystemModuleInformation =xb,
	SystemLocksInformation =xc,
	SystemStackTraceInformation =xd,
	SystemPagedPoolInformation =xe,
	SystemNonPagedPoolInformation =xf,
	SystemHandleInformation =x10,
	SystemObjectInformation =x11,
	SystemPageFileInformation =x12,
	SystemVdmInstemulInformation =x13,
	SystemVdmBopInformation =x14,
	SystemFileCacheInformation =x15,
	SystemPoolTagInformation =x16,
	SystemInterruptInformation =x17,
	SystemDpcBehaviorInformation =x18,
	SystemFullMemoryInformation =x19,
	SystemLoadGdiDriverInformation =x1a,
	SystemUnloadGdiDriverInformation =x1b,
	SystemTimeAdjustmentInformation =x1c,
	SystemSummaryMemoryInformation =x1d,
	SystemMirrorMemoryInformation =x1e,
	SystemPerformanceTraceInformation =x1f,
	SystemObsolete = 0x20,
	SystemExceptionInformation =x21,
	SystemCrashDumpStateInformation =x22,
	SystemKernelDebuggerInformation =x23,
	SystemContextSwitchInformation =x24,
	SystemRegistryQuotaInformation =x25,
	SystemExtendServiceTableInformation =x26,
	SystemPrioritySeperation =x27,
	SystemVerifierAddDriverInformation =x28,
	SystemVerifierRemoveDriverInformation =x29,
	SystemProcessorIdleInformation =x2a,
	SystemLegacyDriverInformation =x2b,
	SystemCurrentTimeZoneInformation =x2c,
	SystemLookasideInformation =x2d,
	SystemTimeSlipNotification =x2e,
	SystemSessionCreate =x2f,
	SystemSessionDetach =x30,
	SystemSessionInformation =x31,
	SystemRangeStartInformation =x32,
	SystemVerifierInformation =x33,
	SystemVerifierThunkExtend =x34,
	SystemSessionProcessInformation =x35,
	SystemLoadGdiDriverInSystemSpace =x36,
	SystemNumaProcessorMap =x37,
	SystemPrefetcherInformation =x38,
	SystemExtendedProcessInformation =x39,
	SystemRecommendedSharedDataAlignment =x3a,
	SystemComPlusPackage =x3b,
	SystemNumaAvailableMemory =x3c,
	SystemProcessorPowerInformation =x3d,
	SystemEmulationBasicInformation =x3e,
	SystemEmulationProcessorInformation =x3f,
	SystemExtendedHandleInformation =x40,
	SystemLostDelayedWriteInformation =x41,
	SystemBigPoolInformation =x42,
	SystemSessionPoolTagInformation =x43,
	SystemSessionMappedViewInformation =x44,
	SystemHotpatchInformation =x45,
	SystemObjectSecurityMode =x46,
	SystemWatchdogTimerHandler =x47,
	SystemWatchdogTimerInformation =x48,
	SystemLogicalProcessorInformation =x49,
	SystemWowSharedInformationObsolete = 0x4a,
	SystemRegisterFirmwareTableInformationHandler =x4b,
	SystemFirmwareTableInformation =x4c,
	SystemModuleInformationEx =x4d,
	SystemVerifierTriageInformation =x4e,
	SystemSuperfetchInformation =x4f,
	SystemMemoryListInformation =x50,
	SystemFileCacheInformationEx =x51,
	SystemThreadPriorityClientIdInformation =x52,
	SystemProcessorIdleCycleTimeInformation =x53,
	SystemVerifierCancellationInformation =x54,
	SystemProcessorPowerInformationEx =x55,
	SystemRefTraceInformation =x56,
	SystemSpecialPoolInformation =x57,
	SystemProcessIdInformation =x58,
	SystemErrorPortInformation =x59,
	SystemBootEnvironmentInformation =x5a,
	SystemHypervisorInformation =x5b,
	SystemVerifierInformationEx =x5c,
	SystemTimeZoneInformation =x5d,
	SystemImageFileExecutionOptionsInformation =x5e,
	SystemCoverageInformation =x5f,
	SystemPrefetchPatchInformation =x60,
	SystemVerifierFaultsInformation =x61,
	SystemSystemPartitionInformation =x62,
	SystemSystemDiskInformation =x63,
	SystemProcessorPerformanceDistribution =x64,
	SystemNumaProximityNodeInformation =x65,
	SystemDynamicTimeZoneInformation =x66,
	SystemCodeIntegrityInformation =x67,
	SystemProcessorMicrocodeUpdateInformation =x68,
	SystemProcessorBrandString =x69,
	SystemVirtualAddressInformation =x6a,
	SystemLogicalProcessorAndGroupInformation =x6b,
	SystemProcessorCycleTimeInformation =x6c,
	SystemStoreInformation =x6d,
	SystemRegistryAppendString =x6e,
	SystemAitSamplingValue =x6f,
	SystemVhdBootInformation =x70,
	SystemCpuQuotaInformation =x71,
	SystemNativeBasicInformation =x72,
	SystemErrorPortTimeouts =x73,
	SystemLowPriorityIoInformation =x74,
	SystemBootEntropyInformation =x75,
	SystemVerifierCountersInformation =x76,
	SystemPagedPoolInformationEx =x77,
	SystemSystemPtesInformationEx =x78,
	SystemNodeDistanceInformation =x79,
	SystemAcpiAuditInformation =x7a,
	SystemBasicPerformanceInformation =x7b,
	SystemQueryPerformanceCounterInformation =x7c,
	SystemSessionBigPoolInformation =x7d,
	SystemBootGraphicsInformation =x7e,
	SystemScrubPhysicalMemoryInformation =x7f,
	SystemBadPageInformation =x80,
	SystemProcessorProfileControlArea =x81,
	SystemCombinePhysicalMemoryInformation =x82,
	SystemEntropyInterruptTimingInformation =x83,
	SystemConsoleInformation =x84,
	SystemPlatformBinaryInformation =x85,
	SystemThrottleNotificationInformation =x86,
	SystemHypervisorProcessorCountInformation =x87,
	SystemDeviceDataInformation =x88,
	SystemDeviceDataEnumerationInformation =x89,
	SystemMemoryTopologyInformation =x8a,
	SystemMemoryChannelInformation =x8b,
	SystemBootLogoInformation =x8c,
	SystemProcessorPerformanceInformationEx =x8d,
	SystemSpare = 0x8e,
	SystemSecureBootPolicyInformation =x8f,
	SystemPageFileInformationEx =x90,
	SystemSecureBootInformation =x91,
	SystemEntropyInterruptTimingRawInformation =x92,
	SystemPortableWorkspaceEfiLauncherInformation =x93,
	SystemFullProcessInformation =x94,
	SystemKernelDebuggerInformationEx =x95,
	SystemBootMetadataInformation =x96,
	SystemSoftRebootInformation =x97,
	SystemElamCertificateInformation =x98,
	SystemOfflineDumpConfigInformation =x99,
	SystemProcessorFeaturesInformation =x9a,
	SystemRegistryReconciliationInformation =x9b,
	MaxSystemInfoClass =x9c,
} SYSTEM_INFORMATION_CLASS;
// 声明函数
// By: Lyshark.com
NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(_In_ PVOID Base);
NTSTATUS NTAPI ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
typedef VOID(__cdecl *PMiProcessLoaderEntry)(PKLDR_DATA_TABLE_ENTRY section, IN LOGICAL Insert);
typedef NTSTATUS(*NTQUERYSYSTEMINFORMATION)(IN ULONG SystemInformationClass, OUT PVOID SystemInformation, IN ULONG_PTR SystemInformationLength, OUT PULONG_PTR ReturnLength OPTIONAL);

特征码字符串解析与扫描实现

我们继续,首先实现特征码字符串的解析与扫描实现此处UtilLySharkSearchPattern函数就是LyShark封装过的,这里依次介绍一下参数传递的含义。

  • pattern 用于传入一段字符串特征值(以\x开头)
  • len 代表输入特征码长度(除去\x后的长度)
  • base 代表扫描内存的基地址
  • size 代表需要向下扫描的长度
  • ppFound 代表扫描到首地址以后返回的内存地址

UtilLySharkSearchPattern如何定位特征

这段代码该如何使用,如下我们以定位IoInitializeTimer为例,演示UtilLySharkSearchPattern如何定位特征的,如下代码pattern变量中就是我们需要定位的特征值,pattern_size则是需要定位的特征码长度,在address地址位置向下扫描128字节,找到则返回到find_address变量内。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "lyshark.h"
PVOID GetIoInitializeTimerAddress()
{
	PVOID VariableAddress =;
	UNICODE_STRING uioiTime = { };
	RtlInitUnicodeString(&uioiTime, L"IoInitializeTimer");
	VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime);
	if (VariableAddress !=)
	{
		return VariableAddress;
	}
	return;
}
// 对指定内存执行特征码扫描
NTSTATUS UtilLySharkSearchPattern(IN PUCHAR pattern, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound)
{
	// 计算匹配长度
	// LyShark.com 特征码扫描
	NT_ASSERT(ppFound != && pattern != 0 && base != 0);
	if (ppFound == || pattern == 0 || base == 0)
	{
		return STATUS_INVALID_PARAMETER;
	}
	__try
	{
		for (ULONG_PTR i =; i < size - len; i++)
		{
			BOOLEAN found = TRUE;
			for (ULONG_PTR j =; j < len; j++)
			{
				if (pattern[j] != ((PUCHAR)base)[i + j])
				{
					found = FALSE;
					break;
				}
			}
			if (found != FALSE)
			{
				*ppFound = (PUCHAR)base + i;
				DbgPrint("[LyShark.com] 特征码匹配地址: %p \n", (PUCHAR)base + i);
				return STATUS_SUCCESS;
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return STATUS_UNHANDLED_EXCEPTION;
	}
	return STATUS_NOT_FOUND;
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint(("Uninstall Driver Is OK \n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint(("hello lyshark.com \n"));
	// 返回匹配长度
	CHAR pattern[] = "\x\x89\x6c\x24\x10";
	PVOID *find_address = NULL;
	int pattern_size = sizeof(pattern) -;
	DbgPrint("匹配长度: %d \n", pattern_size);
	// 得到基地址
	PVOID address = GetIoInitializeTimerAddress();
	// 扫描特征
	NTSTATUS nt = UtilLySharkSearchPattern((PUCHAR)pattern, pattern_size, address,, &find_address);
	DbgPrint("[LyShark 返回地址 => ]x%p \n", (ULONG64)find_address);
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行驱动程序完成特征定位,并对比定位效果。

RtlImageNtHeader对其PE头部解析

如上述所示定位函数我们已经封装好了,相信你也能感受到这种方式要比使用数组更方便,为了能定位到内核PE结构我们需要使用RtlImageNtHeader来解析,这个内核函数专门用来得到内核程序的PE头部结构的,在下方案例中首先我们使用封装过的LySharkToolsUtilKernelBase函数拿到内核基址,如果你不懂函数实现细节请阅读《驱动开发:内核取ntoskrnl模块基地址》这篇文章,拿到基址以后可以直接使用RtlImageNtHeader对其PE头部进行解析,如下所示。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "lyshark.h"
// 定义全局变量
static PVOID g_KernelBase =;
static ULONG g_KernelSize =;
// 得到KernelBase基地址
// lyshark.com
PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG bytes =;
	PRTL_PROCESS_MODULES pMods =;
	PVOID checkPtr =;
	UNICODE_STRING routineName;
	if (g_KernelBase !=)
	{
		if (pSize)
		{
			*pSize = g_KernelSize;
		}
		return g_KernelBase;
	}
	RtlInitUnicodeString(&routineName, L"NtOpenFile");
	checkPtr = MmGetSystemRoutineAddress(&routineName);
	if (checkPtr ==)
		return;
	__try
	{
		status = ZwQuerySystemInformation(SystemModuleInformation,, bytes, &bytes);
		if (bytes ==)
		{
			return;
		}
		pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPoolNx, bytes, L"LyShark");
		RtlZeroMemory(pMods, bytes);
		status = ZwQuerySystemInformation(SystemModuleInformation, pMods, bytes, &bytes);
		if (NT_SUCCESS(status))
		{
			PRTL_PROCESS_MODULE_INFORMATION pMod = pMods->Modules;
			for (ULONG i =; i < pMods->NumberOfModules; i++)
			{
				if (checkPtr >= pMod[i].ImageBase && checkPtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize))
				{
					g_KernelBase = pMod[i].ImageBase;
					g_KernelSize = pMod[i].ImageSize;
					if (pSize)
					{
						*pSize = g_KernelSize;
					}
					break;
				}
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return;
	}
	if (pMods)
	{
		ExFreePoolWithTag(pMods, L"LyShark");
	}
	DbgPrint("KernelBase = > %p \n", g_KernelBase);
	return g_KernelBase;
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint(("Uninstall Driver Is OK \n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint(("hello lyshark.com \n"));
	// 获取内核第一个模块的基地址
	PVOID base = LySharkToolsUtilKernelBase();
	if (!base)
		return STATUS_NOT_FOUND;
	// 得到NT头部PE+结构
	// lyshark.com
	PIMAGE_NT_HEADERS pHdr = RtlImageNtHeader(base);
	if (!pHdr)
		return STATUS_INVALID_IMAGE_FORMAT;
	// 首先寻找代码段
	PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr +);
	for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++)
	{
		ANSI_STRING LySharkSection, LySharkName;
		RtlInitAnsiString(&LySharkSection, ".text");
		RtlInitAnsiString(&LySharkName, (PCCHAR)pSection->Name);
		DbgPrint("[LyShark.PE] 名字: %Z | 地址: %p | 长度: %d \n", LySharkName, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize);
	}
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行这段驱动程序,你会得到当前内核的所有PE节信息,枚举效果如下所示。

既然能够得到PE头部数据了,那么我们只需要扫描这段空间并得到匹配到的数据即可,其实很容易实现,如下代码所示。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "lyshark.h"
// 定义全局变量
static PVOID g_KernelBase =;
static ULONG g_KernelSize =;
// 得到KernelBase基地址
// lyshark.com
PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG bytes =;
	PRTL_PROCESS_MODULES pMods =;
	PVOID checkPtr =;
	UNICODE_STRING routineName;
	if (g_KernelBase !=)
	{
		if (pSize)
		{
			*pSize = g_KernelSize;
		}
		return g_KernelBase;
	}
	RtlInitUnicodeString(&routineName, L"NtOpenFile");
	checkPtr = MmGetSystemRoutineAddress(&routineName);
	if (checkPtr ==)
		return;
	__try
	{
		status = ZwQuerySystemInformation(SystemModuleInformation,, bytes, &bytes);
		if (bytes ==)
		{
			return;
		}
		pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPoolNx, bytes, L"LyShark");
		RtlZeroMemory(pMods, bytes);
		status = ZwQuerySystemInformation(SystemModuleInformation, pMods, bytes, &bytes);
		if (NT_SUCCESS(status))
		{
			PRTL_PROCESS_MODULE_INFORMATION pMod = pMods->Modules;
			for (ULONG i =; i < pMods->NumberOfModules; i++)
			{
				if (checkPtr >= pMod[i].ImageBase && checkPtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize))
				{
					g_KernelBase = pMod[i].ImageBase;
					g_KernelSize = pMod[i].ImageSize;
					if (pSize)
					{
						*pSize = g_KernelSize;
					}
					break;
				}
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return;
	}
	if (pMods)
	{
		ExFreePoolWithTag(pMods, L"LyShark");
	}
	DbgPrint("KernelBase = > %p \n", g_KernelBase);
	return g_KernelBase;
}
// 对指定内存执行特征码扫描
NTSTATUS UtilLySharkSearchPattern(IN PUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound)
{
	NT_ASSERT(ppFound != && pattern != 0 && base != 0);
	if (ppFound == || pattern == 0 || base == 0)
	{
		return STATUS_INVALID_PARAMETER;
	}
	__try
	{
		for (ULONG_PTR i =; i < size - len; i++)
		{
			BOOLEAN found = TRUE;
			for (ULONG_PTR j =; j < len; j++)
			{
				if (pattern[j] != wildcard && pattern[j] != ((PUCHAR)base)[i + j])
				{
					found = FALSE;
					break;
				}
			}
			if (found != FALSE)
			{
				*ppFound = (PUCHAR)base + i;
				DbgPrint("[LyShark] 特征码匹配地址: %p \n", (PUCHAR)base + i);
				return STATUS_SUCCESS;
			}
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return STATUS_UNHANDLED_EXCEPTION;
	}
	return STATUS_NOT_FOUND;
}
// 扫描代码段中的指令片段
NTSTATUS ByLySharkComUtilScanSection(IN PCCHAR section, IN PUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, OUT PVOID* ppFound)
{
	NT_ASSERT(ppFound !=);
	if (ppFound ==)
		return STATUS_INVALID_PARAMETER;
	// 获取内核第一个模块的基地址
	PVOID base = LySharkToolsUtilKernelBase();
	if (!base)
		return STATUS_NOT_FOUND;
	// 得到NT头部PE+结构
	PIMAGE_NT_HEADERS pHdr = RtlImageNtHeader(base);
	if (!pHdr)
		return STATUS_INVALID_IMAGE_FORMAT;
	// 首先寻找代码段
	PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr +);
	for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++)
	{
		ANSI_STRING LySharkSection, LySharkText;
		RtlInitAnsiString(&LySharkSection, section);
		RtlInitAnsiString(&LySharkText, (PCCHAR)pSection->Name);
		// 判断是不是我们要找的.text节
		if (RtlCompareString(&LySharkSection, &LySharkText, TRUE) ==)
		{
			// 如果是则开始匹配特征码
			return UtilLySharkSearchPattern(pattern, wildcard, len, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize, ppFound);
		}
	}
	return STATUS_NOT_FOUND;
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint(("Uninstall Driver Is OK \n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark.com \n");
	PMiProcessLoaderEntry m_MiProcessLoaderEntry = NULL;
	RTL_OSVERSIONINFOW Version = { };
	Version.dwOSVersionInfoSize = sizeof(Version);
	RtlGetVersion(&Version);
	//获取内核版本号
	DbgPrint("主版本: %d -->次版本: %d --> 编译版本: %d", Version.dwMajorVersion, Version.dwMinorVersion, Version.dwBuildNumber);
	if (Version.dwMajorVersion ==)
	{
		// 如果是 win 18363 则匹配特征
		if (Version.dwBuildNumber ==)
		{
			CHAR pattern[] = "\x\x89\x5c\x24\x08";
			int pattern_size = sizeof(pattern) -;
			ByLySharkComUtilScanSection(".text", (PUCHAR)pattern,xCC, pattern_size, (PVOID *)&m_MiProcessLoaderEntry);
			DbgPrint("[LyShark] 输出首地址: %p", m_MiProcessLoaderEntry);
		}
	}
	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

代码中首先判断系统主版本windows 10 18363如果是则执行匹配,只匹配.text也就是代码段中的数据,当遇到0xcc时则取消继续,否则继续执行枚举,程序输出效果如下所示。

在WinDBG中输入命令!dh 0xfffff8007f600000解析出内核PE头数据,可以看到如下所示,对比无误。