首页
社区
课程
招聘
[原创]超详细的3环和0环断链隐藏分析
2023-9-4 20:42 11102

[原创]超详细的3环和0环断链隐藏分析

2023-9-4 20:42
11102

ps: 以下实验均在 windows xp系统下完成

  1. 3环断链(PEB断链)

作用:3环断链通常用于在用户层隐藏dll

获取dll模块的步骤为:获取 TEB -> PEB -> ldr -> dll模块

(1)TEB的获取方法为:fs:[0]

(2)通过TEB结构体发现,PPEB(PEB指针,指向PEB首地址)位于TEB偏移0x30处,因此PPEB == fs:[0x30]

(3)通过PEB结构体发现,ldr位于PEB偏移0xc处,因此 ldr == PPEB + 0xc

(4)通过ldr指向的结构体 _PEB_LDR_DATA 结构体找到3个双向循环链表 _LIST_ENTRY结构体

(5)_LIST_ENTRY结构体有两个成员,指向前驱模块节点的 _LIST_ENTRY、指向后继模块节点的 _LIST_ENTRY

(6)节点指针指向的是 _LIST_ENTRY 结构体,该结构体存储了模块在链表中的位置信息

(7)通过 _LDR_DATA_TABLE_ENTRY 结构体中偏移 0x18的 DllBase 或 0x2c 的 BaseDllName 确定要隐藏的dll,并通过该结构体中的 _LIST_ENTRY结构体删除该节点在链表中的位置信息(双向循环链表删除节点),即可达到3环下的dll隐藏

TEB结构体:3环下的线程环境块结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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          // PPEB
   +0x034 LastErrorValue   : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   +0x03c CsrClientThread  : Ptr32 Void
   +0x040 Win32ThreadInfo  : Ptr32 Void
   +0x044 User32Reserved   : [26] Uint4B
   +0x0ac UserReserved     : [5] Uint4B
   +0x0c0 WOW32Reserved    : Ptr32 Void
   +0x0c4 CurrentLocale    : Uint4B
    ... ...

PEB结构体:3环下的进程环境块结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kd> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA                // ldr
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION
   +0x020 FastPebLockRoutine : Ptr32 Void
   +0x024 FastPebUnlockRoutine : Ptr32 Void
   +0x028 EnvironmentUpdateCount : Uint4B
   +0x02c KernelCallbackTable : Ptr32 Void
    ... ...

_PEB_LDR_DATA结构体:ldr的结构体

1
2
3
4
5
6
7
8
9
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

_LIST_ENTRY结构体:上述三个链表的结构体

1
2
3
4
kd> dt _LIST_ENTRY
ntdll!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY      // 指向前驱节点的指针
   +0x004 Blink            : Ptr32 _LIST_ENTRY      // 指向后继节点的指针

_LDR_DATA_TABLE_ENTRY结构体:存储dll模块的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kd> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY                    
   +0x000 InLoadOrderLinks : _LIST_ENTRY            // _LIST_ENTRY结构体中Flink或Blink指向的位置
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void             // dll基址
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING        // dll名称
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 Void
   +0x04c PatchInformation : Ptr32 Void

PEB断链源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include<stdio.h>
#include<Windows.h>
 
typedef struct _UNICODE_STRING
{
    USHORT Length;        //字符串长度
    USHORT MaximumLength; //字符串最大长度
    PWSTR Buffer;         //双字节字符串指针
} UNICODE_STRING, * PUNICODE_STRING;
 
typedef struct _PEB_LDR_DATA
{
    ULONG Length;
    BOOLEAN Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;           //代表按加载顺序构成的模块列表
    LIST_ENTRY InMemoryOrderModuleList;         //代表按内存顺序构成的模块列表
    LIST_ENTRY InInitializationOrderModuleList; //代表按初始化顺序构成的模块链表
}PEB_LDR_DATA, * PPEB_LDR_DATA;
 
typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY InLoadOrderModuleList;  //代表按加载顺序构成的模块列表
    LIST_ENTRY InMemoryOrderModuleList;    //代表按内存顺序构成的模块列表
    LIST_ENTRY InInitializeationOrderModuleList; //代表按初始化顺序构成的模块链表
    PVOID DllBase;     //该模块的基地址
    PVOID EntryPoint;  //该模块的入口
    ULONG SizeOfImage; //该模块的影像大小
    UNICODE_STRING FullDllName;    //模块的完整路径
    UNICODE_STRING BaseDllName;    //模块名
    ULONG Flags;
    SHORT LoadCount;
    SHORT TlsIndex;
    HANDLE SectionHandle;
    ULONG CheckSum;
    ULONG TimeDataStamp;
}LDR_MODULE, * PLDR_MODULE;
 
PEB_LDR_DATA* g_pPebLdr = NULL;
LDR_MODULE* g_pLdrModule = NULL;
LIST_ENTRY* g_pInLoadOrderModule;
LIST_ENTRY* g_pInMemoryOrderModule;
LIST_ENTRY* g_pInInitializeationOrderModule;
 
void ring3BrokenChains(HMODULE hModule)
{
    LIST_ENTRY* pHead = g_pInLoadOrderModule;
    LIST_ENTRY* pCur = pHead;
 
    do {
        pCur = pCur->Blink;
        g_pLdrModule = (PLDR_MODULE)pCur;  // 这里为什么可以直接将pCur转为PLDR_MODULE,见下面代码解释
         
        // CONTAINING_RECORD这个宏返回成员变量所在结构体的基址,ldte == g_pLdrModule
        // PLDR_MODULE ldte = CONTAINING_RECORD(pCur, _LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
         
         
        if (hModule == g_pLdrModule->DllBase)
        {
            g_pLdrModule->InLoadOrderModuleList.Blink->Flink = g_pLdrModule->InLoadOrderModuleList.Flink;
            g_pLdrModule->InLoadOrderModuleList.Flink->Blink = g_pLdrModule->InLoadOrderModuleList.Blink;
 
            g_pLdrModule->InInitializeationOrderModuleList.Blink->Flink = g_pLdrModule->InInitializeationOrderModuleList.Flink;
            g_pLdrModule->InInitializeationOrderModuleList.Flink->Blink = g_pLdrModule->InInitializeationOrderModuleList.Blink;
 
            g_pLdrModule->InMemoryOrderModuleList.Blink->Flink = g_pLdrModule->InMemoryOrderModuleList.Flink;
            g_pLdrModule->InMemoryOrderModuleList.Flink->Blink = g_pLdrModule->InMemoryOrderModuleList.Blink;
            break;
        }
    } while (pHead != pCur);
}
 
int main(int argc, char* argv[])
{
    __asm
    {
        mov eax, fs: [0x30] ;  // PPEB
        mov ecx, [eax + 0xC];  // ldr
        mov g_pPebLdr, ecx;
 
        mov ebx, ecx;
        add ebx, 0xC;
        mov g_pInLoadOrderModule, ebx;              // 第1个链表
 
        mov ebx, ecx;
        add ebx, 0x14;
        mov g_pInMemoryOrderModule, ebx;            // 第2个链表
 
        mov ebx, ecx;
        add ebx, 0x1C;
        mov g_pInInitializeationOrderModule, ebx;   // 第3个链表
    }
 
    printf("点任意按键开始断链");
    getchar();
    ring3BrokenChains(GetModuleHandleA("kernel32.dll"));
    printf("断链成功\n");
    getchar();
    return 0;
}

关键代码解释:

1
2
3
4
5
6
7
pCur = pCur->Blink;
g_pLdrModule = (PLDR_MODULE)pCur;  // 这里为什么可以直接将pCur转为PLDR_MODULE,见下面代码解释
 
这是因为 pCur 指向 _LIST_ENTRY 结构体,指向的地址刚好是_LDR_DATA_TABLE_ENTRY的首地址,因此二者在内存上刚好是对齐的。
         
