您现在的位置是:首页 > 编程语言学习 > 其他编程语言 > 文章正文 其他编程语言

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

2022-10-29 10:36:27 其他编程语言

简介为了定位特征的方便我们封装实现了一个可以传入数组实现的SearchSpecialCode定位函数,该定位函数其实还不能算的上简单,本章LyShark将对特...

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

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


  1. #include <ntifs.h> 
  2. #include <ntimage.h> 
  3. typedef struct _KLDR_DATA_TABLE_ENTRY 
  4.     LIST_ENTRY64 InLoadOrderLinks; 
  5.     ULONG64 __Undefined1; 
  6.     ULONG64 __Undefined2; 
  7.     ULONG64 __Undefined3; 
  8.     ULONG64 NonPagedDebugInfo; 
  9.     ULONG64 DllBase; 
  10.     ULONG64 EntryPoint; 
  11.     ULONG SizeOfImage; 
  12.     UNICODE_STRING FullDllName; 
  13.     UNICODE_STRING BaseDllName; 
  14.     ULONG   Flags; 
  15.     USHORT  LoadCount; 
  16.     USHORT  __Undefined5; 
  17.     ULONG64 __Undefined6; 
  18.     ULONG   CheckSum; 
  19.     ULONG   __padding1; 
  20.     ULONG   TimeDateStamp; 
  21.     ULONG   __padding2; 
  22. }KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; 
  23. typedef struct _RTL_PROCESS_MODULE_INFORMATION 
  24.     HANDLE Section; 
  25.     PVOID MappedBase; 
  26.     PVOID ImageBase; 
  27.     ULONG ImageSize; 
  28.     ULONG Flags; 
  29.     USHORT LoadOrderIndex; 
  30.     USHORT InitOrderIndex; 
  31.     USHORT LoadCount; 
  32.     USHORT OffsetToFileName; 
  33.     UCHAR  FullPathName[256]; 
  34. } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 
  35. typedef struct _RTL_PROCESS_MODULES 
  36.     ULONG NumberOfModules; 
  37.     RTL_PROCESS_MODULE_INFORMATION Modules[1]; 
  38. } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 
  39. typedef enum _SYSTEM_INFORMATION_CLASS 
  40.     SystemBasicInformation = 0x0, 
  41.     SystemProcessorInformation = 0x1, 
  42.     SystemPerformanceInformation = 0x2, 
  43.     SystemTimeOfDayInformation = 0x3, 
  44.     SystemPathInformation = 0x4, 
  45.     SystemProcessInformation = 0x5, 
  46.     SystemCallCountInformation = 0x6, 
  47.     SystemDeviceInformation = 0x7, 
  48.     SystemProcessorPerformanceInformation = 0x8, 
  49.     SystemFlagsInformation = 0x9, 
  50.     SystemCallTimeInformation = 0xa, 
  51.     SystemModuleInformation = 0xb, 
  52.     SystemLocksInformation = 0xc, 
  53.     SystemStackTraceInformation = 0xd, 
  54.     SystemPagedPoolInformation = 0xe, 
  55.     SystemNonPagedPoolInformation = 0xf, 
  56.     SystemHandleInformation = 0x10, 
  57.     SystemObjectInformation = 0x11, 
  58.     SystemPageFileInformation = 0x12, 
  59.     SystemVdmInstemulInformation = 0x13, 
  60.     SystemVdmBopInformation = 0x14, 
  61.     SystemFileCacheInformation = 0x15, 
  62.     SystemPoolTagInformation = 0x16, 
  63.     SystemInterruptInformation = 0x17, 
  64.     SystemDpcBehaviorInformation = 0x18, 
  65.     SystemFullMemoryInformation = 0x19, 
  66.     SystemLoadGdiDriverInformation = 0x1a, 
  67.     SystemUnloadGdiDriverInformation = 0x1b, 
  68.     SystemTimeAdjustmentInformation = 0x1c, 
  69.     SystemSummaryMemoryInformation = 0x1d, 
  70.     SystemMirrorMemoryInformation = 0x1e, 
  71.     SystemPerformanceTraceInformation = 0x1f, 
  72.     SystemObsolete0 = 0x20, 
  73.     SystemExceptionInformation = 0x21, 
  74.     SystemCrashDumpStateInformation = 0x22, 
  75.     SystemKernelDebuggerInformation = 0x23, 
  76.     SystemContextSwitchInformation = 0x24, 
  77.     SystemRegistryQuotaInformation = 0x25, 
  78.     SystemExtendServiceTableInformation = 0x26, 
  79.     SystemPrioritySeperation = 0x27, 
  80.     SystemVerifierAddDriverInformation = 0x28, 
  81.     SystemVerifierRemoveDriverInformation = 0x29, 
  82.     SystemProcessorIdleInformation = 0x2a, 
  83.     SystemLegacyDriverInformation = 0x2b, 
  84.     SystemCurrentTimeZoneInformation = 0x2c, 
  85.     SystemLookasideInformation = 0x2d, 
  86.     SystemTimeSlipNotification = 0x2e, 
  87.     SystemSessionCreate = 0x2f, 
  88.     SystemSessionDetach = 0x30, 
  89.     SystemSessionInformation = 0x31, 
  90.     SystemRangeStartInformation = 0x32, 
  91.     SystemVerifierInformation = 0x33, 
  92.     SystemVerifierThunkExtend = 0x34, 
  93.     SystemSessionProcessInformation = 0x35, 
  94.     SystemLoadGdiDriverInSystemSpace = 0x36, 
  95.     SystemNumaProcessorMap = 0x37, 
  96.     SystemPrefetcherInformation = 0x38, 
  97.     SystemExtendedProcessInformation = 0x39, 
  98.     SystemRecommendedSharedDataAlignment = 0x3a, 
  99.     SystemComPlusPackage = 0x3b, 
  100.     SystemNumaAvailableMemory = 0x3c, 
  101.     SystemProcessorPowerInformation = 0x3d, 
  102.     SystemEmulationBasicInformation = 0x3e, 
  103.     SystemEmulationProcessorInformation = 0x3f, 
  104.     SystemExtendedHandleInformation = 0x40, 
  105.     SystemLostDelayedWriteInformation = 0x41, 
  106.     SystemBigPoolInformation = 0x42, 
  107.     SystemSessionPoolTagInformation = 0x43, 
  108.     SystemSessionMappedViewInformation = 0x44, 
  109.     SystemHotpatchInformation = 0x45, 
  110.     SystemObjectSecurityMode = 0x46, 
  111.     SystemWatchdogTimerHandler = 0x47, 
  112.     SystemWatchdogTimerInformation = 0x48, 
  113.     SystemLogicalProcessorInformation = 0x49, 
  114.     SystemWow64SharedInformationObsolete = 0x4a, 
  115.     SystemRegisterFirmwareTableInformationHandler = 0x4b, 
  116.     SystemFirmwareTableInformation = 0x4c, 
  117.     SystemModuleInformationEx = 0x4d, 
  118.     SystemVerifierTriageInformation = 0x4e, 
  119.     SystemSuperfetchInformation = 0x4f, 
  120.     SystemMemoryListInformation = 0x50, 
  121.     SystemFileCacheInformationEx = 0x51, 
  122.     SystemThreadPriorityClientIdInformation = 0x52, 
  123.     SystemProcessorIdleCycleTimeInformation = 0x53, 
  124.     SystemVerifierCancellationInformation = 0x54, 
  125.     SystemProcessorPowerInformationEx = 0x55, 
  126.     SystemRefTraceInformation = 0x56, 
  127.     SystemSpecialPoolInformation = 0x57, 
  128.     SystemProcessIdInformation = 0x58, 
  129.     SystemErrorPortInformation = 0x59, 
  130.     SystemBootEnvironmentInformation = 0x5a, 
  131.     SystemHypervisorInformation = 0x5b, 
  132.     SystemVerifierInformationEx = 0x5c, 
  133.     SystemTimeZoneInformation = 0x5d, 
  134.     SystemImageFileExecutionOptionsInformation = 0x5e, 
  135.     SystemCoverageInformation = 0x5f, 
  136.     SystemPrefetchPatchInformation = 0x60, 
  137.     SystemVerifierFaultsInformation = 0x61, 
  138.     SystemSystemPartitionInformation = 0x62, 
  139.     SystemSystemDiskInformation = 0x63, 
  140.     SystemProcessorPerformanceDistribution = 0x64, 
  141.     SystemNumaProximityNodeInformation = 0x65, 
  142.     SystemDynamicTimeZoneInformation = 0x66, 
  143.     SystemCodeIntegrityInformation = 0x67, 
  144.     SystemProcessorMicrocodeUpdateInformation = 0x68, 
  145.     SystemProcessorBrandString = 0x69, 
  146.     SystemVirtualAddressInformation = 0x6a, 
  147.     SystemLogicalProcessorAndGroupInformation = 0x6b, 
  148.     SystemProcessorCycleTimeInformation = 0x6c, 
  149.     SystemStoreInformation = 0x6d, 
  150.     SystemRegistryAppendString = 0x6e, 
  151.     SystemAitSamplingValue = 0x6f, 
  152.     SystemVhdBootInformation = 0x70, 
  153.     SystemCpuQuotaInformation = 0x71, 
  154.     SystemNativeBasicInformation = 0x72, 
  155.     SystemErrorPortTimeouts = 0x73, 
  156.     SystemLowPriorityIoInformation = 0x74, 
  157.     SystemBootEntropyInformation = 0x75, 
  158.     SystemVerifierCountersInformation = 0x76, 
  159.     SystemPagedPoolInformationEx = 0x77, 
  160.     SystemSystemPtesInformationEx = 0x78, 
  161.     SystemNodeDistanceInformation = 0x79, 
  162.     SystemAcpiAuditInformation = 0x7a, 
  163.     SystemBasicPerformanceInformation = 0x7b, 
  164.     SystemQueryPerformanceCounterInformation = 0x7c, 
  165.     SystemSessionBigPoolInformation = 0x7d, 
  166.     SystemBootGraphicsInformation = 0x7e, 
  167.     SystemScrubPhysicalMemoryInformation = 0x7f, 
  168.     SystemBadPageInformation = 0x80, 
  169.     SystemProcessorProfileControlArea = 0x81, 
  170.     SystemCombinePhysicalMemoryInformation = 0x82, 
  171.     SystemEntropyInterruptTimingInformation = 0x83, 
  172.     SystemConsoleInformation = 0x84, 
  173.     SystemPlatformBinaryInformation = 0x85, 
  174.     SystemThrottleNotificationInformation = 0x86, 
  175.     SystemHypervisorProcessorCountInformation = 0x87, 
  176.     SystemDeviceDataInformation = 0x88, 
  177.     SystemDeviceDataEnumerationInformation = 0x89, 
  178.     SystemMemoryTopologyInformation = 0x8a, 
  179.     SystemMemoryChannelInformation = 0x8b, 
  180.     SystemBootLogoInformation = 0x8c, 
  181.     SystemProcessorPerformanceInformationEx = 0x8d, 
  182.     SystemSpare0 = 0x8e, 
  183.     SystemSecureBootPolicyInformation = 0x8f, 
  184.     SystemPageFileInformationEx = 0x90, 
  185.     SystemSecureBootInformation = 0x91, 
  186.     SystemEntropyInterruptTimingRawInformation = 0x92, 
  187.     SystemPortableWorkspaceEfiLauncherInformation = 0x93, 
  188.     SystemFullProcessInformation = 0x94, 
  189.     SystemKernelDebuggerInformationEx = 0x95, 
  190.     SystemBootMetadataInformation = 0x96, 
  191.     SystemSoftRebootInformation = 0x97, 
  192.     SystemElamCertificateInformation = 0x98, 
  193.     SystemOfflineDumpConfigInformation = 0x99, 
  194.     SystemProcessorFeaturesInformation = 0x9a, 
  195.     SystemRegistryReconciliationInformation = 0x9b, 
  196.     MaxSystemInfoClass = 0x9c, 
  197. } SYSTEM_INFORMATION_CLASS; 
  198. // 声明函数 
  199. // By: Lyshark.com 
  200. NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(_In_ PVOID Base); 
  201. NTSTATUS NTAPI ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); 
  202. typedef VOID(__cdecl *PMiProcessLoaderEntry)(PKLDR_DATA_TABLE_ENTRY section, IN LOGICAL Insert); 
  203. 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变量内。

  1. // 署名权 
  2. // right to sign one's name on a piece of work 
  3. // PowerBy: LyShark 
  4. // Email: me@lyshark.com 
  5. #include "lyshark.h" 
  6. PVOID GetIoInitializeTimerAddress() 
  7.     PVOID VariableAddress = 0; 
  8.     UNICODE_STRING uioiTime = { 0 }; 
  9.     RtlInitUnicodeString(&uioiTime, L"IoInitializeTimer"); 
  10.     VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime); 
  11.     if (VariableAddress != 0) 
  12.     { 
  13.         return VariableAddress; 
  14.     } 
  15.     return 0; 
  16. // 对指定内存执行特征码扫描 
  17. NTSTATUS UtilLySharkSearchPattern(IN PUCHAR pattern, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound) 
  18.     // 计算匹配长度 
  19.     // LyShark.com 特征码扫描 
  20.     NT_ASSERT(ppFound != 0 && pattern != 0 && base != 0); 
  21.     if (ppFound == 0 || pattern == 0 || base == 0) 
  22.     { 
  23.         return STATUS_INVALID_PARAMETER; 
  24.     } 
  25.     __try 
  26.     { 
  27.         for (ULONG_PTR i = 0; i < size - len; i++) 
  28.         { 
  29.             BOOLEAN found = TRUE; 
  30.             for (ULONG_PTR j = 0; j < len; j++) 
  31.             { 
  32.                 if (pattern[j] != ((PUCHAR)base)[i + j]) 
  33.                 { 
  34.                     found = FALSE; 
  35.                     break
  36.                 } 
  37.             } 
  38.             if (found != FALSE) 
  39.             { 
  40.                 *ppFound = (PUCHAR)base + i; 
  41.                 DbgPrint("[LyShark.com] 特征码匹配地址: %p \n", (PUCHAR)base + i); 
  42.                 return STATUS_SUCCESS; 
  43.             } 
  44.         } 
  45.     } 
  46.     __except (EXCEPTION_EXECUTE_HANDLER) 
  47.     { 
  48.         return STATUS_UNHANDLED_EXCEPTION; 
  49.     } 
  50.     return STATUS_NOT_FOUND; 
  51. VOID UnDriver(PDRIVER_OBJECT driver) 
  52.     DbgPrint(("Uninstall Driver Is OK \n")); 
  53. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) 
  54.     DbgPrint(("hello lyshark.com \n")); 
  55.     // 返回匹配长度5 
  56.     CHAR pattern[] = "\x48\x89\x6c\x24\x10"
  57.     PVOID *find_address = NULL; 
  58.     int pattern_size = sizeof(pattern) - 1; 
  59.     DbgPrint("匹配长度: %d \n", pattern_size); 
  60.     // 得到基地址 
  61.     PVOID address = GetIoInitializeTimerAddress(); 
  62.     // 扫描特征 
  63.     NTSTATUS nt = UtilLySharkSearchPattern((PUCHAR)pattern, pattern_size, address, 128, &find_address); 
  64.     DbgPrint("[LyShark 返回地址 => ] 0x%p \n", (ULONG64)find_address); 
  65.     Driver->DriverUnload = UnDriver; 
  66.     return STATUS_SUCCESS; 

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

