一、断链原理

3环下PEB断链是一种常见的模块隐藏技术,原理是修改 _PEB_LDR_DATA 中的三个双向链表,删除链表中的项,让 CreateToolhelp32Snapshot 之类的API无法通过模块列表枚举DLL。

以 InLoadOrderModuleList 链表为例,画个简单的示意图:

所谓断链,就是把三个链表断掉,让3环的API读不出模块信息。最简单的做法就是让Head的Flink和Blink指向它自己。

二、隐藏所有模块

// PEB断链.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <Windows.h>// 内核Unicode字符串
typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;// LDR链表头
typedef struct _PEB_LDR_DATA
{DWORD Length;bool Initialized;PVOID SsHandle;// LIST_ENTRY 是双端链表项,指向前后节点LIST_ENTRY InLoadOrderModuleList; // 指向了 InLoadOrderModuleList 链表的第一项LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA,*PPEB_LDR_DATA;// LDR表项,存储了模块信息
typedef struct _LDR_DATA_TABLE_ENTRY
{LIST_ENTRY          InLoadOrderModuleList;LIST_ENTRY          InMemoryOrderModuleList;LIST_ENTRY          InInitializationOrderModuleList;void*               BaseAddress;void*               EntryPoint;  ULONG               SizeOfImage;UNICODE_STRING      FullDllName;UNICODE_STRING      BaseDllName;ULONG               Flags;SHORT               LoadCount;SHORT               TlsIndex;HANDLE              SectionHandle;ULONG               CheckSum;ULONG               TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;void HideModule()
{   PPEB_LDR_DATA ldr;  PLDR_DATA_TABLE_ENTRY ldte;// 获取LDR__asm{mov eax,fs:[0x30] // PEB mov ecx,[eax + 0x0c] // LDRmov ldr,ecx  }PLIST_ENTRY Head; // Head 指向链表第一项,第一项不存储模块信息// 分别将三个链表断链处理Head = &(ldr->InLoadOrderModuleList);Head->Flink = Head->Blink = Head;Head = &(ldr->InMemoryOrderModuleList);Head->Flink = Head->Blink = Head;Head = &(ldr->InInitializationOrderModuleList);Head->Flink = Head->Blink = Head;
}int _tmain(int argc, _TCHAR* argv[])
{printf("未断链前状态(敲任意字符开始断链)\n");getchar();HideModule();printf("断链后状态.\n");getchar();return 0;
}

断链前:

断链后:

三、隐藏特定模块

如果想隐藏某个特定模块,例如隐藏掉 kernel32.dll,可以这样做:

// PEB断链.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <Windows.h>// 内核Unicode字符串
typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;// LDR链表头
typedef struct _PEB_LDR_DATA
{DWORD Length;bool Initialized;PVOID SsHandle;// LIST_ENTRY 是双端链表项,指向前后节点LIST_ENTRY InLoadOrderModuleList; // 指向了 InLoadOrderModuleList 链表的第一项LIST_ENTRY InMemoryOrderModuleList;LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA,*PPEB_LDR_DATA;// LDR表项,存储了模块信息
typedef struct _LDR_DATA_TABLE_ENTRY
{LIST_ENTRY          InLoadOrderModuleList;LIST_ENTRY          InMemoryOrderModuleList;LIST_ENTRY          InInitializationOrderModuleList;void*               BaseAddress;void*               EntryPoint;  ULONG               SizeOfImage;UNICODE_STRING      FullDllName;UNICODE_STRING      BaseDllName;ULONG               Flags;SHORT               LoadCount;SHORT               TlsIndex;HANDLE              SectionHandle;ULONG               CheckSum;ULONG               TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;void HideModule(HMODULE hModule)
{   PPEB_LDR_DATA ldr;  PLDR_DATA_TABLE_ENTRY ldte;// 获取LDR__asm{mov eax,fs:[0x30] // PEB mov ecx,[eax + 0x0c] // LDRmov ldr,ecx  }PLIST_ENTRY Head, Cur; // Head 指向链表第一项,第一项不存储模块信息;Cur指向第二项,是第一个存储了模块信息的项// 分别将三个链表断链处理Head = &(ldr->InLoadOrderModuleList);Cur = Head->Flink;do{// CONTAINING_RECORD宏的作用是传入一个地址,一个结构体类型和该地址属于结构体中的哪个属性,返回结构体基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);if (ldte->BaseAddress == hModule){       // 断链ldte->InLoadOrderModuleList.Blink->Flink = ldte->InLoadOrderModuleList.Flink;  ldte->InLoadOrderModuleList.Flink->Blink = ldte->InLoadOrderModuleList.Blink;        }Cur = Cur->Flink;} while(Head != Cur);Head = &(ldr->InMemoryOrderModuleList);Cur = Head->Flink;do  {  // CONTAINING_RECORD宏的作用是传入一个地址,一个结构体类型和该地址属于结构体中的哪个属性,返回结构体基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);  if (ldte->BaseAddress == hModule){// 断链ldte->InMemoryOrderModuleList.Blink->Flink = ldte->InMemoryOrderModuleList.Flink;  ldte->InMemoryOrderModuleList.Flink->Blink = ldte->InMemoryOrderModuleList.Blink;       }Cur = Cur->Flink;} while(Head != Cur);Head = &(ldr->InInitializationOrderModuleList);Cur = Head->Flink;do  {  // CONTAINING_RECORD宏的作用是传入一个地址,一个结构体类型和该地址属于结构体中的哪个属性,返回结构体基址ldte = CONTAINING_RECORD( Cur, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);  if (ldte->BaseAddress == hModule){// 断链ldte->InInitializationOrderModuleList.Blink->Flink = ldte->InInitializationOrderModuleList.Flink;  ldte->InInitializationOrderModuleList.Flink->Blink = ldte->InInitializationOrderModuleList.Blink;                  }Cur = Cur->Flink;} while(Head != Cur);
}int _tmain(int argc, _TCHAR* argv[])
{printf("未断链前状态(敲任意字符开始断链)\n");getchar();HideModule(GetModuleHandleA("kernel32.dll"));printf("断链后状态.\n");getchar();return 0;
}

断链前:

断链后:

(35)3环PEB断链相关推荐

  1. 4.PEB断链隐藏模块

    0x4 PEB断链隐藏模块 1.如何找到_PEB_LDR_DATA 由_TEB找到_PEB,_PEB偏移0xC找到_PEB_LDR_DATA 2.基础知识 _LDR_DATA_TABLE_ENTRY结 ...

  2. (53)进程结构体EPROCESS,擦除 DebugPort 实现反调试,ActiveProcessLinks 断链实现进程隐藏

    一.进程的作用 进程最重要的作用是提供了CR3,10-10-12分页下CR3指向页目录表,2-9-9-12分页下CR3指向页目录指针表. 每个进程有一个或多个线程.本质上,没有进程切换,只有线程切换. ...

  3. (54)线程结构体 ETHREAD,线程断链

    一.回顾 上次课我们学习了进程,我们知道了进程是空间概念,最主要的功能是提供CR3,而线程才是CPU调度的最小单位: 更早的时候做SSDT HOOK FindWindow 时我们还了解到了,当3环程序 ...

  4. _ETHREAD断链 —— 实现线程隐藏

    简介 线程所属的父进程 _EPROCESS 结构体中的 ThreadListHead 成员是当前进程中所有线程的双向链表头,该成员有两个,分别在 0x50 和 0x190 处.我们可以通过该线程链表头 ...

  5. nats断链情况总结

    1.客户端启动时nats server连不上 代码段: func setupConnOptions() []nats.Option {opts := make([]nats.Option,0)opts ...

  6. c语言断链隐藏dll,利用C++ R3层断链实现模块隐藏功能

    一.模块隐藏的实现原理 普通API查找模块实现思路:其通过查询在R3中的PEB(Process Environment Block 进程环境块)与TEB(Thread Environment Bloc ...

  7. 关于递归删除链表节点为什么不会断链问题解释

    问题的由来:    当你第一次实现用递归实现链表删除功能的时候,是否有一丝丝的考虑过.这个问题呢?为什么对于非递归版本的删除必须要知道当前要删除节点的前驱,而需要对其前驱节点的next域指针进行修改. ...

  8. 断链在平曲线计算中的处理——短链篇

    第十二篇  断链在平曲线计算中的处理--短链篇 1. 短链在平曲线编程数据库里的处理方法 断链是在一些线路设计或施工中因某种情况下而产生的,具体原因在此不做讨论,短链就是断链的其中一种常见形式,另一种 ...

  9. 应用使用Druid连接池经常性断链问题分析

    前段时间有应用使用Druid连接池经常的提示断链报错,整个问题排查分析过程很有意思.这里将Druid连接池.数据库层以及负载均衡层的配置分析下,记录整个问题的分析过程,同时梳理下Druid连接池的配置 ...

最新文章

  1. 三月新增电脑病毒400万 被感染计算机多达2000万
  2. Phalcon和YII的优点
  3. java异常处理学习总结
  4. C#中System.ServiceProgress报错
  5. 从字到词,大词典中文BERT模型的探索之旅
  6. 中国房地产市值已经超过450万亿,为何还不见房价下跌?
  7. document 文挡对象详解(JavaScript脚本语言描述)
  8. php画弧,php绘制一条弧线的方法
  9. Reporting Services Catalog Database File Existence error during installing SQL Server 2008 R2
  10. Remoting事件序列一:客户端触发服务器端事件
  11. innosetup 安装前、卸载前判断是否有进程正在运行转
  12. android Intent调用地图应用客户端
  13. 实战来了!聊聊电商系统中红包雨功能的设计与实现
  14. c语言编译九行菱形,C语言打印菱形
  15. Windows2003下运行JSP,环境配置教程(J2SDK+Tomcat5+IIS)
  16. Quasi-globally Optimal and Near/True Real-time Vanishing Point Estimation in Manhattan World 论文阅读学习
  17. html5充值页面(Vue)
  18. nz-upload的[nzCustomRequest]自定义上传
  19. Spring源码解析之 Bean与BeanDefinition详解
  20. MFC CImage图像失真的解决方法

热门文章

  1. Dataset:GiveMeSomeCredit数据集的简介、下载、使用方法之详细攻略
  2. Database之SQLSever:SQLSever数据库管理(GUI法/SQL语句命令法两种方法实现备份(完整备份、差异备份、日志备份)、还原、删除、修改数据库等案例)之详细攻略
  3. AI:2020年7月10日世界人工智能大会WAIC青少年人工智能创新发展论坛《人工智能从娃娃抓起》
  4. AI开发者大会之AI学习与进阶实践:2020年7月3日《如何转型搞AI?》、《基于AI行业价值的AI学习与进阶路径》、《自动机器学习与前沿AI开源项目》、《使用TensorFlow实现经典模型》
  5. Py之torchvision:torchvision库的简介、安装、使用方法之详细攻略
  6. 成功解决没有tf.nn.rnn_cell属性
  7. 成功解决from nets import inception_resnet_v2 ModuleNotFoundError: No module named 'nets'
  8. BZOJ3569: DZY Loves Chinese II(线性基构造)
  9. 通过构造函数来创建新对象
  10. 兰山天书(贺兰山岩画)