拉不拉稀肚拉稀 发表于 2022-10-18 18:29:59

驱动开发:内核特征码扫描PE代码段

在笔者上一篇文章《驱动开发:内核特征码搜索函数封装》中为了定位特征的方便我们封装实现了一个可以传入数组实现的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;
        USHORTLoadCount;
        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;
        UCHARFullPathName;
} 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 = 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: me@lyshark.com
#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 != ((PUCHAR)base))
                                {
                                        found = FALSE;
                                        break;
                                }
                        }

                        if (found != FALSE)
                        {
                                *ppFound = (PUCHAR)base + i;
                                DbgPrint(" 特征码匹配地址: %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(" 0x%p \n", (ULONG64)find_address);

        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
}运行驱动程序完成特征定位,并对比定位效果。
https://img2022.cnblogs.com/blog/1379525/202210/1379525-20221018160157493-807086585.png
如上述所示定位函数我们已经封装好了,相信你也能感受到这种方式要比使用数组更方便,为了能定位到内核PE结构我们需要使用RtlImageNtHeader来解析,这个内核函数专门用来得到内核程序的PE头部结构的,在下方案例中首先我们使用封装过的LySharkToolsUtilKernelBase函数拿到内核基址,如果你不懂函数实现细节请阅读《驱动开发:内核取ntoskrnl模块基地址》这篇文章,拿到基址以后可以直接使用RtlImageNtHeader对其PE头部进行解析,如下所示。
// 署名
// PowerBy: LyShark
// Email: me@lyshark.com
#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.ImageBase && checkPtr < (PVOID)((PUCHAR)pMod.ImageBase + pMod.ImageSize))
                                {
                                        g_KernelBase = pMod.ImageBase;
                                        g_KernelSize = pMod.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(" 名字: %Z | 地址: %p | 长度: %d \n", LySharkName, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize);
        }

        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
}运行这段驱动程序,你会得到当前内核的所有PE节信息,枚举效果如下所示。
https://img2022.cnblogs.com/blog/1379525/202210/1379525-20221018163025024-25786436.png
既然能够得到PE头部数据了,那么我们只需要扫描这段空间并得到匹配到的数据即可,其实很容易实现,如下代码所示。
// 署名
// PowerBy: LyShark
// Email: me@lyshark.com
#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.ImageBase && checkPtr < (PVOID)((PUCHAR)pMod.ImageBase + pMod.ImageSize))
                                {
                                        g_KernelBase = pMod.ImageBase;
                                        g_KernelSize = pMod.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 != wildcard && pattern != ((PUCHAR)base))
                                {
                                        found = FALSE;
                                        break;
                                }
                        }

                        if (found != FALSE)
                        {
                                *ppFound = (PUCHAR)base + i;
                                DbgPrint(" 特征码匹配地址: %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(" 输出首地址: %p", m_MiProcessLoaderEntry);
                }
        }

        Driver->DriverUnload = UnDriver;
        return STATUS_SUCCESS;
}代码中首先判断系统主版本windows 10 18363如果是则执行匹配,只匹配.text也就是代码段中的数据,当遇到0xcc时则取消继续,否则继续执行枚举,程序输出效果如下所示。
https://img2022.cnblogs.com/blog/1379525/202210/1379525-20221018164351415-998536488.png
在WinDBG中输入命令!dh 0xfffff8007f600000解析出内核PE头数据,可以看到如下所示,对比无误。
https://img2022.cnblogs.com/blog/1379525/202210/1379525-20221018165733008-190958541.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 驱动开发:内核特征码扫描PE代码段