利用C++实现模块隐藏(R3层断链)

摘要:
模块隐藏的实现思路:对于R3层中的模块隐藏,我们需要做的就是断开链接列表的链接,从双向链接列表中删除一个模块,这样当我们调用传统的API时,将不搜索LDR_ DATA_ TABLE_ ENTRY+0x000InLoadOrderLinks:_ LIST_ ENTRY+0x008InMemoryOrderLinks:_LIST_ ENTRY+0x010InInitializationOrderLinks:_LIST_ ENTRY+0x018DllBase:Ptr32oid//模块基地址+0x01cEntryPoint:Ptr32Id//输入函数+0x020SizeOfImage:Uint4B//模块大小+0x024FullDllName:_ UNICODE_ STRING//完整模块名称(带路径)+0x02cBaseDllName:_ UNICODESTRING//模块名称+0x034标志:Uint4B2。使用olldbg查看并查找首先加载的模块的模块名称。2.1)根据之前的TEB内容fs:[0x30]查找PEB的位置。2.2)InLoadOrderModuleList成员位于其0x00c处,该成员指向a_LDR_DATA_TABLE_ENTRY结构。

一、模块隐藏的实现原理

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

利用C++实现模块隐藏(R3层断链)第1张

  模块隐藏实现思路:在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],查看其内存地址。

    利用C++实现模块隐藏(R3层断链)第2张

  2.2) 在内存窗口使用命令 "db 5E7000" 跳转到该内存,使用地址格式(长型-地址)显示。

    利用C++实现模块隐藏(R3层断链)第3张

<2>  PEB结构体 -- fs:[0x30]

使用 Windbg 指令 dt _PEB 查看 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 进程加载信息表

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

    利用C++实现模块隐藏(R3层断链)第4张

  2.3)  跳转到 _LDR_DATA_TABLE_ENTRY 结构体,从0x0c开始依次是三个 _LIST_ENTRY 结构体,该结构体双向链表存储着两个地址。

    利用C++实现模块隐藏(R3层断链)第5张

  2.4)选中第一个进入,在其偏移0x02c处(UNICODE结构体占四字),可以查看字符串名称。

    利用C++实现模块隐藏(R3层断链)第6张

  2.5)通过开头 _LIST_ENTRY结构体可以遍历前一个模块的内容和下一个模块的内容。

    利用C++实现模块隐藏(R3层断链)第7张

三、利用C++断链来实现模块隐藏

  如果你看懂上面分析,则源代码非常好理解。

  1 // 隐藏模块.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
  2 //
  3 
  4 #include "pch.h"
  5 #include <iostream>
  6 #include <Windows.h>
  7 
  8 
  9 /* 所需要的结构体
 10 1. _LDR_DATA_TABLE_ENTRY 链表指向数据
 11 2. _PEB_LDR_DATA 表示其 PEB0x处指向的数据表
 12 3. _LIST_ENTRY 指针指向的链表
 13 */
 14 
 15 typedef struct _LSA_UNICODE_STRING {
 16     USHORT Length;
 17     USHORT MaximumLength;
 18     PWSTR  Buffer;
 19 }
 20 UNICODE_STRING, *PUNICODE_STRING;
 21 
 22 typedef struct _PEB_LDR_DATA
 23 {
 24     DWORD Length; // +0x00
 25     bool Initialized; // +0x04
 26     PVOID SsHandle; // +0x08
 27     LIST_ENTRY InLoadOrderModuleList; // +0x0c
 28     LIST_ENTRY InMemoryOrderModuleList; // +0x14
 29     LIST_ENTRY InInitializationOrderModuleList;// +0x1c
 30 } PEB_LDR_DATA, *PPEB_LDR_DATA; // +0x24
 31 
 32 typedef struct _LDR_MODULE
 33 {
 34     LIST_ENTRY          InLoadOrderModuleList;
 35     LIST_ENTRY          InMemoryOrderModuleList;
 36     LIST_ENTRY          InInitializationOrderModuleList;
 37     void*               BaseAddress;
 38     void*               EntryPoint;
 39     ULONG               SizeOfImage;
 40     UNICODE_STRING   FullDllName;
 41     UNICODE_STRING      BaseDllName;
 42     ULONG               Flags;
 43     SHORT               LoadCount;
 44     SHORT               TlsIndex;
 45     HANDLE              SectionHandle;
 46     ULONG               CheckSum;
 47     ULONG               TimeDateStamp;
 48 } LDR_MODULE, *PLDR_MODULE;
 49 
 50 //所谓模块句柄,即该模块的入口地址
 51 void hide_module(char* szDllName)
 52 {
 53     HMODULE hMod = GetModuleHandleA(szDllName);
 54     PLIST_ENTRY Head, Cur;
 55     PPEB_LDR_DATA ldr;
 56     PLDR_MODULE ldm;
 57     __asm
 58     {
 59         mov eax, fs:[0x30]
 60         mov ecx, [eax + 0x0c] //Ldr  
 61         mov ldr, ecx
 62     }
 63     Head = &(ldr->InLoadOrderModuleList);
 64     Cur = Head->Flink;
 65     do
 66     {
 67         ldm = CONTAINING_RECORD(Cur, LDR_MODULE, InLoadOrderModuleList);
 68         if (hMod == ldm->BaseAddress)
 69         {
 70             // 三个链表同时给断掉
 71             ldm->InLoadOrderModuleList.Blink->Flink =
 72                 ldm->InLoadOrderModuleList.Flink;
 73             ldm->InLoadOrderModuleList.Flink->Blink =
 74                 ldm->InLoadOrderModuleList.Blink;
 75 
 76             //
 77             ldm->InInitializationOrderModuleList.Blink->Flink =
 78                 ldm->InInitializationOrderModuleList.Flink;
 79             ldm->InInitializationOrderModuleList.Flink->Blink =
 80                 ldm->InInitializationOrderModuleList.Blink;
 81             
 82             //
 83             ldm->InMemoryOrderModuleList.Blink->Flink =
 84                 ldm->InMemoryOrderModuleList.Flink;
 85             ldm->InMemoryOrderModuleList.Flink->Blink =
 86                 ldm->InMemoryOrderModuleList.Blink;
 87             break;
 88         }
 89         Cur = Cur->Flink;
 90     } while (Head != Cur);
 91 }
 92 
 93 
 94 
 95 int main()
 96 {
 97     // 通过模块名,来获取模块句柄
 98     printf("****按任意键隐藏模块*****");
 99     getchar();
100     hide_module((char*)"kernel32.dll");
101     printf("****隐藏模块完成*****");
102     getchar();
103     getchar();
104 
105 }

