TEB和PEB结构

TEB和PEB都在用户层(3环),通过断链实现的模块隐藏只能绕过应用层的api,内核层的VAD结构还是可以查询到模块名的,就算把VAD数抹掉了也可以通过遍历内存确定模块。

在内存中遍历,找到MZ字符,在MZ处往后偏移64个字节,加上此处的偏移得到PE两个字符,通过MZ和PE可以判断这是一个PE指纹,只要找到PE指纹那么就一定有一个未知的模块存在,MZ就是模块的首地址


TEB(Thread Environment Block),它记录的相关线程的信息,每一个线程都有自己的TEB,FS:[0]即是当前线程的TEB

1
mov eax,fs:[0]

TEB

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
101
102
103
104
105
106
107
108
109
110
ntdll!_TEB
+0x000 NtTib : _NT_TIB //TIB结构
[+0x000] ExceptionList : 0x1df360 [Type: _EXCEPTION_REGISTRATION_RECORD *]//指向SEH链
[+0x004] StackBase : 0x1e0000 [Type: void *]//堆栈基址
[+0x008] StackLimit : 0x1dd000 [Type: void *]//堆栈大小
[+0x00c] SubSystemTib : 0x0 [Type: void *]//
[+0x010] FiberData : 0x1e00 [Type: void *]
[+0x010] Version : 0x1e00 [Type: unsigned long]
[+0x014] ArbitraryUserPointer : 0x0 [Type: void *]
[+0x018] Self : 0x7ffde000 [Type: _NT_TIB *]//指向自身的指针,也就是说Self同时是指向TEB和TIB头部的指针(因为TIB为TEB结构的第一个成员)
+0x01c EnvironmentPointer : Ptr32 Void//环境指针
+0x020 ClientId : _CLIENT_ID//CLIENT_ID结构,存储PID和当前线程ID
[+0x000] UniqueProcess Ptr32 Void
[+0x004] UniqueThread Ptr32 Void
+0x028 ActiveRpcHandle : Ptr32 Void//活动的RPC句柄
+0x02c ThreadLocalStoragePointer : Ptr32 Void//指向线程局部存储数组
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB//指向PEB结构
+0x034 LastErrorValue : Uint4B//保存着LastError的值
+0x038 CountOfOwnedCriticalSections : Uint4B//所拥有的临界区数量
+0x03c CsrClientThread : Ptr32 Void//指向CSR客户线程
+0x040 Win32ThreadInfo : Ptr32 Void//指向Win32线程信息
+0x044 User32Reserved : [26] Uint4B
+0x0ac UserReserved : [5] Uint4B
+0x0c0 WOW32Reserved : Ptr32 Void
+0x0c4 CurrentLocale : Uint4B//当前的Locale
+0x0c8 FpSoftwareStatusRegister : Uint4B//FP软件状态寄存器
+0x0cc SystemReserved1 : [54] Ptr32 Void
+0x1a4 ExceptionCode : Int4B//异常码
+0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK//指向活动上下文栈的指针
+0x1ac SpareBytes : [36] UChar//空闲字节
+0x1d0 TxFsContext : Uint4B
+0x1d4 GdiTebBatch : _GDI_TEB_BATCH
+0x6b4 RealClientId : _CLIENT_ID
+0x6bc GdiCachedProcessHandle : Ptr32 Void
+0x6c0 GdiClientPID : Uint4B//真实的进程PID
+0x6c4 GdiClientTID : Uint4B//真实的线程TID
+0x6c8 GdiThreadLocalInfo : Ptr32 Void
+0x6cc Win32ClientInfo : [62] Uint4B
+0x7c4 glDispatchTable : [233] Ptr32 Void
+0xb68 glReserved1 : [29] Uint4B
+0xbdc glReserved2 : Ptr32 Void
+0xbe0 glSectionInfo : Ptr32 Void
+0xbe4 glSection : Ptr32 Void
+0xbe8 glTable : Ptr32 Void
+0xbec glCurrentRC : Ptr32 Void
+0xbf0 glContext : Ptr32 Void
+0xbf4 LastStatusValue : Uint4B
+0xbf8 StaticUnicodeString : _UNICODE_STRING
+0xc00 StaticUnicodeBuffer : [261] Wchar
+0xe0c DeallocationStack : Ptr32 Void
+0xe10 TlsSlots : [64] Ptr32 Void
+0xf10 TlsLinks : _LIST_ENTRY
+0xf18 Vdm : Ptr32 Void
+0xf1c ReservedForNtRpc : Ptr32 Void
+0xf20 DbgSsReserved : [2] Ptr32 Void
+0xf28 HardErrorMode : Uint4B
+0xf2c Instrumentation : [9] Ptr32 Void
+0xf50 ActivityId : _GUID
+0xf60 SubProcessTag : Ptr32 Void
+0xf64 EtwLocalData : Ptr32 Void
+0xf68 EtwTraceData : Ptr32 Void
+0xf6c WinSockData : Ptr32 Void
+0xf70 GdiBatchCount : Uint4B
+0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER
+0xf74 IdealProcessorValue : Uint4B
+0xf74 ReservedPad0 : UChar
+0xf75 ReservedPad1 : UChar
+0xf76 ReservedPad2 : UChar
+0xf77 IdealProcessor : UChar
+0xf78 GuaranteedStackBytes : Uint4B
+0xf7c ReservedForPerf : Ptr32 Void
+0xf80 ReservedForOle : Ptr32 Void
+0xf84 WaitingOnLoaderLock : Uint4B
+0xf88 SavedPriorityState : Ptr32 Void
+0xf8c SoftPatchPtr1 : Uint4B
+0xf90 ThreadPoolData : Ptr32 Void
+0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
+0xf98 MuiGeneration : Uint4B
+0xf9c IsImpersonating : Uint4B
+0xfa0 NlsCache : Ptr32 Void
+0xfa4 pShimData : Ptr32 Void
+0xfa8 HeapVirtualAffinity : Uint4B
+0xfac CurrentTransactionHandle : Ptr32 Void
+0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME
+0xfb4 FlsData : Ptr32 Void
+0xfb8 PreferredLanguages : Ptr32 Void
+0xfbc UserPrefLanguages : Ptr32 Void
+0xfc0 MergedPrefLanguages : Ptr32 Void
+0xfc4 MuiImpersonation : Uint4B
+0xfc8 CrossTebFlags : Uint2B
+0xfc8 SpareCrossTebBits : Pos 0, 16 Bits
+0xfca SameTebFlags : Uint2B
+0xfca SafeThunkCall : Pos 0, 1 Bit
+0xfca InDebugPrint : Pos 1, 1 Bit
+0xfca HasFiberData : Pos 2, 1 Bit
+0xfca SkipThreadAttach : Pos 3, 1 Bit
+0xfca WerInShipAssertCode : Pos 4, 1 Bit
+0xfca RanProcessInit : Pos 5, 1 Bit
+0xfca ClonedThread : Pos 6, 1 Bit
+0xfca SuppressDebugMsg : Pos 7, 1 Bit
+0xfca DisableUserStackWalk : Pos 8, 1 Bit
+0xfca RtlExceptionAttached : Pos 9, 1 Bit
+0xfca InitialThread : Pos 10, 1 Bit
+0xfca SpareSameTebBits : Pos 11, 5 Bits
+0xfcc TxnScopeEnterCallback : Ptr32 Void
+0xfd0 TxnScopeExitCallback : Ptr32 Void
+0xfd4 TxnScopeContext : Ptr32 Void
+0xfd8 LockCount : Uint4B
+0xfdc SpareUlong0 : Uint4B
+0xfe0 ResourceRetValue : Ptr32 Void