// CONTAINING_RECORD这个宏返回成员变量所在结构体的基址,ldte == g_pLdrModule
PLDR_MODULE ldte = CONTAINING_RECORD(pCur, _LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
  1. 0环断链(EPROCESS断链)

作用:0环断链通常用于在内核层隐藏进程

获取进程模块的步骤为:获取 _KPCR -> _KPRCB -> KTHREAD -> _KAPC_STATE -> _KPROCESS -> _EPROCESS

(1)KPCR 的获取方法为:fs:[0]

(2)KPCR 结构体中偏移0x120处有一个成员 _KPRCB 结构体,该结构体中偏移0x4处(即 fs:[0x124])有一个 CurrentThread 指针,指向 _KTHREAD 结构体

(3)_KTHREAD 结构体偏移0x34处有一个 ApcState 结构体,该结构体偏移0x10处有一个 Process 指针,指向 _KPROCESS

(4)_EPROCESS 结构体的第一个成员是 Pcb,是一个 _KPROCESS 结构体

(5)(3)中的 Process 指针指向的就是 _EPROCESS 中的一个成员 _KPROCESS 结构体,也是 _EPROCESS 结构体的首地址。这一点和PEB断链中,

​ ldr->Flink 与 _LDR_DATA_TABLE_ENTRY 首地址相等是一样的

(6)_EPROCESS 结构体中偏移0x88有一个 _LIST_ENTRY 结构体,该结构体保存了当前进程在进程链表中的位置信息

(7)节点指针指向的是 _LIST_ENTRY 结构体,该结构体存储了模块在链表中的位置信息

(8)通过 _EPROCESS 结构体中偏移0x174的 ImageFileName 确定所属进程, 并通过该结构体中的 _LIST_ENTRY结构体删除该节点在链表中的位置信息(双向循环链表删除节点),即可达到0环下的进程隐藏

KPRC(Kernel Processor Control Region, 内核处理器控制区域)结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kd> dt _kpcr
nt!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 DebugActive      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B
   +0x090 SecondLevelCacheSize : Uint4B
   +0x094 HalReserved      : [16] Uint4B
   +0x0d4 InterruptMode    : Uint4B
   +0x0d8 Spare1           : UChar
   +0x0dc KernelReserved2  : [17] Uint4B
   +0x120 PrcbData         : _KPRCB     // _KPRCB 结构体

_KPRCB 结构体:

kd> dt _KPRCB
ntdll!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD		// fs:[0x124]
   +0x008 NextThread       : Ptr32 _KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
    ... ...

_KTHREAD 结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
kd> dt _KTHREAD
ntdll!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 MutantListHead   : _LIST_ENTRY
   +0x018 InitialStack     : Ptr32 Void
   +0x01c StackLimit       : Ptr32 Void
   +0x020 Teb              : Ptr32 Void
   +0x024 TlsArray         : Ptr32 Void
   +0x028 KernelStack      : Ptr32 Void
   +0x02c DebugActive      : UChar
   +0x02d State            : UChar
   +0x02e Alerted          : [2] UChar
   +0x030 Iopl             : UChar
   +0x031 NpxState         : UChar
   +0x032 Saturation       : Char
   +0x033 Priority         : Char
   +0x034 ApcState         : _KAPC_STATE    // _KAPC_STATE 结构体
   +0x04c ContextSwitches  : Uint4B
    ... ...

_KAPC_STATE 结构体:

1
2
3
4
5
6
7
kd> dt _KAPC_STATE
ntdll!_KAPC_STATE
   +0x000 ApcListHead      : [2] _LIST_ENTRY
   +0x010 Process          : Ptr32 _KPROCESS    // _KTHREAD + 0x44 = _KPROCESS
   +0x014 KernelApcInProgress : UChar
   +0x015 KernelApcPending : UChar
   +0x016 UserApcPending   : UChar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
kd> dt _eprocess
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY      // 保存进程的双线循环链表结构体,与PEB中的ldr 结构体一样
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
   +0x0a8 CommitCharge     : Uint4B
   +0x0ac PeakVirtualSize  : Uint4B
   +0x0b0 VirtualSize      : Uint4B
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
   +0x0c0 ExceptionPort    : Ptr32 Void
   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : Uint4B
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : Uint4B
   +0x114 ForkInProgress   : Ptr32 _ETHREAD
   +0x118 HardwareTrigger  : Uint4B
   +0x11c VadRoot          : Ptr32 Void
   +0x120 VadHint          : Ptr32 Void
   +0x124 CloneRoot        : Ptr32 Void
   +0x128 NumberOfPrivatePages : Uint4B
   +0x12c NumberOfLockedPages : Uint4B
   +0x130 Win32Process     : Ptr32 Void
   +0x134 Job              : Ptr32 _EJOB
   +0x138 SectionObject    : Ptr32 Void
   +0x13c SectionBaseAddress : Ptr32 Void
   +0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
   +0x148 Win32WindowStation : Ptr32 Void
   +0x14c InheritedFromUniqueProcessId : Ptr32 Void
   +0x150 LdtInformation   : Ptr32 Void
   +0x154 VadFreeHint      : Ptr32 Void
   +0x158 VdmObjects       : Ptr32 Void
   +0x15c DeviceMap        : Ptr32 Void
   +0x160 PhysicalVadList  : _LIST_ENTRY
   +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
   +0x168 Filler           : Uint8B
   +0x170 Session          : Ptr32 Void
   +0x174 ImageFileName    : [16] UChar         // 进程名称
   +0x184 JobLinks         : _LIST_ENTRY
   +0x18c LockedPagesList  : Ptr32 Void
   +0x190 ThreadListHead   : _LIST_ENTRY
   +0x198 SecurityPort     : Ptr32 Void
   +0x19c PaeTop           : Ptr32 Void
   +0x1a0 ActiveThreads    : Uint4B
   +0x1a4 GrantedAccess    : Uint4B
   +0x1a8 DefaultHardErrorProcessing : Uint4B
   +0x1ac LastThreadExitStatus : Int4B
   +0x1b0 Peb              : Ptr32 _PEB         // 3环的PEB地址
   +0x1b4 PrefetchTrace    : _EX_FAST_REF
    ... ...

EPROCESS断链源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <ntddk.h>
 
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path);
NTSTATUS DriverUnload(PDRIVER_OBJECT driver);
 
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    UNREFERENCED_PARAMETER(reg_path);
 
    PEPROCESS pEprocess, pCurProcess;
    PCHAR ImageFileName;
 
    DbgBreakPoint();
 
    __asm
    {
        mov eax, fs: [0x124] ;      // 获取指向 _KTHREAD 的指针
        mov eax, [eax + 0x44];      // 获取指向 _KPROCESS 的指针, 即EPROCESS 的首地址
        mov pEprocess, eax;
    }
    pCurProcess = pEprocess;
 
    do
    {
        ImageFileName = (PCHAR)pCurProcess + 0x174;     // 进程名
        if (strcmp(ImageFileName, "notepad.exe") == 0)
        {
            PLIST_ENTRY curNode;
 
            curNode = (PLIST_ENTRY)((ULONG)pCurProcess + 0x88);     // +88 指向链表结构体
 
            curNode->Flink->Blink = curNode->Blink;
            curNode->Blink->Flink = curNode->Flink;
 
            DbgPrint("断链成功!\n");
            break;
        }
        pCurProcess = (PEPROCESS)(*(PULONG)((ULONG)pCurProcess + 0x88) - 0x88);  // 更新进程
 
    } while (pEprocess != pCurProcess);
 
    driver->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}
 