免责声明:文章转载自《利用C++实现模块隐藏(R3层断链)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇缓冲区溢出漏洞(2)python报错_couldn't recognize data in image file下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

数据结构-链表习题

判断题 1.在单向链表中,头指针中存放的是头结点的内容。      T      F 2.单向链表中的每个结点都需要动态分配内存空间。      T      F 3.通常使用结构的嵌套来定义单向链表结点的数据类型。      T      F 4.用链表代替数组进行数据操作时,查询更加方便。      T      F 选择题 1.以下程序的输...

redis list结构

一个功能肯定有其应用场景: PUSH和POP操作,其实是队列的基本操作。Redis的list就是一个极其强大的队列系统。我们在哪些地方会用到队列呢?下面,我们说两个例子: a,评论系统 逛过微博的筒子们应该都对评论系统有了解。我们在看完一条微博之后,常常会评论一番,或者看看其他人的吐槽。每条评论的记录都是按照时间顺序排序的。我们读的时候也是这个顺序。这时,...

约瑟夫生死游戏(单链表实现)

本周的作业还算挺好玩。。约瑟夫生死游戏嘛。 老师要抽签选择每个组对应的数据结构。结果宝宝抽到了单链表。。。。 一、项目简介       约瑟夫生者死者游戏的大意是:30个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分;因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免遇难。无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人开始...

面渣逆袭:HashMap追魂二十三问

大家好,我是老三。 HashMap作为我们熟悉的一种集合,可以说是面试必考题。简单的使用,再到原理、数据结构,还可以延伸到并发,可以说,就一个HashMap,能聊半个小时。 1.能说一下HashMap的数据结构吗? JDK1.7的数据结构是数组+链表,JDK1.7还有人在用?不会吧…… 说一下JDK1.8的数据结构吧: JDK1.8的数据结构是数组+链表+...

Linux/Android——input_handler之evdev (四) 【转】

转自:http://blog.csdn.net/u013491946/article/details/72638919 版权声明:免责声明: 本人在此发文(包括但不限于汉字、拼音、拉丁字母)均为随意敲击键盘所出,用于检验本人电脑键盘录入、屏幕显示的机械、光电性能,并不代表本人局部或全部同意、支持或者反对观点。如需要详查请直接与键盘生产厂商法人代表联系 .挖...

进程隐藏的实现

通过Hook SSDT (System Service Dispatch Table) 隐藏进程1.原理介绍: Windows操作系统是一种分层的架构体系。应用层的程序是通过API来访问操作系统。而API又是通过ntdll里面的核心API来进行系统服务的查询。核心API通过对int 2e的切换,从用户模式转换到内核模式。2Eh中断的功能是通过NTOSKRN...