驱动-内核空间与内核模块

admin 2024年2月15日11:11:46评论6 views字数 10581阅读35分16秒阅读模式

在经过前两张学习,已经掌握了最基本的如何编写一个内核程序。那么什么是内核程序呢?

  • 从运行方式上说:

内核程序运行在高2G内存中,与DLL、EXE一样,都是一个PE文件结构,不过他的后缀是.sys,同时不能与EXE一样,直接双击运行,反倒是和DLL类似,需要借助一些接口,将内核程序贴到高2G空间中。

  • 从代码上来看:

DLL的程序入口是DllMain,而EXE的入口点为main,那么sys的入口呢?sys的内存程序,入口为:DriverEntry,卸载内核的函数名:DriverUnload

DRIVER_OBJECT

在了解了内核模块与其他PE的模块区别之后,我们再来了解DRIVER_OBJECT结构体。

这个结构体是我们每个内核模块自己的一个结构体,该结构体记录描述了这个模块在内核中的位置、大小、名称等等。

#include <ntddk.h>

void DriverUnload(PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("pDriverObject: %pn", pDriverObject);
DbgPrint("pRegPath: %pn", pRegPath);
NTSTATUS status = STATUS_SUCCESS;


pDriverObject->DriverUnload = DriverUnload;

return status;
}

void DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("[MyDriver] DriverUnloadn");

return;
}

该结构体是我们创建内核程序需要传入的两个参数之一。

  • DRIVER_OBJECT:

typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
PFAST_IO_DISPATCH FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;

这样并不直观,我们在windbg上查看一下:

先编写上述程序,将我们的驱动程序运行之后,打印pDriverObject地址

驱动-内核空间与内核模块

在windbg上查看一下:

kd> dt _DRIVER_OBJECT 0x81CD4880
ntdll!_DRIVER_OBJECT
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : (null)
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf88a0000 Void
+0x010 DriverSize : 0x6000
+0x014 DriverSection : 0x81cde418 Void
+0x018 DriverExtension : 0x81cd4928 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "DriverMyDriver2"
+0x024 HardwareDatabase : 0x80691b90 _UNICODE_STRING "REGISTRYMACHINEHARDWAREDESCRIPTIONSYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf88a4000 long MyDriver2!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0xf88a1040 void MyDriver2!DriverUnload+0
+0x038 MajorFunction : [28] 0x804fe101 long nt!IopInvalidDeviceRequest+0

其中:

  • DriverStart:驱动开始的地方

  • DriverSize:驱动大小

  • DriverName:驱动名称

  • DriverSection:存储目前所有已加载的驱动程序信息相关的LDR_DATA_TABLE_ENTRY结构体,并且该结构是一个双向链表,通过这个可以访问所有的

这里在介绍一下什么是LDR_DATA_TABLE_ENTRY

  • LDR_DATA_TABLE_ENTRY:是一个数据结构,表示所有已经加载的模块信息

typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
// 其他字段...
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

其中比较重要的信息有:

  • DllBase:模块的基址

  • EntryPoint:模块的入口点

  • SizeOfImage:模块的大小

  • FullDllName:完整的路径名称

  • BaseDllName:模块的基本文件名

也就是说,我们可以遍历该结构,访问到所有加载的模块。

LDR_DATA_TABLE_ENTRY

InLoadOrderLinks

在这里我们在介绍一下InLoadOrderLinks ,首先InMemoryOrderLinks、InInitializationOrderLinks在0环中没啥用。

根据上文可知:InLoadOrderLinks 是LIST_ENTRY类型。

我们可以通过他来串联所有已经加载的模块。

  • InLoadOrderLinks结构:

typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
  • Flink: Forward Link,指向链表中下一个元素的指针。

  • Blink: Backward Link,指向链表中上一个元素的指针。

我们来访问一下该数据结构:

驱动-内核空间与内核模块

kd> dt _DRIVER_OBJECT 0x81CD4880
ntdll!_DRIVER_OBJECT
+0x000 Type : 0n4
+0x002 Size : 0n168
+0x004 DeviceObject : (null)
+0x008 Flags : 0x12
+0x00c DriverStart : 0xf88a0000 Void
+0x010 DriverSize : 0x6000
+0x014 DriverSection : 0x81cde418 Void
+0x018 DriverExtension : 0x81cd4928 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "DriverMyDriver2"
+0x024 HardwareDatabase : 0x80691b90 _UNICODE_STRING "REGISTRYMACHINEHARDWAREDESCRIPTIONSYSTEM"
+0x028 FastIoDispatch : (null)
+0x02c DriverInit : 0xf88a4000 long MyDriver2!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : 0xf88a1040 void MyDriver2!DriverUnload+0
+0x038 MajorFunction : [28] 0x804fe101 long nt!IopInvalidDeviceRequest+0
kd> dt _LDR_DATA_TABLE_ENTRY 0x81cde418
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8055c340 - 0x81d0dfa0 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x77b83db8 - 0x0 ]
+0x018 DllBase : 0xf88a0000 Void
+0x01c EntryPoint : 0xf88a4000 Void
+0x020 SizeOfImage : 0x6000
+0x024 FullDllName : _UNICODE_STRING "??C:Documents and SettingsAdministrator桌面MyDriver2.sys"
+0x02c BaseDllName : _UNICODE_STRING "MyDriver2.sys"
+0x034 Flags : 0x9104000
+0x038 LoadCount : 1
+0x03a TlsIndex : 0
+0x03c HashLinks : _LIST_ENTRY [ 0xffffffff - 0xe591 ]
+0x03c SectionPointer : 0xffffffff Void
+0x040 CheckSum : 0xe591
+0x044 TimeDateStamp : 0xfffffffe
+0x044 LoadedImports : 0xfffffffe Void
+0x048 EntryPointActivationContext : (null)
+0x04c PatchInformation : 0x0079004d Void