PEB

PEB(PROCESS Environment BLock,进程环境块)存放进程信息,每个进程都有自己的PEB信息,TEB偏移0x30即当前进程的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
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
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
+0x020 AtlThunkSListPtr : Ptr32 Void
+0x024 IFEOKey : Ptr32 Void
+0x028 CrossProcessFlags : Uint4B
+0x028 ProcessInJob : Pos 0, 1 Bit
+0x028 ProcessInitializing : Pos 1, 1 Bit
+0x028 ProcessUsingVEH : Pos 2, 1 Bit
+0x028 ProcessUsingVCH : Pos 3, 1 Bit
+0x028 ProcessUsingFTH : Pos 4, 1 Bit
+0x028 ReservedBits0 : Pos 5, 27 Bits
+0x02c KernelCallbackTable : Ptr32 Void
+0x02c UserSharedInfoPtr : Ptr32 Void
+0x030 SystemReserved : [1] Uint4B
+0x034 AtlThunkSListPtr32 : Uint4B
+0x038 ApiSetMap : Ptr32 Void
+0x03c TlsExpansionCounter : Uint4B
+0x040 TlsBitmap : Ptr32 Void
+0x044 TlsBitmapBits : [2] Uint4B
+0x04c ReadOnlySharedMemoryBase : Ptr32 Void
+0x050 HotpatchInformation : Ptr32 Void
+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
+0x058 AnsiCodePageData : Ptr32 Void
+0x05c OemCodePageData : Ptr32 Void
+0x060 UnicodeCaseTableData : Ptr32 Void
+0x064 NumberOfProcessors : Uint4B
+0x068 NtGlobalFlag : Uint4B
+0x070 CriticalSectionTimeout : _LARGE_INTEGER
+0x078 HeapSegmentReserve : Uint4B
+0x07c HeapSegmentCommit : Uint4B
+0x080 HeapDeCommitTotalFreeThreshold : Uint4B
+0x084 HeapDeCommitFreeBlockThreshold : Uint4B
+0x088 NumberOfHeaps : Uint4B
+0x08c MaximumNumberOfHeaps : Uint4B
+0x090 ProcessHeaps : Ptr32 Ptr32 Void
+0x094 GdiSharedHandleTable : Ptr32 Void
+0x098 ProcessStarterHelper : Ptr32 Void
+0x09c GdiDCAttributeList : Uint4B
+0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION
+0x0a4 OSMajorVersion : Uint4B
+0x0a8 OSMinorVersion : Uint4B
+0x0ac OSBuildNumber : Uint2B
+0x0ae OSCSDVersion : Uint2B
+0x0b0 OSPlatformId : Uint4B
+0x0b4 ImageSubsystem : Uint4B
+0x0b8 ImageSubsystemMajorVersion : Uint4B
+0x0bc ImageSubsystemMinorVersion : Uint4B
+0x0c0 ActiveProcessAffinityMask : Uint4B
+0x0c4 GdiHandleBuffer : [34] Uint4B
+0x14c PostProcessInitRoutine : Ptr32 void
+0x150 TlsExpansionBitmap : Ptr32 Void
+0x154 TlsExpansionBitmapBits : [32] Uint4B
+0x1d4 SessionId : Uint4B
+0x1d8 AppCompatFlags : _ULARGE_INTEGER
+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
+0x1e8 pShimData : Ptr32 Void
+0x1ec AppCompatInfo : Ptr32 Void
+0x1f0 CSDVersion : _UNICODE_STRING
+0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
+0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
+0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
+0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
+0x208 MinimumStackCommit : Uint4B
+0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO
+0x210 FlsListHead : _LIST_ENTRY
+0x218 FlsBitmap : Ptr32 Void
+0x21c FlsBitmapBits : [4] Uint4B
+0x22c FlsHighIndex : Uint4B
+0x230 WerRegistrationData : Ptr32 Void
+0x234 WerShipAssertPtr : Ptr32 Void
+0x238 pContextData : Ptr32 Void
+0x23c pImageHeaderHash : Ptr32 Void
+0x240 TracingFlags : Uint4B
+0x240 HeapTracingEnabled : Pos 0, 1 Bit
+0x240 CritSecTracingEnabled : Pos 1, 1 Bit
+0x240 SpareTracingBits : Pos 2, 30 Bits

