内核空间与内核模块
一、内核空间
高2G内存里的内容都是一样的,低2G内存都是各进程的
二、内核模块
每个驱动程序都是一个模块,称为内核模块,都可以加载到内核中,都遵循PE结构,但本质上讲,任意一个.sys文件与内核文件没有区别
1、DRIVER_OBJECT结构体
每个内核模块都有一个对应的结构体,来描述这个模块在内核中:位置、大小、名称等等
0: kd> dt _DRIVER_OBJECT ntdll!_DRIVER_OBJECT +0x000 Type : Int2B +0x002 Size : Int2B +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT +0x008 Flags : Uint4B +0x00c DriverStart : Ptr32 Void //驱动的位置 +0x010 DriverSize : Uint4B //驱动大小 +0x014 DriverSection : Ptr32 Void +0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING //驱动名 +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING +0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH +0x02c DriverInit : Ptr32 long +0x030 DriverStartIo : Ptr32 void +0x034 DriverUnload : Ptr32 void +0x038 MajorFunction : [28] Ptr32 long
咱们可以实验一下打印pDriver的地址在查看其结构,测试代码如下
#include<ntddk.h> VOID DriverUnload(PDRIVER_OBJECT driver) { DbgPrint("驱动停止运行.\r\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) { DbgPrint("My Driver"); DbgPrint("Driver addr:%x", pDriver); pDriver->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
运行驱动后
0: kd> dt _DRIVER_OBJECT 89d1c978 ntdll!_DRIVER_OBJECT +0x000 Type : 0n4 +0x002 Size : 0n168 +0x004 DeviceObject : (null) +0x008 Flags : 0x12 +0x00c DriverStart : 0xf7817000 Void +0x010 DriverSize : 0x6000 +0x014 DriverSection : 0x8996d780 Void +0x018 DriverExtension : 0x89d1ca20 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\KMDFDriver1" +0x024 HardwareDatabase : 0x8069c210 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0xf781b000 long SYMSRV: BYINDEX: 0x5
其中DriverSection是一个指针,指向下一个驱动模块的指针,其相对应的结构体是
_LDR_DATA_TABLE_ENTRY
0: kd> dt _LDR_DATA_TABLE_ENTRY ntdll!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY +0x008 InMemoryOrderLinks : _LIST_ENTRY +0x010 InInitializationOrderLinks : _LIST_ENTRY +0x018 DllBase : Ptr32 Void +0x01c EntryPoint : Ptr32 Void +0x020 SizeOfImage : Uint4B +0x024 FullDllName : _UNICODE_STRING +0x02c BaseDllName : _UNICODE_STRING +0x034 Flags : Uint4B +0x038 LoadCount : Uint2B +0x03a TlsIndex : Uint2B +0x03c HashLinks : _LIST_ENTRY +0x03c SectionPointer : Ptr32 Void +0x040 CheckSum : Uint4B +0x044 TimeDateStamp : Uint4B +0x044 LoadedImports : Ptr32 Void +0x048 EntryPointActivationContext : Ptr32 Void +0x04c PatchInformation : Ptr32 Void
我们查看上一个样例的试试
0: kd> dt _LDR_DATA_TABLE_ENTRY 8996d780 ntdll!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x805644c0 - 0x89c57ae0 ] +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ] +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ] +0x018 DllBase : 0xf7817000 Void +0x01c EntryPoint : 0xf781b000 Void +0x020 SizeOfImage : 0x6000 +0x024 FullDllName : _UNICODE_STRING "\??\C:\Documents and Settings\Administrator\桌面\KMDFDriver1.sys" +0x02c BaseDllName : _UNICODE_STRING "KMDFDriver1.sys" +0x034 Flags : 0x9104000 +0x038 LoadCount : 1 +0x03a TlsIndex : 0x49 +0x03c HashLinks : _LIST_ENTRY [ 0xffffffff - 0xc7af ] +0x03c SectionPointer : 0xffffffff Void +0x040 CheckSum : 0xc7af +0x044 TimeDateStamp : 0xfffffffe +0x044 LoadedImports : 0xfffffffe Void +0x048 EntryPointActivationContext : (null) +0x04c PatchInformation : 0x004d004b Void
指向的是我们运行的驱动程序
DLLBase成员代表我们的内核模块从哪里开始
InLoadOrderLinks可以遍历下一个内核模块
也就是说只要找到这个成员就可以遍历所有的内核模块
三、内核模块链表DriverSection
既然我们DriverSection可以遍历链表,那么我们来尝试一下,代码与实验结果如下
#include<ntddk.h> typedef struct { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; UINT32 SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; UINT32 Flags; UINT16 LoadCount; UINT16 TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; UINT32 CheckSum; UINT32 TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY; VOID DriverUnload(PDRIVER_OBJECT driver) { DbgPrint("驱动停止运行.\r\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) { DbgPrint("My Driver"); DbgPrint("Driver addr:%x", pDriver); pDriver->DriverUnload = DriverUnload; PLDR_DATA_TABLE_ENTRY pdte = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection; PLDR_DATA_TABLE_ENTRY head = pdte; do { PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pdte, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); DbgPrint("DllBase: %p, SizeOfImage: %08X %wZ\n", pdte->DllBase, pdte->SizeOfImage, &(pdte->FullDllName)); pdte = (PLDR_DATA_TABLE_ENTRY)pdte->InLoadOrderLinks.Flink; } while (pdte != head); return STATUS_SUCCESS; }
通过特征码查找函数PspTerminateProcess
#include<ntifs.h> #include<ntddk.h> typedef struct { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; UINT32 SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; UINT32 Flags; UINT16 LoadCount; UINT16 TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; UINT32 CheckSum; UINT32 TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; typedef NTSTATUS(*_PspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode); VOID DriverUnLoad(PDRIVER_OBJECT driver) { DbgPrint("Driver already shut off"); } VOID FindDriver(PDRIVER_OBJECT pDriver,PVOID* KernelBase,PUINT32 uKernelImageSize) { PLDR_DATA_TABLE_ENTRY pldte=(PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection; PLDR_DATA_TABLE_ENTRY head = pldte; UNICODE_STRING usKernelBaseDllName; RtlInitUnicodeString(&usKernelBaseDllName, L"ntoskrnl.exe"); do { if (RtlCompareUnicodeString(&pldte->BaseDllName, &usKernelBaseDllName, TRUE) == 0) { *KernelBase=pldte->DllBase; *uKernelImageSize = pldte->SizeOfImage; return; } pldte=(PLDR_DATA_TABLE_ENTRY)pldte->InLoadOrderLinks.Flink; } while (head != pldte); return; } PVOID MemorySearch(PVOID KernelBase, UINT32 uKernelImageSize, PVOID ByteCode,UINT32 ByteLength) { PVOID cur=KernelBase; while ((UINT32)cur!=(UINT32)KernelBase+uKernelImageSize) { if (RtlCompareMemory(cur, ByteCode, ByteLength) == ByteLength) { __asm int 3; return (PVOID)(((UINT32)cur) - 0x6); } cur = (PVOID)((UINT32)cur+1); } } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING reg_path) { pDriver->DriverUnload = DriverUnLoad; PVOID pKernelBase=NULL; UINT32 uKernelImageSize; UINT32 ByteCode[] = { 0x0124a164, 0x758b0000, 0x44703b08, 0x0db80775, 0xebc00000, 0xbe8d575a, 0x00000248, 0x200147f6, 0x868d1274, 0x00000174 }; _PspTerminateProcess PspTerminateProcess; FindDriver(pDriver, &pKernelBase, &uKernelImageSize); PspTerminateProcess=(_PspTerminateProcess)MemorySearch(pKernelBase, uKernelImageSize, ByteCode, sizeof(ByteCode)); DbgPrint("PspTerminateProcess Addr:%p", PspTerminateProcess); PEPROCESS pE; PsLookupProcessByProcessId((HANDLE)1244, &pE); PspTerminateProcess(pE, 0); DbgPrint("记事本关闭了"); return STATUS_SUCCESS; }
非常感谢hambaga师傅,我的博客都是学着他写的,因为他写的很有调理,所以非常感谢