继续遍历:

驱动-内核空间与内核模块

kd> dt _LDR_DATA_TABLE_ENTRY 0x8055c340
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x81ffc3a8 - 0x81cde418 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x018 DllBase : (null)
+0x01c EntryPoint : (null)
+0x020 SizeOfImage : 0x805637e0
+0x024 FullDllName : _UNICODE_STRING ""
+0x02c BaseDllName : _UNICODE_STRING ""
+0x034 Flags : 0
+0x038 LoadCount : 0
+0x03a TlsIndex : 0
+0x03c HashLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x03c SectionPointer : (null)
+0x040 CheckSum : 0
+0x044 TimeDateStamp : 0
+0x044 LoadedImports : (null)
+0x048 EntryPointActivationContext : (null)
+0x04c PatchInformation : (null)

也就说,如果我们进行0环的隐藏,可以通过断InLoadOrderLinks。但是,还是不会百分百隐藏。因为高2G有一个二叉树,二叉树存储了每个进程中的信息。

PEB与TEB

在这里,我们在介绍一下PEB和TEB

TEB

TEB,全称叫做:Thread Environment Block,也就是线程环境块,是每一个线程私有的数据结构,用于存储线程的运行时环境信息,TEB位于线程的用户模式堆栈底部,通常占用一个内存页,也就是4KB。

成员为:

kd> dt _TEB
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
+0x034 LastErrorValue : Uint4B
+0x038 CountOfOwnedCriticalSections : Uint4B
+0x03c CsrClientThread : Ptr32 Void
+0x040 Win32ThreadInfo : Ptr32 Void
+0x044 User32Reserved : [26] Uint4B
+0x0ac UserReserved : [5] Uint4B
+0x0c0 WOW32Reserved : Ptr32 Void
+0x0c4 CurrentLocale : Uint4B
+0x0c8 FpSoftwareStatusRegister : Uint4B
+0x0cc SystemReserved1 : [54] Ptr32 Void
+0x1a4 ExceptionCode : Int4B
+0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
+0x1bc SpareBytes1 : [24] UChar
+0x1d4 GdiTebBatch : _GDI_TEB_BATCH
+0x6b4 RealClientId : _CLIENT_ID
+0x6bc GdiCachedProcessHandle : Ptr32 Void
+0x6c0 GdiClientPID : Uint4B
+0x6c4 GdiClientTID : Uint4B
+0x6c8 GdiThreadLocalInfo : Ptr32 Void
+0x6cc Win32ClientInfo : [62] Uint4B
+0x7c4 glDispatchTable : [233] Ptr32 Void
+0xb68 glReserved1 : [29] Uint4B
+0xbdc glReserved2 : Ptr32 Void
+0xbe0 glSectionInfo : Ptr32 Void
+0xbe4 glSection : Ptr32 Void
+0xbe8 glTable : Ptr32 Void
+0xbec glCurrentRC : Ptr32 Void
+0xbf0 glContext : Ptr32 Void
+0xbf4 LastStatusValue : Uint4B
+0xbf8 StaticUnicodeString : _UNICODE_STRING
+0xc00 StaticUnicodeBuffer : [261] Uint2B
+0xe0c DeallocationStack : Ptr32 Void
+0xe10 TlsSlots : [64] Ptr32 Void
+0xf10 TlsLinks : _LIST_ENTRY
+0xf18 Vdm : Ptr32 Void
+0xf1c ReservedForNtRpc : Ptr32 Void
+0xf20 DbgSsReserved : [2] Ptr32 Void
+0xf28 HardErrorsAreDisabled : Uint4B
+0xf2c Instrumentation : [16] Ptr32 Void
+0xf6c WinSockData : Ptr32 Void
+0xf70 GdiBatchCount : Uint4B
+0xf74 InDbgPrint : UChar
+0xf75 FreeStackOnTermination : UChar
+0xf76 HasFiberData : UChar
+0xf77 IdealProcessor : UChar
+0xf78 Spare3 : Uint4B
+0xf7c ReservedForPerf : Ptr32 Void
+0xf80 ReservedForOle : Ptr32 Void
+0xf84 WaitingOnLoaderLock : Uint4B
+0xf88 Wx86Thread : _Wx86ThreadState
+0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
+0xf98 ImpersonationLocale : Uint4B
+0xf9c IsImpersonating : Uint4B
+0xfa0 NlsCache : Ptr32 Void
+0xfa4 pShimData : Ptr32 Void
+0xfa8 HeapVirtualAffinity : Uint4B
+0xfac CurrentTransactionHandle : Ptr32 Void
+0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME
+0xfb4 SafeThunkCall : UChar
+0xfb5 BooleanSpare : [3] UChar
......

