驅動開發:內核特征碼掃描PE代碼段

来源:https://www.cnblogs.com/LyShark/archive/2022/10/18/16802659.html
-Advertisement-
Play Games

在筆者上一篇文章`《驅動開發:內核特征碼搜索函數封裝》`中為了定位特征的方便我們封裝實現了一個可以傳入數組實現的`SearchSpecialCode`定位函數,該定位函數其實還不能算的上簡單,本章`LyShark`將對特征碼定位進行簡化,讓定位變得更簡單,並運用定位代碼實現掃描內核PE的`.text... ...


在筆者上一篇文章《驅動開發:內核特征碼搜索函數封裝》中為了定位特征的方便我們封裝實現了一個可以傳入數組實現的SearchSpecialCode定位函數,該定位函數其實還不能算的上簡單,本章LyShark將對特征碼定位進行簡化,讓定位變得更簡單,並運用定位代碼實現掃描內核PE的.text代碼段,並從代碼段中得到某個特征所在記憶體位置。

老樣子為了後續教程能夠繼續,先來定義一個lyshark.h頭文件,該頭文件中包含了我們本篇文章所必須要使用到的結構體定義,這些定義的函數如果不懂請去看LyShark以前的文章,這裡就不羅嗦了。

#include <ntifs.h>
#include <ntimage.h>

typedef struct _KLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY64 InLoadOrderLinks;
	ULONG64 __Undefined1;
	ULONG64 __Undefined2;
	ULONG64 __Undefined3;
	ULONG64 NonPagedDebugInfo;
	ULONG64 DllBase;
	ULONG64 EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG   Flags;
	USHORT  LoadCount;
	USHORT  __Undefined5;
	ULONG64 __Undefined6;
	ULONG   CheckSum;
	ULONG   __padding1;
	ULONG   TimeDateStamp;
	ULONG   __padding2;
}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[256];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES
{
	ULONG NumberOfModules;
	RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;

typedef enum _SYSTEM_INFORMATION_CLASS
{
	SystemBasicInformation = 0x0,
	SystemProcessorInformation = 0x1,
	SystemPerformanceInformation = 0x2,
	SystemTimeOfDayInformation = 0x3,
	SystemPathInformation = 0x4,
	SystemProcessInformation = 0x5,
	SystemCallCountInformation = 0x6,
	SystemDeviceInformation = 0x7,
	SystemProcessorPerformanceInformation = 0x8,
	SystemFlagsInformation = 0x9,
	SystemCallTimeInformation = 0xa,
	SystemModuleInformation = 0xb,
	SystemLocksInformation = 0xc,
	SystemStackTraceInformation = 0xd,
	SystemPagedPoolInformation = 0xe,
	SystemNonPagedPoolInformation = 0xf,
	SystemHandleInformation = 0x10,
	SystemObjectInformation = 0x11,
	SystemPageFileInformation = 0x12,
	SystemVdmInstemulInformation = 0x13,
	SystemVdmBopInformation = 0x14,
	SystemFileCacheInformation = 0x15,
	SystemPoolTagInformation = 0x16,
	SystemInterruptInformation = 0x17,
	SystemDpcBehaviorInformation = 0x18,
	SystemFullMemoryInformation = 0x19,
	SystemLoadGdiDriverInformation = 0x1a,
	SystemUnloadGdiDriverInformation = 0x1b,
	SystemTimeAdjustmentInformation = 0x1c,
	SystemSummaryMemoryInformation = 0x1d,
	SystemMirrorMemoryInformation = 0x1e,
	SystemPerformanceTraceInformation = 0x1f,
	SystemObsolete0 = 0x20,
	SystemExceptionInformation = 0x21,
	SystemCrashDumpStateInformation = 0x22,
	SystemKernelDebuggerInformation = 0x23,
	SystemContextSwitchInformation = 0x24,
	SystemRegistryQuotaInformation = 0x25,
	SystemExtendServiceTableInformation = 0x26,
	SystemPrioritySeperation = 0x27,
	SystemVerifierAddDriverInformation = 0x28,
	SystemVerifierRemoveDriverInformation = 0x29,
	SystemProcessorIdleInformation = 0x2a,
	SystemLegacyDriverInformation = 0x2b,
	SystemCurrentTimeZoneInformation = 0x2c,
	SystemLookasideInformation = 0x2d,
	SystemTimeSlipNotification = 0x2e,
	SystemSessionCreate = 0x2f,
	SystemSessionDetach = 0x30,
	SystemSessionInformation = 0x31,
	SystemRangeStartInformation = 0x32,
	SystemVerifierInformation = 0x33,
	SystemVerifierThunkExtend = 0x34,
	SystemSessionProcessInformation = 0x35,
	SystemLoadGdiDriverInSystemSpace = 0x36,
	SystemNumaProcessorMap = 0x37,
	SystemPrefetcherInformation = 0x38,
	SystemExtendedProcessInformation = 0x39,
	SystemRecommendedSharedDataAlignment = 0x3a,
	SystemComPlusPackage = 0x3b,
	SystemNumaAvailableMemory = 0x3c,
	SystemProcessorPowerInformation = 0x3d,
	SystemEmulationBasicInformation = 0x3e,
	SystemEmulationProcessorInformation = 0x3f,
	SystemExtendedHandleInformation = 0x40,
	SystemLostDelayedWriteInformation = 0x41,
	SystemBigPoolInformation = 0x42,
	SystemSessionPoolTagInformation = 0x43,
	SystemSessionMappedViewInformation = 0x44,
	SystemHotpatchInformation = 0x45,
	SystemObjectSecurityMode = 0x46,
	SystemWatchdogTimerHandler = 0x47,
	SystemWatchdogTimerInformation = 0x48,
	SystemLogicalProcessorInformation = 0x49,
	SystemWow64SharedInformationObsolete = 0x4a,
	SystemRegisterFirmwareTableInformationHandler = 0x4b,
	SystemFirmwareTableInformation = 0x4c,
	SystemModuleInformationEx = 0x4d,
	SystemVerifierTriageInformation = 0x4e,
	SystemSuperfetchInformation = 0x4f,
	SystemMemoryListInformation = 0x50,
	SystemFileCacheInformationEx = 0x51,
	SystemThreadPriorityClientIdInformation = 0x52,
	SystemProcessorIdleCycleTimeInformation = 0x53,
	SystemVerifierCancellationInformation = 0x54,
	SystemProcessorPowerInformationEx = 0x55,
	SystemRefTraceInformation = 0x56,
	SystemSpecialPoolInformation = 0x57,
	SystemProcessIdInformation = 0x58,
	SystemErrorPortInformation = 0x59,
	SystemBootEnvironmentInformation = 0x5a,
	SystemHypervisorInformation = 0x5b,
	SystemVerifierInformationEx = 0x5c,
	SystemTimeZoneInformation = 0x5d,
	SystemImageFileExecutionOptionsInformation = 0x5e,
	SystemCoverageInformation = 0x5f,
	SystemPrefetchPatchInformation = 0x60,
	SystemVerifierFaultsInformation = 0x61,
	SystemSystemPartitionInformation = 0x62,
	SystemSystemDiskInformation = 0x63,
	SystemProcessorPerformanceDistribution = 0x64,
	SystemNumaProximityNodeInformation = 0x65,
	SystemDynamicTimeZoneInformation = 0x66,
	SystemCodeIntegrityInformation = 0x67,
	SystemProcessorMicrocodeUpdateInformation = 0x68,
	SystemProcessorBrandString = 0x69,
	SystemVirtualAddressInformation = 0x6a,
	SystemLogicalProcessorAndGroupInformation = 0x6b,
	SystemProcessorCycleTimeInformation = 0x6c,
	SystemStoreInformation = 0x6d,
	SystemRegistryAppendString = 0x6e,
	SystemAitSamplingValue = 0x6f,
	SystemVhdBootInformation = 0x70,
	SystemCpuQuotaInformation = 0x71,
	SystemNativeBasicInformation = 0x72,
	SystemErrorPortTimeouts = 0x73,
	SystemLowPriorityIoInformation = 0x74,
	SystemBootEntropyInformation = 0x75,
	SystemVerifierCountersInformation = 0x76,
	SystemPagedPoolInformationEx = 0x77,
	SystemSystemPtesInformationEx = 0x78,
	SystemNodeDistanceInformation = 0x79,
	SystemAcpiAuditInformation = 0x7a,
	SystemBasicPerformanceInformation = 0x7b,
	SystemQueryPerformanceCounterInformation = 0x7c,
	SystemSessionBigPoolInformation = 0x7d,
	SystemBootGraphicsInformation = 0x7e,
	SystemScrubPhysicalMemoryInformation = 0x7f,
	SystemBadPageInformation = 0x80,
	SystemProcessorProfileControlArea = 0x81,
	SystemCombinePhysicalMemoryInformation = 0x82,
	SystemEntropyInterruptTimingInformation = 0x83,
	SystemConsoleInformation = 0x84,
	SystemPlatformBinaryInformation = 0x85,
	SystemThrottleNotificationInformation = 0x86,
	SystemHypervisorProcessorCountInformation = 0x87,
	SystemDeviceDataInformation = 0x88,
	SystemDeviceDataEnumerationInformation = 0x89,
	SystemMemoryTopologyInformation = 0x8a,
	SystemMemoryChannelInformation = 0x8b,
	SystemBootLogoInformation = 0x8c,
	SystemProcessorPerformanceInformationEx = 0x8d,
	SystemSpare0 = 0x8e,
	SystemSecureBootPolicyInformation = 0x8f,
	SystemPageFileInformationEx = 0x90,
	SystemSecureBootInformation = 0x91,
	SystemEntropyInterruptTimingRawInformation = 0x92,
	SystemPortableWorkspaceEfiLauncherInformation = 0x93,
	SystemFullProcessInformation = 0x94,
	SystemKernelDebuggerInformationEx = 0x95,
	SystemBootMetadataInformation = 0x96,
	SystemSoftRebootInformation = 0x97,
	SystemElamCertificateInformation = 0x98,
	SystemOfflineDumpConfigInformation = 0x99,
	SystemProcessorFeaturesInformation = 0x9a,
	SystemRegistryReconciliationInformation = 0x9b,
	MaxSystemInfoClass = 0x9c,
} 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 代表掃描到首地址以後返回的記憶體地址

這段代碼該如何使用,如下我們以定位IoInitializeTimer為例,演示UtilLySharkSearchPattern如何定位特征的,如下代碼pattern變數中就是我們需要定位的特征值,pattern_size則是需要定位的特征碼長度,在address地址位置向下掃描128位元組,找到則返回到find_address變數內。

// 署名
// PowerBy: LyShark
// Email: [email protected]
#include "lyshark.h"

PVOID GetIoInitializeTimerAddress()
{
	PVOID VariableAddress = 0;
	UNICODE_STRING uioiTime = { 0 };

	RtlInitUnicodeString(&uioiTime, L"IoInitializeTimer");
	VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime);
	if (VariableAddress != 0)
	{
		return VariableAddress;
	}
	return 0;
}

// 對指定記憶體執行特征碼掃描
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 != 0 && pattern != 0 && base != 0);
	if (ppFound == 0 || pattern == 0 || base == 0)
	{
		return STATUS_INVALID_PARAMETER;
	}

	__try
	{
		for (ULONG_PTR i = 0; i < size - len; i++)
		{
			BOOLEAN found = TRUE;
			for (ULONG_PTR j = 0; 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"));

	// 返回匹配長度5
	CHAR pattern[] = "\x48\x89\x6c\x24\x10";
	PVOID *find_address = NULL;

	int pattern_size = sizeof(pattern) - 1;
	DbgPrint("匹配長度: %d \n", pattern_size);

	// 得到基地址
	PVOID address = GetIoInitializeTimerAddress();

	// 掃描特征
	NTSTATUS nt = UtilLySharkSearchPattern((PUCHAR)pattern, pattern_size, address, 128, &find_address);

	DbgPrint("[LyShark 返回地址 => ] 0x%p \n", (ULONG64)find_address);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

運行驅動程式完成特征定位,並對比定位效果。

如上述所示定位函數我們已經封裝好了,相信你也能感受到這種方式要比使用數組更方便,為了能定位到內核PE結構我們需要使用RtlImageNtHeader來解析,這個內核函數專門用來得到內核程式的PE頭部結構的,在下方案例中首先我們使用封裝過的LySharkToolsUtilKernelBase函數拿到內核基址,如果你不懂函數實現細節請閱讀《驅動開發:內核取ntoskrnl模塊基地址》這篇文章,拿到基址以後可以直接使用RtlImageNtHeader對其PE頭部進行解析,如下所示。

// 署名
// PowerBy: LyShark
// Email: [email protected]
#include "lyshark.h"

// 定義全局變數
static PVOID g_KernelBase = 0;
static ULONG g_KernelSize = 0;

// 得到KernelBase基地址
// lyshark.com
PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG bytes = 0;
	PRTL_PROCESS_MODULES pMods = 0;
	PVOID checkPtr = 0;
	UNICODE_STRING routineName;

	if (g_KernelBase != 0)
	{
		if (pSize)
		{
			*pSize = g_KernelSize;
		}
		return g_KernelBase;
	}

	RtlInitUnicodeString(&routineName, L"NtOpenFile");

	checkPtr = MmGetSystemRoutineAddress(&routineName);
	if (checkPtr == 0)
		return 0;

	__try
	{
		status = ZwQuerySystemInformation(SystemModuleInformation, 0, bytes, &bytes);
		if (bytes == 0)
		{
			return 0;
		}

		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 = 0; 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 0;
	}

	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(0);
	if (!base)
		return STATUS_NOT_FOUND;

	// 得到NT頭部PE32+結構
	// lyshark.com
	PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader(base);
	if (!pHdr)
		return STATUS_INVALID_IMAGE_FORMAT;

	// 首先尋找代碼段
	PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1);
	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頭部數據了,那麼我們只需要掃描這段空間並得到匹配到的數據即可,其實很容易實現,如下代碼所示。

// 署名
// PowerBy: LyShark
// Email: [email protected]
#include "lyshark.h"

// 定義全局變數
static PVOID g_KernelBase = 0;
static ULONG g_KernelSize = 0;

// 得到KernelBase基地址
// lyshark.com
PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG bytes = 0;
	PRTL_PROCESS_MODULES pMods = 0;
	PVOID checkPtr = 0;
	UNICODE_STRING routineName;

	if (g_KernelBase != 0)
	{
		if (pSize)
		{
			*pSize = g_KernelSize;
		}
		return g_KernelBase;
	}

	RtlInitUnicodeString(&routineName, L"NtOpenFile");

	checkPtr = MmGetSystemRoutineAddress(&routineName);
	if (checkPtr == 0)
		return 0;

	__try
	{
		status = ZwQuerySystemInformation(SystemModuleInformation, 0, bytes, &bytes);
		if (bytes == 0)
		{
			return 0;
		}

		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 = 0; 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 0;
	}

	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 != 0 && pattern != 0 && base != 0);
	if (ppFound == 0 || pattern == 0 || base == 0)
	{
		return STATUS_INVALID_PARAMETER;
	}

	__try
	{
		for (ULONG_PTR i = 0; i < size - len; i++)
		{
			BOOLEAN found = TRUE;
			for (ULONG_PTR j = 0; 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 != 0);
	if (ppFound == 0)
		return STATUS_INVALID_PARAMETER;

	// 獲取內核第一個模塊的基地址
	PVOID base = LySharkToolsUtilKernelBase(0);
	if (!base)
		return STATUS_NOT_FOUND;

	// 得到NT頭部PE32+結構
	PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader(base);
	if (!pHdr)
		return STATUS_INVALID_IMAGE_FORMAT;

	// 首先尋找代碼段
	PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1);
	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) == 0)
		{
			// 如果是則開始匹配特征碼
			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 = { 0 };

	Version.dwOSVersionInfoSize = sizeof(Version);
	RtlGetVersion(&Version);

	//獲取內核版本號
	DbgPrint("主版本: %d -->次版本: %d --> 編譯版本: %d", Version.dwMajorVersion, Version.dwMinorVersion, Version.dwBuildNumber);

	if (Version.dwMajorVersion == 10)
	{
		// 如果是 win10 18363 則匹配特征
		if (Version.dwBuildNumber == 18363)
		{
			CHAR pattern[] = "\x48\x89\x5c\x24\x08";
			int pattern_size = sizeof(pattern) - 1;

			ByLySharkComUtilScanSection(".text", (PUCHAR)pattern, 0xCC, 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頭數據,可以看到如下所示,對比無誤。

文章作者:lyshark (王瑞)
文章出處:https://www.cnblogs.com/LyShark/p/16802659.html
版權聲明:本博客文章與代碼均為學習時整理的筆記,文章 [均為原創] 作品,轉載請 [添加出處] ,您添加出處是我創作的動力!

轉載文章請遵守《中華人民共和國著作權法》相關法律規定或遵守《署名CC BY-ND 4.0國際》規範,合理合規攜帶原創出處轉載,如果不攜帶文章出處,並惡意轉載多篇原創文章被本人發現,本人保留起訴權!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、print() print()函數的作用是輸出數據到控制台,就是列印在你能看到的界面上。 2、return return語句[表達式]退出函數,選擇性地向調用方返回一個表達式。不帶參數值的return語句返回None。 return作為腳本單獨運行時則需要print函數才能顯示,但是在交互模式下 ...
  • 使用這種分頁方式,好像是比jpa或者MyBatis自帶的分頁工具有更好的性能和安全性。 需要接收的參數 public ApiResponse getBlackList( @RequestParam(name = "pageSize", required = false) Integer pageSi ...
  • R語言之旅。原書P88頁案例3-3解答。根據描述統計量有什麼見解、本國學生和國外學生學費差別、工作經驗要求與否與起薪差別、英語測試要求與否與起薪差別、起薪與學費關係。 ...
  • 1、五大基本數據類型和操作 1.1 字元串-string | 命令 | 說明 | | | | | set key value | 如果key還沒有,那就可以添加,如果key已經存在了,那會覆蓋原有key的值 | | get key | 如果key還沒有,獲取為(nil),代表key沒有被使用,如果k ...
  • 自動生成路由 普通cbv視圖形式的路由: path('books4/', views.Book4View.as_view()), re_path('books4/(?P<pk>\d+)', views.Book4DetailView.as_view()) 繼承了ViewSetMixin及其子類的視圖 ...
  • 前言 嗨嘍,大家好呀~這裡是愛看美女的茜茜吶 又到了學Python時刻~ 在面對想聽的歌沒得權時,正常人一般的操作是百度一下又或者直接找朋友借 但是程式員就不一樣了~直接展示一手如何用Python 實現通過輸入歌手名或歌名一秒下載 ~ 第三方庫: requests >>> pip install r ...
  • 什麼是MQ? 【1】MQ:MessageQueue,消息隊列。 隊列,是一種FIFO 先進先出的數據結構。消息由生產者發送到MQ進行排隊,然後按原來的順序交由消息的消費者進行處理。QQ和微信就是典型的MQ。 為什麼要用MQ(MQ的優點)? MQ的作用主要有以下三個方面: 【1】非同步 例子:快遞員發快 ...
  • 網上有很多可以自行查詢; 1、狂神的RedisUtil 點擊查看代碼 //在我們真實的開發中,或者在公司,一般都可以看到一個公司自己封裝的Utils工具~~ @Component public class RedisUtil { @Autowired //@Qualifier("myRedisTem ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...