如何利用C++R3层断链实现模块隐藏功能
这篇文章给大家分享的是有关如何利用C++R3层断链实现模块隐藏功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
创新互联建站于2013年开始,先为五大连池等服务建站,五大连池等地企业,进行企业商务咨询服务。为五大连池企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
一、模块隐藏的实现原理
普通API查找模块实现思路:其通过查询在R3中的PEB(Process Environment Block 进程环境块)与TEB(Thread Environment Block 进程环境块)来找到一个双向链表,通过遍历双向链表中某一成员(字符串)来查找全部模块。
模块隐藏实现思路:在R3层的模块隐藏,我们需要做的就是将其该链表断链,将某一模块从这个双向链表中摘除,这样再调用传统的API时就会搜索不到。
二、结构体成员详细介绍
<1> TEB结构体 -- 内存地址为 fs:[0] 处。
使用Windbg的 "dt _TEB"命令来查看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
1. 属性介绍
1.1)_NT_TIB:重点两个属性,栈顶与栈大小。
http://www.nirsoft.net/kernel_struct/vista/NT_TIB.html
1.2) _CLIENT_ID: 存储该进程ID与当前主线程ID。
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tsts/a11e7129-685b-4535-8d37-21d4596ac057?redirectedfrom=MSDN
1.3) _PEB:进程环境块 ,记住其在 TEB 偏移 0x30处即可。
2. 通过olldbg查看该结构体
2.1) 打开任意进程,在寄存器窗口找到 fs:[0],查看其内存地址。
2.2) 在内存窗口使用命令 "db 5E7000" 跳转到该内存,使用地址格式(长型-地址)显示。
<2> PEB结构体 -- fs:[0x30]
使用 Windbg 指令 dt _PEB 查看 PEB结构体,重点关注最后一个 进程加载信息表。
kd> dt _PEBntdll!_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 进程加载信息表
1. 查看 _PEB_LDR_DATA 进程加载信息表 的结构体
1.1)重点关注 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
2.2)理解其三个成员的顺序,其指向_LDR_DATA_TABLE_ENTRY元素中开始的三个成员,而 _LDR_DATA_TABLE_ENTRY 中存储着就是关于有关模块信息的元素(比如模块名等)
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 // 入口函数(对于 exe 模块有效) + 0x020 SizeOfImage : Uint4B // 模块大小 + 0x024 FullDllName : _UNICODE_STRING // 完成模块名称(带路径) + 0x02c BaseDllName : _UNICODE_STRING // 模块名称 + 0x034 Flags : Uint4B
2. 使用olldbg来查看查找首先加载模块的模块名称(TEB->PEB-> InLoadOrderModuleList -> BaseDllName)
2.1)接之前TEB内容查找到PEB的所在位置 fs:[0x30]。
2.2) 在其0x00c处发现InLoadOrderModuleList成员,其指向的是一个_LDR_DATA_TABLE_ENTRY 结构体。
2.3) 跳转到 _LDR_DATA_TABLE_ENTRY 结构体,从0x0c开始依次是三个 _LIST_ENTRY 结构体,该结构体双向链表存储着两个地址。
2.4)选中第一个进入,在其偏移0x02c处(UNICODE结构体占四字),可以查看字符串名称。
2.5)通过开头 _LIST_ENTRY结构体可以遍历前一个模块的内容和下一个模块的内容。
三、利用C++断链来实现模块隐藏
如果你看懂上面分析,则源代码非常好理解。
// 隐藏模块.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include "pch.h"#include
感谢各位的阅读!关于“如何利用C++R3层断链实现模块隐藏功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
新闻名称:如何利用C++R3层断链实现模块隐藏功能
文章路径:http://myzitong.com/article/ijephp.html