其中最重要的是:

kd> dt _TEB
ntdll!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB

也就是在ds段寄存器偏移0x30的地方,指向PEB,那么什么是PEB呢?

PEB

PEB(Process Environment Block)又叫做进程环境块。是Windows操作系统中每个进程私有的数据结构,用于存储进程的运行时环境信息。PEB 位于用户模式下进程的内存空间中,由操作系统在进程创建时分配和初始化。我们可以通过fs:[0x30]找到他。

结构如下:

kd> dt _PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
+0x020 FastPebLockRoutine : Ptr32 Void
+0x024 FastPebUnlockRoutine : Ptr32 Void
+0x028 EnvironmentUpdateCount : Uint4B
+0x02c KernelCallbackTable : Ptr32 Void
+0x030 SystemReserved : [1] Uint4B
+0x034 AtlThunkSListPtr32 : Uint4B
+0x038 FreeList : Ptr32 _PEB_FREE_BLOCK
+0x03c TlsExpansionCounter : Uint4B
+0x040 TlsBitmap : Ptr32 Void
+0x044 TlsBitmapBits : [2] Uint4B
+0x04c ReadOnlySharedMemoryBase : Ptr32 Void
+0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
+0x058 AnsiCodePageData : Ptr32 Void
+0x05c OemCodePageData : Ptr32 Void
+0x060 UnicodeCaseTableData : Ptr32 Void
+0x064 NumberOfProcessors : Uint4B
+0x068 NtGlobalFlag : Uint4B
+0x070 CriticalSectionTimeout : _LARGE_INTEGER
+0x078 HeapSegmentReserve : Uint4B
+0x07c HeapSegmentCommit : Uint4B
+0x080 HeapDeCommitTotalFreeThreshold : Uint4B
+0x084 HeapDeCommitFreeBlockThreshold : Uint4B
+0x088 NumberOfHeaps : Uint4B
+0x08c MaximumNumberOfHeaps : Uint4B
+0x090 ProcessHeaps : Ptr32 Ptr32 Void
+0x094 GdiSharedHandleTable : Ptr32 Void
+0x098 ProcessStarterHelper : Ptr32 Void
+0x09c GdiDCAttributeList : Uint4B
+0x0a0 LoaderLock : Ptr32 Void
+0x0a4 OSMajorVersion : Uint4B
+0x0a8 OSMinorVersion : Uint4B
+0x0ac OSBuildNumber : Uint2B
+0x0ae OSCSDVersion : Uint2B
+0x0b0 OSPlatformId : Uint4B
+0x0b4 ImageSubsystem : Uint4B
+0x0b8 ImageSubsystemMajorVersion : Uint4B
+0x0bc ImageSubsystemMinorVersion : Uint4B
+0x0c0 ImageProcessAffinityMask : Uint4B
+0x0c4 GdiHandleBuffer : [34] Uint4B
+0x14c PostProcessInitRoutine : Ptr32 void
+0x150 TlsExpansionBitmap : Ptr32 Void
+0x154 TlsExpansionBitmapBits : [32] Uint4B
+0x1d4 SessionId : Uint4B
+0x1d8 AppCompatFlags : _ULARGE_INTEGER
+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
+0x1e8 pShimData : Ptr32 Void
+0x1ec AppCompatInfo : Ptr32 Void
+0x1f0 CSDVersion : _UNICODE_STRING
+0x1f8 ActivationContextData : Ptr32 Void
+0x1fc ProcessAssemblyStorageMap : Ptr32 Void
+0x200 SystemDefaultActivationContextData : Ptr32 Void
+0x204 SystemAssemblyStorageMap : Ptr32 Void
+0x208 MinimumStackCommit : Uint4B

其中最重要的是:

kd> dt _PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA

PEB_LDR_DATA结构

  • PEB_LDR_DATA:

kd> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void

这里主要介绍InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList

  • InLoadOrderModuleList:表示已加载模块的加载顺序

  • InMemoryOrderModuleList:内存顺序

  • InInitializationOrderModuleList:初始化顺序

这三个都是_LIST_ENTRY结构,也就是都是链表。而这三个链表都存储了我们的进程信息,如果我们想要实现3环的进程的断链隐藏,我们可以将我们的进程信息从这三个链表中抹去。但是这种隐藏,对于0环程序没啥影响,只是对api查询的程序,搜索不到。

原文始发于微信公众号(loochSec):驱动-内核空间与内核模块

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月15日11:11:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   驱动-内核空间与内核模块https://cn-sec.com/archives/2198065.html

发表评论

匿名网友 填写信息