一、模块隐藏的实现原理

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

    

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

    

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

    

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

    

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

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

 // 隐藏模块.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// #include "pch.h"
#include <iostream>
#include <Windows.h> /* 所需要的结构体
1. _LDR_DATA_TABLE_ENTRY 链表指向数据
2. _PEB_LDR_DATA 表示其 PEB0x处指向的数据表
3. _LIST_ENTRY 指针指向的链表
*/ typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}
UNICODE_STRING, *PUNICODE_STRING; typedef struct _PEB_LDR_DATA
{
DWORD Length; // +0x00
bool Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA, *PPEB_LDR_DATA; // +0x24 typedef struct _LDR_MODULE
{
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_MODULE, *PLDR_MODULE; //所谓模块句柄,即该模块的入口地址
void hide_module(char* szDllName)
{
HMODULE hMod = GetModuleHandleA(szDllName);
PLIST_ENTRY Head, Cur;
PPEB_LDR_DATA ldr;
PLDR_MODULE ldm;
__asm
{
mov eax, fs:[0x30]
mov ecx, [eax + 0x0c] //Ldr
mov ldr, ecx
}
Head = &(ldr->InLoadOrderModuleList);
Cur = Head->Flink;
do
{
ldm = CONTAINING_RECORD(Cur, LDR_MODULE, InLoadOrderModuleList);
if (hMod == ldm->BaseAddress)
{
// 三个链表同时给断掉
ldm->InLoadOrderModuleList.Blink->Flink =
ldm->InLoadOrderModuleList.Flink;
ldm->InLoadOrderModuleList.Flink->Blink =
ldm->InLoadOrderModuleList.Blink; //
ldm->InInitializationOrderModuleList.Blink->Flink =
ldm->InInitializationOrderModuleList.Flink;
ldm->InInitializationOrderModuleList.Flink->Blink =
ldm->InInitializationOrderModuleList.Blink; //
ldm->InMemoryOrderModuleList.Blink->Flink =
ldm->InMemoryOrderModuleList.Flink;
ldm->InMemoryOrderModuleList.Flink->Blink =
ldm->InMemoryOrderModuleList.Blink;
break;
}
Cur = Cur->Flink;
} while (Head != Cur);
} int main()
{
// 通过模块名,来获取模块句柄
printf("****按任意键隐藏模块*****");
getchar();
hide_module((char*)"kernel32.dll");
printf("****隐藏模块完成*****");
getchar();
getchar(); }

利用C++实现模块隐藏(R3层断链)的更多相关文章

  1. 【旧文章搬运】修改PEB,断链隐藏模块成功

    原文发表于百度空间,2008-7-26========================================================================== 继续实践之前 ...

  2. phalcon:官方多模块支models层,mode数据库配置(二)

    phalcon:官方多模块支models层,mode数据库配置(二) 利用:\pahlcon\mvc\model\Manager::registerNamespaceAlias()方法获取多模块下的m ...

  3. 微信小程序弹出和隐藏遮罩层动画以及五星评分

    参考源码: http://www.see-source.com/weixinwidget/detail.html?wid=82 https://blog.csdn.net/pcaxb/article/ ...

  4. phalcon:官方多模块支models层,mode数据库配置

    phalcon:官方多模块支models层,mode数据库配置 按: backend分后台, frondend 分前台 每个多模块下面都有一个 Module.php文件, 1. frondend/mo ...

  5. jquery实现隐藏显示层动画效果、仿新浪字符动态输入、tab效果

    已经有两年多没登陆csdn账号了,中间做了些旁的事,可是现在却还是回归程序,但改做前端了,虽然很多东西都已忘得差不多了,但还是应该摆正心态,慢慢来,在前端漫游,做一只快乐双鱼. 路是一步一步走出来的, ...

  6. Java工程师高薪训练营-第一阶段 开源框架源码解析-模块一 持久层框架涉及实现及MyBatis源码分析-任务一:自定义持久层框架

    目录 任务一:自定义持久层框架 1.1 JDBC回顾及问题分析 1.2 自定义持久层框架思路分析 1.3 IPersistence_Test编写 1.3.1 XXXMapper.xml详解 1.3.2 ...

  7. 【笔记】拉勾Java工程师高薪训练营-第一阶段 开源框架源码解析-模块一 持久层框架涉及实现及MyBatis源码分析-任务一:自定义持久层框架

    以下笔记是我看完视频之后总结整理的,部分较为基础的知识点也做了补充,如有问题欢迎沟通. 目录 任务一:自定义持久层框架 1.1 JDBC回顾及问题分析 1.2 自定义持久层框架思路分析 1.3 IPe ...

  8. 利用pip安装模块(以安装pyperclip为例)

    >任务:利用pip安装pyperclip模块 >前提:你已经在你的电脑里面安装啦Python2.7的Windows版本,并且已经配置了环境变量 >实现步骤 >>打开你的P ...

  9. 手把手教你写LKM rookit! 之 第一个lkm程序及模块隐藏(一)

    唉,一开始在纠结起个什么名字,感觉名字常常的很装逼,于是起了个这<手把手教你写LKM rookit> 我觉得: 你们觉得:...... 开始之前,我们先来理解一句话:一切的操作都是系统调用 ...

随机推荐

  1. 牛客网暑期ACM多校训练营(第二场) I Car 思维

    链接:https://www.nowcoder.com/acm/contest/140/I来源:牛客网 White Cloud has a square of n*n from (1,1) to (n ...

  2. 天梯杯 PAT L2-001. 紧急救援 最短路变形

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  3. PHP 实现字符串表达式计算

    什么是字符串表达式?即,将我们常见的表达式文本写到了字符串中,如:"$age >= 20",$age 的值是动态的整型变量. 什么是字符串表达式计算?即,我们需要一段程序来执 ...

  4. 讲解开源项目:用 Python 生成有“灵魂”的二维码

    本文作者:HelloGitHub-LITTLECHIEH 这是 HelloGitHub 推出的<讲解开源项目>系列,今天给大家推荐一个 Python 开源生成二维码的项目--qrcode ...

  5. Json的动态解析

    最近在项目中需要动态解析json,但解析json的方式有很多,如何合理的解析就是我们需要考虑的问题?比如Newtonsoft.Json.Linq下提供的JToken.JObject等,Newtonso ...

  6. GO 语言学习笔记--数组切片篇

    1.对于make 数组切片,长度和容量需要理解清楚: 容量表示底层数组的大小,长度是你可以使用的大小: 容量的用处在哪?在与当你用 appen d扩展长度时,如果新的长度小于容量,不会更换底层数组,否 ...

  7. springmvc项目中的中文乱码的解决及未生效解决

    情景: springmvc项目中,在控制台输出时中文乱码,在web网页中正常. 解决方法: 在web.xml中添加如下代码: <!-- 中文乱码解决 --> <filter> ...

  8. a417: 螺旋矩陣

    题目: 每行有一正整数T,代表有几组测试数据 接下来有T行,每行有N.M两正整数 N为矩阵长宽,就是会有N*N矩阵 M为方向,M=1为顺时钟,M=2为逆时钟 N范围为1~100之间 思路: 所以,代码 ...

  9. 【学习笔记】第四章 Python3核心技术与实践--列表与元组

    前面的课程,我们了解了Python 语言的学习方法,并且带你了解了 Python 必知的常用工具——Jupyter.接下来我们正式学习 Python 的具体知识. 对于每一门编程语言来说,数据结构都是 ...

  10. 【学习笔记】第三章 python3核心技术与实践--Jupyter Notebook

    可能你已经知道,Python 在 14 年后的“崛起”,得益于机器学习和数学统计应用的兴起.那为什么 Python 如此适合数学统计和机器学习呢?作为“老司机”的我可以肯定地告诉你,Jupyter N ...