_PEB_LDR_DATA

_LDR_DATA_TABLE_ENTRY里面储存了模块的详细路径,将下面这几个双向链表断链可以达到隐藏模块的目的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ntdll!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
[+0x000] Flink : Ptr32 _LIST_ENTRY//指向下一个_LDR_DATA_TABLE_ENTRY结构的InLoadOrderLinks:_LIST_ENTRY
[+0x004] Blink : Ptr32 _LIST_ENTRY//指向上一个_LDR_DATA_TABLE_ENTRY结构的InLoadOrderLinks:_LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
[+0x000] Flink : Ptr32 _LIST_ENTRY//指向下一个_LDR_DATA_TABLE_ENTRY结构的InMemoryOrderLinks:_LIST_ENTRY
[+0x004] Blink : Ptr32 _LIST_ENTRY//指向上一个_LDR_DATA_TABLE_ENTRY结构的InMemoryOrderLinks:_LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
[+0x000] Flink : Ptr32 _LIST_ENTRY//指向上一个_LDR_DATA_TABLE_ENTRY结构的InInitializationOrderLinks:_LIST_ENTRY
[+0x004] Blink : Ptr32 _LIST_ENTRY//指向下一个_LDR_DATA_TABLE_ENTRY结构的InInitializationOrderLinks:_LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void
+0x028 ShutdownInProgress : UChar
+0x02c ShutdownThreadId : Ptr32 Void