NTSTATUS DriverUnload(PDRIVER_OBJECT driver)
{
    UNREFERENCED_PARAMETER(driver);
    DbgPrint("驱动卸载成功\n");
    return STATUS_SUCCESS;
}

关键代码解释:

(1)更新pCurProcess的说明

1
2
3
// + 0x88:从 _LIST_ENTRY结构体中的Flink 指向的是下一个进程的双向循环链表结构体首地址
// - 0x88:链表指向的是下一个进程结构体+88的位置,-0x88让指针指向EPROCESS的首地址
pCurProcess = (PEPROCESS)(*(PULONG)((ULONG)pCurProcess + 0x88) - 0x88);

(2)获取EPRCESS的两种办法

第1种:通过内核函数 PsGetCurrentProcess。原理已在前面部分解释

1
2
3
4
kd> u psgetcurrentprocess
nt!PsGetCurrentProcess:
804ef608 64a124010000    mov     eax,dword ptr fs:[00000124h]   // 获取指向 _KTHREAD 的指针
804ef60e 8b4044          mov     eax,dword ptr [eax+44h]        // 获取指向 _KPROCESS 的指针, 即EPROCESS 的首地址

第2种:

获取进程模块的步骤为:获取 KPCR -> KTHREAD-> ETHREAD -> EPROCESS

