cyxyrq-code-loading

 

Win32学习8

30、模块隐藏

一般来说,程序中注入的dll 都很难存活,因为程序的保护机制会遍历dll,会发现不属于自己的那个dll。所以我们就需要进行模块隐藏,将dll隐藏,让程序查不到。

①模块隐藏之断链

<1> TEB(Thread Environment Block 线程环境块 (属于是三环的结构体而非零环)),它记录的相关线程的信息,每一个线程都有自己的TEB, FS:[0]即是当前线程的TEB.
mov eax,fs:[0]

<2>PEB(Process Environment Block,进程环境块(属于是三环的结构体而非零环))存放进程信息,每个进程都有自己的PEB信息,TEB偏移0x30即当前进程的PEB.
mov eax,fs:[0x30]
mov PEB,eax
<3> TEB与PEB都在用户空间

普通API查找模块实现思路:其通过查询在R3中的PEB(Process Environment Block 进程环境块)与TEB(Thread Environment Block 进程环境块)来找到一个双向链表,通过遍历双向链表中某一成员(字符串)来查找全部模块。

模块隐藏实现思路:在R3层的模块隐藏,我们需要做的就是将其该链表断链,将某一模块从这个双向链表中摘除,这样再调用传统的API时就会搜索不到。

TEB结构体
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

PEB结构体
kd> dt _PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 BitField : UChar
+0x003 ImageUsesLargePages : Pos 0, 1 Bit
+0x003 IsProtectedProcess : Pos 1, 1 Bit
+0x003 IsLegacyProcess : Pos 2, 1 Bit
+0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
+0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
+0x003 SpareBits : Pos 5, 3 Bits
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA // PEB_LOADER_DATA 进程加载信息表

**重点关注 0x00c处的指针,其指向 _PEB_LDR_DATA 这个结构体,在这个结构体中 0x00c、0x014、0x01c 分别表示 *模块加载顺序* / *加载后在内存中的顺序* / *模块初始化的顺序。*

**

​ 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
​ + 0x028 ShutdownInProgress : UChar
​ + 0x02c ShutdownThreadId : Ptr32 Void

 理解其三个成员的顺序,其指向_LDR_DATA_TABLE_ENTRY元素中开始的三个成员,而 _LDR_DATA_TABLE_ENTRY 中存储着就是关于有关模块信息的元素(比如模块名等)

②模块隐藏之PE指纹

通过遍历内存找到PE指纹找到并非自己的dll 。

③模块隐藏之VAD树

方法主要是将API 查询dll进行屏蔽掉,但是仍可以通过别的方法查询得到。比如说通过一些驱动程序查询内存,仍可以找到你加载的那个dll。

④最好的隐藏:

无模块注入 也就是代码注入

31、注入代码

注入代码相较于模块注入更加的“隐藏”,因为所有的模块特征都没有。

远程代码注入:适用于代码量少且简单的情况。

远程代码注入:仅向目标进程注入必要的代码,要想使注入代码正常运行,还必须将代码中使用的数据一同注入。

①回顾远程线程

image-20230303224618875

②注入代码的思路

image-20230303225514084

我们将我们编写的代码放置于目标进程中,我们不能直接将我们编写的代码或者说是对应的汇编代码编写进去,因为每个程序编译结束之后都是一串机器码,我们只有将机器码写入目标进程,才能够实现注入代码。

④复制代码的编写原则:

(1)不能有全局变量

(2)不能使用常量字符串

(3)不能使用系统调用

(4)不能嵌套调用其他函数

⑤传递参数

posted on 2023-07-17 08:03  清雨中欣喜  阅读(24)  评论(0编辑  收藏  举报

导航