RtlImageNtHeader对其PE头部解析

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

  1. // 署名权 
  2. // right to sign one's name on a piece of work 
  3. // PowerBy: LyShark 
  4. // Email: me@lyshark.com 
  5. #include "lyshark.h" 
  6. // 定义全局变量 
  7. static PVOID g_KernelBase = 0; 
  8. static ULONG g_KernelSize = 0; 
  9. // 得到KernelBase基地址 
  10. // lyshark.com 
  11. PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize) 
  12.     NTSTATUS status = STATUS_SUCCESS; 
  13.     ULONG bytes = 0; 
  14.     PRTL_PROCESS_MODULES pMods = 0; 
  15.     PVOID checkPtr = 0; 
  16.     UNICODE_STRING routineName; 
  17.     if (g_KernelBase != 0) 
  18.     { 
  19.         if (pSize) 
  20.         { 
  21.             *pSize = g_KernelSize; 
  22.         } 
  23.         return g_KernelBase; 
  24.     } 
  25.     RtlInitUnicodeString(&routineName, L"NtOpenFile"); 
  26.     checkPtr = MmGetSystemRoutineAddress(&routineName); 
  27.     if (checkPtr == 0) 
  28.         return 0; 
  29.     __try 
  30.     { 
  31.         status = ZwQuerySystemInformation(SystemModuleInformation, 0, bytes, &bytes); 
  32.         if (bytes == 0) 
  33.         { 
  34.             return 0; 
  35.         } 
  36.         pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPoolNx, bytes, L"LyShark"); 
  37.         RtlZeroMemory(pMods, bytes); 
  38.         status = ZwQuerySystemInformation(SystemModuleInformation, pMods, bytes, &bytes); 
  39.         if (NT_SUCCESS(status)) 
  40.         { 
  41.             PRTL_PROCESS_MODULE_INFORMATION pMod = pMods->Modules; 
  42.             for (ULONG i = 0; i < pMods->NumberOfModules; i++) 
  43.             { 
  44.                 if (checkPtr >= pMod[i].ImageBase && checkPtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize)) 
  45.                 { 
  46.                     g_KernelBase = pMod[i].ImageBase; 
  47.                     g_KernelSize = pMod[i].ImageSize; 
  48.                     if (pSize) 
  49.                     { 
  50.                         *pSize = g_KernelSize; 
  51.                     } 
  52.                     break
  53.                 } 
  54.             } 
  55.         } 
  56.     } 
  57.     __except (EXCEPTION_EXECUTE_HANDLER) 
  58.     { 
  59.         return 0; 
  60.     } 
  61.     if (pMods) 
  62.     { 
  63.         ExFreePoolWithTag(pMods, L"LyShark"); 
  64.     } 
  65.     DbgPrint("KernelBase = > %p \n", g_KernelBase); 
  66.     return g_KernelBase; 
  67. VOID UnDriver(PDRIVER_OBJECT driver) 
  68.     DbgPrint(("Uninstall Driver Is OK \n")); 
  69. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) 
  70.     DbgPrint(("hello lyshark.com \n")); 
  71.     // 获取内核第一个模块的基地址 
  72.     PVOID base = LySharkToolsUtilKernelBase(0); 
  73.     if (!base) 
  74.         return STATUS_NOT_FOUND; 
  75.     // 得到NT头部PE32+结构 
  76.     // lyshark.com 
  77.     PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader(base); 
  78.     if (!pHdr) 
  79.         return STATUS_INVALID_IMAGE_FORMAT; 
  80.     // 首先寻找代码段 
  81.     PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1); 
  82.     for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++) 
  83.     { 
  84.         ANSI_STRING LySharkSection, LySharkName; 
  85.         RtlInitAnsiString(&LySharkSection, ".text"); 
  86.         RtlInitAnsiString(&LySharkName, (PCCHAR)pSection->Name); 
  87.         DbgPrint("[LyShark.PE] 名字: %Z | 地址: %p | 长度: %d \n", LySharkName, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize); 
  88.     } 
  89.     Driver->DriverUnload = UnDriver; 
  90.     return STATUS_SUCCESS; 

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

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

  1. // 署名权 
  2. // right to sign one's name on a piece of work 
  3. // PowerBy: LyShark 
  4. // Email: me@lyshark.com 
  5. #include "lyshark.h" 
  6. // 定义全局变量 
  7. static PVOID g_KernelBase = 0; 
  8. static ULONG g_KernelSize = 0; 
  9. // 得到KernelBase基地址 
  10. // lyshark.com 
  11. PVOID LySharkToolsUtilKernelBase(OUT PULONG pSize) 
  12.     NTSTATUS status = STATUS_SUCCESS; 
  13.     ULONG bytes = 0; 
  14.     PRTL_PROCESS_MODULES pMods = 0; 
  15.     PVOID checkPtr = 0; 
  16.     UNICODE_STRING routineName; 
  17.     if (g_KernelBase != 0) 
  18.     { 
  19.         if (pSize) 
  20.         { 
  21.             *pSize = g_KernelSize; 
  22.         } 
  23.         return g_KernelBase; 
  24.     } 
  25.     RtlInitUnicodeString(&routineName, L"NtOpenFile"); 
  26.     checkPtr = MmGetSystemRoutineAddress(&routineName); 
  27.     if (checkPtr == 0) 
  28.         return 0; 
  29.     __try 
  30.     { 
  31.         status = ZwQuerySystemInformation(SystemModuleInformation, 0, bytes, &bytes); 
  32.         if (bytes == 0) 
  33.         { 
  34.             return 0; 
  35.         } 
  36.         pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPoolNx, bytes, L"LyShark"); 
  37.         RtlZeroMemory(pMods, bytes); 
  38.         status = ZwQuerySystemInformation(SystemModuleInformation, pMods, bytes, &bytes); 
  39.         if (NT_SUCCESS(status)) 
  40.         { 
  41.             PRTL_PROCESS_MODULE_INFORMATION pMod = pMods->Modules; 
  42.             for (ULONG i = 0; i < pMods->NumberOfModules; i++) 
  43.             { 
  44.                 if (checkPtr >= pMod[i].ImageBase && checkPtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize)) 
  45.                 { 
  46.                     g_KernelBase = pMod[i].ImageBase; 
  47.                     g_KernelSize = pMod[i].ImageSize; 
  48.                     if (pSize) 
  49.                     { 
  50.                         *pSize = g_KernelSize; 
  51.                     } 
  52.                     break
  53.                 } 
  54.             } 
  55.         } 
  56.     } 
  57.     __except (EXCEPTION_EXECUTE_HANDLER) 
  58.     { 
  59.         return 0; 
  60.     } 
  61.     if (pMods) 
  62.     { 
  63.         ExFreePoolWithTag(pMods, L"LyShark"); 
  64.     } 
  65.     DbgPrint("KernelBase = > %p \n", g_KernelBase); 
  66.     return g_KernelBase; 
  67. // 对指定内存执行特征码扫描 
  68. NTSTATUS UtilLySharkSearchPattern(IN PUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound) 
  69.     NT_ASSERT(ppFound != 0 && pattern != 0 && base != 0); 
  70.     if (ppFound == 0 || pattern == 0 || base == 0) 
  71.     { 
  72.         return STATUS_INVALID_PARAMETER; 
  73.     } 
  74.     __try 
  75.     { 
  76.         for (ULONG_PTR i = 0; i < size - len; i++) 
  77.         { 
  78.             BOOLEAN found = TRUE; 
  79.             for (ULONG_PTR j = 0; j < len; j++) 
  80.             { 
  81.                 if (pattern[j] != wildcard && pattern[j] != ((PUCHAR)base)[i + j]) 
  82.                 { 
  83.                     found = FALSE; 
  84.                     break
  85.                 } 
  86.             } 
  87.             if (found != FALSE) 
  88.             { 
  89.                 *ppFound = (PUCHAR)base + i; 
  90.                 DbgPrint("[LyShark] 特征码匹配地址: %p \n", (PUCHAR)base + i); 
  91.                 return STATUS_SUCCESS; 
  92.             } 
  93.         } 
  94.     } 
  95.     __except (EXCEPTION_EXECUTE_HANDLER) 
  96.     { 
  97.         return STATUS_UNHANDLED_EXCEPTION; 
  98.     } 
  99.     return STATUS_NOT_FOUND; 
  100. // 扫描代码段中的指令片段 
  101. NTSTATUS ByLySharkComUtilScanSection(IN PCCHAR section, IN PUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, OUT PVOID* ppFound) 
  102.     NT_ASSERT(ppFound != 0); 
  103.     if (ppFound == 0) 
  104.         return STATUS_INVALID_PARAMETER; 
  105.     // 获取内核第一个模块的基地址 
  106.     PVOID base = LySharkToolsUtilKernelBase(0); 
  107.     if (!base) 
  108.         return STATUS_NOT_FOUND; 
  109.     // 得到NT头部PE32+结构 
  110.     PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader(base); 
  111.     if (!pHdr) 
  112.         return STATUS_INVALID_IMAGE_FORMAT; 
  113.     // 首先寻找代码段 
  114.     PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1); 
  115.     for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++) 
  116.     { 
  117.         ANSI_STRING LySharkSection, LySharkText; 
  118.         RtlInitAnsiString(&LySharkSection, section); 
  119.         RtlInitAnsiString(&LySharkText, (PCCHAR)pSection->Name); 
  120.         // 判断是不是我们要找的.text节 
  121.         if (RtlCompareString(&LySharkSection, &LySharkText, TRUE) == 0) 
  122.         { 
  123.             // 如果是则开始匹配特征码 
  124.             return UtilLySharkSearchPattern(pattern, wildcard, len, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize, ppFound); 
  125.         } 
  126.     } 
  127.     return STATUS_NOT_FOUND; 
  128. VOID UnDriver(PDRIVER_OBJECT driver) 
  129.     DbgPrint(("Uninstall Driver Is OK \n")); 
  130. NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) 
  131.     DbgPrint("hello lyshark.com \n"); 
  132.     PMiProcessLoaderEntry m_MiProcessLoaderEntry = NULL; 
  133.     RTL_OSVERSIONINFOW Version = { 0 }; 
  134.     Version.dwOSVersionInfoSize = sizeof(Version); 
  135.     RtlGetVersion(&Version); 
  136.     //获取内核版本号 
  137.     DbgPrint("主版本: %d -->次版本: %d --> 编译版本: %d", Version.dwMajorVersion, Version.dwMinorVersion, Version.dwBuildNumber); 
  138.     if (Version.dwMajorVersion == 10) 
  139.     { 
  140.         // 如果是 win10 18363 则匹配特征 
  141.         if (Version.dwBuildNumber == 18363) 
  142.         { 
  143.             CHAR pattern[] = "\x48\x89\x5c\x24\x08"
  144.             int pattern_size = sizeof(pattern) - 1; 
  145.             ByLySharkComUtilScanSection(".text", (PUCHAR)pattern, 0xCC, pattern_size, (PVOID *)&m_MiProcessLoaderEntry); 
  146.             DbgPrint("[LyShark] 输出首地址: %p", m_MiProcessLoaderEntry); 
  147.         } 
  148.     } 
  149.     Driver->DriverUnload = UnDriver; 
  150.     return STATUS_SUCCESS; 

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

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

相关文章

站点信息