对应的汇编是:

1
2
3
4
5
6
__asm
{
    mov eax, fs: [0x124] ;      // 获取指向 _KTHREAD 的指针, 即 ETHREAD 的首地址。原理与上面一样
    mov eax, [eax + 0x220];     // ETHREAD + 0x220  -> ThreadsProcess : Ptr32 _EPROCESS
    mov pEprocess, eax;
}

_ETHREAD 结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kd> dt _EThread
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD           // _KTHREAD 结构体
   +0x1c0 CreateTime       : _LARGE_INTEGER
   +0x1c0 NestedFaultCount : Pos 0, 2 Bits
   +0x1c0 ApcNeeded        : Pos 2, 1 Bit
   +0x1c8 ExitTime         : _LARGE_INTEGER
   +0x1c8 LpcReplyChain    : _LIST_ENTRY
   +0x1c8 KeyedWaitChain   : _LIST_ENTRY
   +0x1d0 ExitStatus       : Int4B
   +0x1d0 OfsChain         : Ptr32 Void
   +0x1d4 PostBlockList    : _LIST_ENTRY
   +0x1dc TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x1dc ReaperLink       : Ptr32 _ETHREAD
   +0x1dc KeyedWaitValue   : Ptr32 Void
   +0x1e0 ActiveTimerListLock : Uint4B
   +0x1e4 ActiveTimerListHead : _LIST_ENTRY
   +0x1ec Cid              : _CLIENT_ID
   +0x1f4 LpcReplySemaphore : _KSEMAPHORE
   +0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
   +0x208 LpcReplyMessage  : Ptr32 Void
   +0x208 LpcWaitingOnPort : Ptr32 Void
   +0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
   +0x210 IrpList          : _LIST_ENTRY
   +0x218 TopLevelIrp      : Uint4B
   +0x21c DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x220 ThreadsProcess   : Ptr32 _EPROCESS        // PPEB
   +0x224 StartAddress     : Ptr32 Void
    ... ...
  1. 总结

(1)隐藏模块或进程就是一个断链的过程,将自身节点从双向循环链表中删除就可以达到隐藏的效果

(2)破坏双向循环链表的连续性就可以达到隐藏全部的效果

(3)为什么删除进程的节点后,程序任然可以运行?这是因为CPU调度的基本单位是线程,和进程无关

(4)找到EPROCESS也有多种方法


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2023-9-4 20:55 被ATrueMan编辑 ,原因: 格式
收藏
点赞6
打赏
分享
最新回复 (6)
雪    币: 310
活跃值: (1917)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 2023-9-4 21:55
2
0
mark
雪    币: 19431
活跃值: (29092)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-9-5 10:03
3
1
mark
雪    币: 2502
活跃值: (2753)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
院士 2023-9-5 12:57
4
0
先收藏,感谢分享。
雪    币: 6124
活跃值: (4081)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
黑洛 1 2023-9-14 01:42
5
0
?
雪    币: 2140
活跃值: (3528)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
R0g 2 2023-9-14 03:02
6
0
?
雪    币: 126
活跃值: (907)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我的研究 2023-9-21 15:58
7
0
现在谁还玩xp,能不能来个64位下的R0 下的隐藏进程教教,不蓝屏的那种
游客
登录 | 注册 方可回帖
返回