_LDR_DATA_TABLE_ENTRY

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
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第一个_LIST_ENTRY结构指向这里
+0x008 InMemoryOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第二个_LIST_ENTRY结构指向这里
+0x010 InInitializationOrderLinks : _LIST_ENTRY//_PEB_LDR_DATA的第三个_LIST_ENTRY结构指向这里
+0x018 DllBase : Ptr32 Void//DLL基址
+0x01c EntryPoint : Ptr32 Void
+0x020 SizeOfImage : Uint4B
+0x024 FullDllName : _UNICODE_STRING//带路径的dll的名称
+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 _ACTIVATION_CONTEXT
+0x04c PatchInformation : Ptr32 Void
+0x050 ForwarderLinks : _LIST_ENTRY
+0x058 ServiceTagLinks : _LIST_ENTRY
+0x060 StaticLinks : _LIST_ENTRY
+0x068 ContextInformation : Ptr32 Void
+0x06c OriginalBase : Uint4B
+0x070 LoadTime : _LARGE_INTEGER


实现模块隐藏

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
101
102
103
104
105
106
107
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>

/*
_LDR_DATA_TABLE_ENTRY结构中储存的_UNICODE_STRING类型*/

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}UNICODE_STRING, *PUNICODE_STRING;

typedef struct _PEB_LDR_DATA {
ULONG Length;
UCHAR Initialized;
PVOID Sshandle;
/*3个双向链表*/
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
}PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;//_PEB_LDR_DATA的第一个_LIST_ENTRY结构指向这里
LIST_ENTRY InMemoryOrderLinks; //_PEB_LDR_DATA的第二个_LIST_ENTRY结构指向这里
LIST_ENTRY InInitializationOrderLinks;//_PEB_LDR_DATA的第三个_LIST_ENTRY结构指向这里
PVOID BaseAddress;//该模块的基址
PVOID EntryPoint;//该模块的入口
ULONG SizeOfImage;//该模块的影像大小
UNICODE_STRING FullDllName;//带路径的模块名称
UNICODE_STRING BaseDllName;//不包含路径的模块名
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
PVOID SectionPointer;
ULONG CheckSum;
ULONG TimeDateStamp;
}LDR_MODULE, *PLDR_MODULE;

void hideModule(CONST CHAR *szModuleName) {
HANDLE hMod = ::GetModuleHandle(szModuleName);
PLIST_ENTRY head, cur;
PPEB_LDR_DATA pLdr;
PLDR_MODULE pLdrMod;

__asm {
/*fs:[0]储存是的TEB,偏移0x30得到PEB*/
mov eax, fs : [0x30]
/*偏移0x0c得到_PEB_LDR_DATA的地址*/
mov ecx, [eax + 0x0c]
/*将得到的地址储存到C变量中*/
mov pLdr, ecx
}

//指向InLoadOrderModuleList的指针
head = &(pLdr->InLoadOrderModuleList);
//指向下一个_LDR_DATA_TABLE_ENTRY结构
cur = head->Flink;



//遍历当前模块名
do {

//CONTAINING_RECORD宏,找到cur所在结构体的首地址
pLdrMod = CONTAINING_RECORD(cur, LDR_MODULE, InLoadOrderLinks);

//断链实现隐藏模块

/*
将上一个节点的Flink指向其自身的Flink,反方向同理,将其越过去*/
if (pLdrMod->BaseAddress == hMod) {
pLdrMod->InLoadOrderLinks.Blink->Flink =
pLdrMod->InLoadOrderLinks.Flink;
pLdrMod->InLoadOrderLinks.Flink->Blink =
pLdrMod->InLoadOrderLinks.Blink;
pLdrMod->InMemoryOrderLinks.Blink->Flink =
pLdrMod->InMemoryOrderLinks.Flink;
pLdrMod->InMemoryOrderLinks.Flink->Blink =
pLdrMod->InMemoryOrderLinks.Blink;
pLdrMod->InInitializationOrderLinks.Blink->Flink =
pLdrMod->InInitializationOrderLinks.Flink;
pLdrMod->InInitializationOrderLinks.Flink->Blink =
pLdrMod->InInitializationOrderLinks.Blink;

break;
}

/*将其指向下一个节点*/
cur = cur->Flink;
} while (head != cur);
}

int main()
{

printf("***********按任意键隐藏模块***********\n");
getchar();
hideModule("kernel32.dll");

/*阻塞调试*/
getchar();
return 0;
}


执行程序后kernel32模块不见了。