2015-08-01

Peb(Process Environment Block)简单学习及分析

文章目录
  1. 1. PEB结构初探
  2. 2. Peb应用程序代码

参考资料:
Google peb site:pediy.com
PEB结构——枚举用户模块列表
修改已加载DLL的模块名和路径

PEB结构初探

windows系统中通过各种结构来管理各个对象,关于进程线程的PEB、TEB、EPROCESS等,这几个结构的关系如下图


PEB、TEB、EPROCESS结构在系统结构中关系

而PEB(Process Environment Block)——进程环境块使用较多,并且我们可以找到很多关于PEB的资料并且用处也很大,它包含了映像加载器、堆管理器和其他的windows系统DLL所需要的信息,因为它们需要在用户模式下修改PEB中的信息,所以必须位于用户空间。PEB存放进程信息,每个进程都有自己的 PEB 信息。准确的 PEB 地址应从系统的 EPROCESS 结构的 1b0H 偏移处获得,但由于 EPROCESS在进程的核心内存区,所以程序不能直接访问。但是由上面的关系图可以发现TEB也指向PEB结构同时位于用户空间并且可以很方便的获得,可以通过CPU的FS寄存器来访问TEB,一般存储在[FS:0],在TEB结构偏移30H处可以获得PEB位置
1
2
3
4
5
__asm
{
mov eax,fs:[0x30]
mov PEB,eax
}


除此之外还可以通过以下方式获得PEB结构
- 在内核中我们可以先PsGetCurrentProcess得到当前进程的EPROCESS,然后通过它的成员域PEB访问到当前进程
- 在内核中,我们可以通过KPRCB获得当前线程的ETHREAD,然后通过它的成员域来访问当TEB,然后再通过TEB的成员域来访问PEB

##PEB结构体
###_PEB
PEB结构体

上图是PEB结构各个元素关系图,可以对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
MSDN文档中结构体不是很详细,所以PEB结构现在也属于一个未公开结构体。
32位系统
typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged; 标识当前进程是否被调试,在反调试
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr; 
  PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
  BYTE                          Reserved4[104];
  PVOID                         Reserved5[52];
  PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
  BYTE                          Reserved6[128];
  PVOID                         Reserved7[1];
  ULONG                         SessionId;
} PEB, *PPEB;
64位系统
typedef struct _PEB {
    BYTE Reserved1[2];
    BYTE BeingDebugged;
    BYTE Reserved2[21];
    PPEB_LDR_DATA LoaderData;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
    BYTE Reserved3[520];
    PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
    BYTE Reserved4[136];
    ULONG SessionId;
} PEB;
根据reactos来的结构定义
typedef struct _PEB {
+0x000 BOOLEAN InheritedAddressSpace;
+0x001 BOOLEAN ReadImageFileExecOptions;
+0x002 BOOLEAN BeingDebugged; 			标志当前进程是否被调试
+0x003 BOOLEAN Spare;
+0x004 HANDLE Mutant;
+0x008 PVOID ImageBaseAddress; 		进程的映像基地址,exe 0x400000,dll 0x1000000
+0x00c PPEB_LDR_DATA LoaderData; 		由PE Loader填充,包含很多pe中包含的信息,用来枚举用户加载的模块
+0x010 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 指向  RTL_USER_PROCESS_PARAMETERS 的指针,RTL_USER_PROCESS_PARAMETERS 中是一些进程的参数。
+0x014 PVOID SubSystemData;
PVOID ProcessHeap;  			指向进程堆首地址,每个程序新建时默认堆使用
PVOID FastPebLock;  			存放的是PEBLOCKROUTINE这个例程函数需要用到的参数。
PPEBLOCKROUTINE FastPebLockRoutine;   PEB加锁/解锁回调例程
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount; 	进程的环境变量更改的次数
PPVOID KernelCallbackTable;		从内核“回调”用户空间的函数
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter; 
PVOID TlsBitmap;                 域代表TLS位图
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PPVOID ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PPVOID *ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;


由上面结构体中可以发现PEB结构成员众多且还属于未公开结构体,但是微软也公开了一些结构。其中PPEB_LDR_DATA是本篇主要讨论的
###PPEB_LDR_DATA
msdn.aspx)
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
typedef struct _PEB_LDR_DATA {
  BYTE       Reserved1[8];
  PVOID      Reserved2[3];
  LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

ReactOS
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 _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;

} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

typedef struct _LDR_MODULE {
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID BaseAddress;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;    模块全路径
    UNICODE_STRING BaseDllName;	   模块名称
    ULONG Flags;
    SHORT LoadCount;
    SHORT TlsIndex;
    LIST_ENTRY HashTableEntry;
    ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;



从PEB到Ldr_module

上图展示了从PEB——->PEB_LDR_DATA———>LDR_MODULE的过程,LDR_MODULE中容纳的是进程中各个dll的信息最后通过LIST_ENTRY形成双向链表将各个dll信息连接起来。我们就可以通过上面的方式找到各个dll模块然后将信息打印出来,形成自己的模块遍历程序。
同时我们也可以通过修改或则删除某些dll模块信息达到隐藏dll目的。

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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//AboutPeb.h
#ifndef _ABOUT_PEB_
#define _ABOUT_PEB_
#include 
#include 
#include 

typedef struct _MYPEB_LDR_DATA
{
	ULONG Length;
	BOOLEAN Initialized;
	PVOID SsHandle;
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
}MYPEB_LDR_DATA,*PMYPEB_LDR_DATA;
typedef struct _MYLDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	WORD LoadCount;
	WORD TlsIndex;
	union
	{
		LIST_ENTRY HashLinks;
		struct
		{
			PVOID SectionPointer;
			ULONG CheckSum;
		};
	};
	union
	{
		ULONG TimeDateStamp;
		PVOID LoadedImports;
	};
	_ACTIVATION_CONTEXT * EntryPointActivationContext;
	PVOID PatchInformation;
	LIST_ENTRY ForwarderLinks;
	LIST_ENTRY ServiceTagLinks;
	LIST_ENTRY StaticLinks;
} MYLDR_DATA_TABLE_ENTRY, *PMYLDR_DATA_TABLE_ENTRY;


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;

typedef struct {
	DWORD InLoadNext;
	DWORD InLoadPrev;

	DWORD InMemNext;
	DWORD InMemPrev;

	DWORD InInitNext;
	DWORD InInitPrev;

	DWORD ImageBase;          //模块基地址

	PVOID EntryPoint;

	ULONG SizeOfImage;

	UNICODE_STRING FullDllName;

	UNICODE_STRING BaseDllName;
} PEB_LIST_ENTRY, *PPEB_LIST_ENTRY;


//声明一些函数

PEB_LIST_ENTRY *GetPEBAdd();
void ListDllModByPeb();
BOOL ModifyDllInfoByPeb(HMODULE hMod,PWSTR pFakename,PWSTR pFakePath);
//dll模块的隐藏  Toolhelp--->InLoadOrderModuleList psapi--->InMemoryOrderModuleList       http://bbs.pediy.com/showthread.php?t=59932
//win7  [psapi]EnumProcessModules-->[KERNEL32.dll]K32EnumProcessModules(x,x,x,x)--->EnumProcessModulesInternal----->NtQueryInformationProcess[BOOL GetPebbyNativeApi(DWORD dwPid)基本类似]
BOOL HiddeDllByRemovePebList(HMODULE hMod);
BOOL HidebyPeb(HANDLE hprocess,HMODULE hmodhid);

//http://www.cnblogs.com/boyxiao/archive/2011/02/27/1966383.html
void ListProcessByApi(DWORD dwPid);

//IsDebugerPresent peb反调试 学习 http://www.cnblogs.com/this-543273659/archive/2013/03/04/2943380.html

//peb 另外一种获取方式 NtQueryInformationProcess   [PEB]获取进程完整路径探索
BOOL GetPebbyNativeApi(DWORD dwPid);

//通过peb写通用 shellcode  WinXP/Win7/Win8通用shellcode_Dream  http://www.freebuf.com/articles/system/58920.html  http://blog.csdn.net/wowolook/article/details/8747586

//反peb隐藏  通过VirtualQueryEx函数列举出进程内虚拟内存的段,然后根据PE结构和内存属性来定位Image文件的映像基地址
//http://www.blogfshare.com/enumprocess-by-search.html   http://www.blogfshare.com/activeprocesslinks-dkom.html

//调试ldr链接  http://bbs.pediy.com/showthread.php?t=149527   http://blog.csdn.net/hgy413/article/details/8490918  http://bbs.pediy.com/showthread.php?t=175833

//高级玩法  https://github.com/David-Reguera-Garcia-Dreg/phook

#endif

——————————————-代码—————————————————-

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
// AboutPeb.cpp : 定义控制台应用程序的入口点。
//
#include "StdAfx.h"
#include "AboutPeb.h"
#include 
void bugW( LPWSTR format, ... )
{
	va_list args;
	va_start(args, format);
	WCHAR wszMsg[1024] = {0};
	wvsprintfW(wszMsg, format, args);
	va_end(args);

	OutputDebugStringW(wszMsg);
}
PEB_LIST_ENTRY *GetPEBAdd()
{
	DWORD Loaded_Head;
	DWORD **pPEB;
	DWORD *Ldr;

	__asm {
		MOV EAX,30h
			MOV EAX,DWORD PTR FS:[EAX]  //获得peb首地址 PEB = FS:0x30
		ADD EAX, 08h                //保存模块基址 Imagebaseaddress
			MOV SS:[pPEB], EAX
	}

	Ldr = *(pPEB + 1);
	Loaded_Head = *(Ldr + 3);
	return (PEB_LIST_ENTRY *)Loaded_Head;
}
void ListDllModByPeb()
{
	MYPEB_LDR_DATA *pPEBLDR;
	LDR_MODULE *pLdrMod;
	LIST_ENTRY *pListEntry,*pStart;

	_asm
	{
		mov eax,fs:[0x30] //TEB->PEB
		mov eax,[eax+0xC] //PEB->Ldr
		mov pPEBLDR,eax
	}
	//通过InLoadOrderModuleList遍历
	printf("\n\t-----InLoadOrderModuleList-----\n");
	pStart=pListEntry=(LIST_ENTRY*)(PUCHAR)&(pPEBLDR->InLoadOrderModuleList);//0x773a8b4c
	pListEntry=pListEntry->Flink;
	for (int i=0;pListEntry!=pStart;pListEntry=pListEntry->Flink)
	{
		++i;
		pLdrMod=(LDR_MODULE*)(pListEntry);//0x773a8b40
		printf("%d:名称:%010ws,基地址:0x%010x,模块大小:%010x\n模块路径:%ws\n\n",
			i,pLdrMod->BaseDllName.Buffer,pLdrMod->BaseAddress,
			pLdrMod->SizeOfImage,pLdrMod->FullDllName.Buffer);
	}


	////通过InLoadOrderModuleList遍历
	//printf("\n\t-----InMemoryOrderModuleList-----\n");
	//pStart=pListEntry=(LIST_ENTRY*)(PUCHAR)&(pPEBLDR->InMemoryOrderModuleList);//0x773a8b4c
	//pListEntry=pListEntry->Flink;
	//for (int i=0;pListEntry!=pStart;pListEntry=pListEntry->Flink)
	//{
	//	++i;
	//	pLdrMod=(LDR_MODULE*)(pListEntry-sizeof(LIST_ENTRY));
	//	printf("%d:名称:%010ws,基地址:0x%010x,模块大小:%010x\n模块路径:%ws\n\n",
	//		i,pLdrMod->BaseDllName.Buffer,pLdrMod->BaseAddress,
	//		pLdrMod->SizeOfImage,pLdrMod->FullDllName.Buffer);
	//}

}
BOOL ModifyDllInfoByPeb(HMODULE hMod,PWSTR pFakename,PWSTR pFakePath)
{
	MYPEB_LDR_DATA *pPEBLDR;
	LDR_MODULE *pLdrMod;
	LIST_ENTRY *pListEntry,*pStart;
	DWORD dwKernelBase;
	PWSTR fakemodulename=pFakename;
	PWSTR fakemodulepath=pFakePath;
	BOOL bRet=FALSE;
	_asm
	{
		mov eax,fs:[0x30] //TEB->PEB
		mov eax,[eax+0xC] //PEB->Ldr
		mov pPEBLDR,eax
	}
	dwKernelBase=(DWORD)hMod;
	pStart=pListEntry=(LIST_ENTRY*)(PUCHAR)&(pPEBLDR->InLoadOrderModuleList);
	do 
	{
		pListEntry=pListEntry->Flink;
		pLdrMod=(LDR_MODULE*)(pListEntry);
		if ((DWORD)pLdrMod->BaseAddress==dwKernelBase)
		{
			lstrcpyW(pLdrMod->BaseDllName.Buffer,fakemodulename);
			lstrcpyW(pLdrMod->FullDllName.Buffer,fakemodulepath);
			bRet=TRUE;
			break;
		}

	} while(pListEntry!=pStart);
	return bRet;
}

BOOL HiddeDllByRemovePebList(HMODULE hMod)
{
	PEB_LIST_ENTRY *Depends_List, *List_Head;
	PEB_LIST_ENTRY *prev, *next;
	bool bRet=false;

	Depends_List = List_Head = GetPEBAdd();
	do {
		if (Depends_List->ImageBase == (DWORD)hMod) {

			//1
			prev = (PEB_LIST_ENTRY *) Depends_List->InLoadPrev;
			next = (PEB_LIST_ENTRY *) Depends_List->InLoadNext;
			if (prev)
				prev->InLoadNext = (DWORD)next;
			if (next)
				next->InLoadPrev = (DWORD)prev;

			prev = (PEB_LIST_ENTRY *) (Depends_List->InMemPrev - 8);
			next = (PEB_LIST_ENTRY *) (Depends_List->InMemNext - 8);

			//2
			if (Depends_List->InMemPrev) {
				if (Depends_List->InMemNext)
					prev->InMemNext = ((DWORD)next) + 8;
				else
					prev->InMemNext = NULL;
			}

			if (Depends_List->InMemNext) {
				if (Depends_List->InMemPrev)
					next->InMemPrev = ((DWORD)prev) + 8;
				else 
					next->InMemPrev = NULL;
			}

			//3
			prev = (PEB_LIST_ENTRY *) (Depends_List->InInitPrev - 16);
			next = (PEB_LIST_ENTRY *) (Depends_List->InInitNext - 16);

			if (Depends_List->InInitPrev) {
				if (Depends_List->InInitNext)
					prev->InInitNext = ((DWORD)next) + 16;
				else
					prev->InInitNext = NULL;
			}

			if (Depends_List->InInitNext) {
				if (Depends_List->InInitPrev)
					next->InInitPrev = ((DWORD)prev) + 16;
				else 
					next->InInitPrev = NULL;
			}
			bRet=true;
			break;			
		}
		Depends_List = (PEB_LIST_ENTRY *)Depends_List->InLoadNext;
	} while(List_Head != Depends_List); 

	return bRet;
}
BOOL HidebyPeb(HANDLE hprocess,HMODULE hmodhid)
{
	HMODULE hMod = GetModuleHandle( _T( "ntdll.dll"));
	HMODULE hModMyself = hmodhid;//GetModuleHandle( _T("dll.dll"));
	LONG (WINAPI *pfnNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
	pfnNtQueryInformationProcess= (LONG (WINAPI *)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG))GetProcAddress( hMod, "NtQueryInformationProcess");

	PROCESS_BASIC_INFORMATION stInfo = {0};
	DWORD dwRetnLen = 0;
	DWORD dw = pfnNtQueryInformationProcess( hprocess, ProcessBasicInformation, &stInfo, sizeof(stInfo), &dwRetnLen);

	//获得peb的指针
	PPEB pPeb = stInfo.PebBaseAddress;
	PLIST_ENTRY ListHead, Current;
	PMYLDR_DATA_TABLE_ENTRY pstEntry = NULL;
	//完整定义 http://bbs.pediy.com/showthread.php?t=149527
	ListHead = &(PMYPEB_LDR_DATA(stInfo.PebBaseAddress->Ldr)->InLoadOrderModuleList);
	Current = ListHead->Flink;
	while ( Current != ListHead)
	{   //修改系统的  取得内存中任何结构体的首地址(结构体中某个成员(field)的地址,结构体的类型type,要得到地址那个成员的名字field)
		pstEntry = CONTAINING_RECORD( Current, MYLDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
		//OutputDebugStringW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
		if ( pstEntry->DllBase == hModMyself)
		{
			pstEntry->InLoadOrderLinks.Flink->Blink = pstEntry->InLoadOrderLinks.Blink;
			pstEntry->InLoadOrderLinks.Blink->Flink = pstEntry->InLoadOrderLinks.Flink;
			OutputDebugString( _T( "Hide injected dll."));
			break;
		}
		Current = pstEntry->InLoadOrderLinks.Flink;
	}

	ListHead = &( stInfo.PebBaseAddress->Ldr->InMemoryOrderModuleList);
	Current = ListHead->Flink;
	while ( Current != ListHead)
	{
		pstEntry = CONTAINING_RECORD( Current, MYLDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList);
		bugW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
		if ( pstEntry->DllBase == hModMyself)
		{
			pstEntry->InMemoryOrderModuleList.Flink->Blink = pstEntry->InMemoryOrderModuleList.Blink;
			pstEntry->InMemoryOrderModuleList.Blink->Flink = pstEntry->InMemoryOrderModuleList.Flink;
			OutputDebugString( _T( "Hide injected dll."));
			break;
		}
		Current = pstEntry->InMemoryOrderModuleList.Flink;
	}
	OutputDebugStringW( L"\r\n");

	ListHead = &(PMYPEB_LDR_DATA(stInfo.PebBaseAddress->Ldr)->InInitializationOrderModuleList);
	Current = ListHead->Flink;
	while ( Current != ListHead)
	{
		pstEntry = CONTAINING_RECORD( Current, MYLDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
		bugW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint);
		if ( pstEntry->DllBase == hModMyself)
		{
			pstEntry->InInitializationOrderModuleList.Flink->Blink = pstEntry->InInitializationOrderModuleList.Blink;
			pstEntry->InInitializationOrderModuleList.Blink->Flink = pstEntry->InInitializationOrderModuleList.Flink;
			OutputDebugString( _T( "Hide injected dll."));
			break;
		}
		Current = pstEntry->InInitializationOrderModuleList.Flink;
	}
	//OutputDebugString( _T("Out HideMyself\r\n"));
	return TRUE;
}

//EnumProcessModulesInternal 类似
BOOL GetPebbyNativeApi(DWORD dwPid)
{
	BOOL bRet=FALSE;

	DWORD dwParentPid=0;

	PROCESS_BASIC_INFORMATION pi;
	ZeroMemory(&pi,sizeof(pi));

	DWORD LoaderData=0;
	DWORD InMemoryOrderModuleList=0;
	UNICODE_STRING usImagePath;
	WCHAR ImagePath[MAX_PATH]={0};
	usImagePath.MaximumLength=MAX_PATH;
	HANDLE hProcess=NULL;
	//定义函数指针 Winternl.h 中有定义这里动态获取
	LONG (WINAPI *PNtQueryinfomationProcess)(HANDLE,PROCESSINFOCLASS,
		PVOID,ULONG,PULONG);
	do 
	{
		hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,dwPid);
		if (hProcess==NULL)
		{
			printf("open process errno:%d",GetLastError());
			continue;
		}
		
		//获取函数地址
		PNtQueryinfomationProcess=(LONG (WINAPI *)(HANDLE,PROCESSINFOCLASS,
			PVOID,ULONG,PULONG))GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtQueryInformationProcess");
		if (PNtQueryinfomationProcess==NULL)
		continue;

		if (PNtQueryinfomationProcess(hProcess,ProcessBasicInformation,&pi,
			sizeof(pi),NULL)==0)
		{
			//读取LoaderData
			if (!ReadProcessMemory(hProcess,(PVOID*)((DWORD)pi.PebBaseAddress
				+0xc),&LoaderData,sizeof(DWORD),NULL))
				continue;
			 // 读取 InMemoryOrderModuleList
			if (!ReadProcessMemory(hProcess,(PVOID *)((DWORD)LoaderData+0x14),
				&InMemoryOrderModuleList,sizeof(DWORD),NULL))
				continue;
			if (!ReadProcessMemory(hProcess,(PVOID *)((DWORD)InMemoryOrderModuleList+0x1c),
				&usImagePath,sizeof(UNICODE_STRING),NULL))
				continue;
			// 读取真正的路径
			if (!ReadProcessMemory(hProcess,usImagePath.Buffer,&ImagePath,
				MAX_PATH,NULL))
				continue;

		}
		else
			continue;
		bRet=TRUE;
	} while (FALSE);

	if (bRet)
	{
		//从PROCESS_BASIC_INFORMATION Reserved3是父进程pid 可以修改父进程pid试试  通过TlHelp32.h也能获取到父进程pid Process32FirstW(hSnapProcess, &ProcessEntry); PROCESSENTRY32W
		//pi.Reserved3=000; 修改这个对大部分ark没用,其他地方肯定还有备份 利用监视某个进程的退出WaitForSingleObject(ParentHandle, INFINITE)
		printf("父进程pid:%u\n",(DWORD)pi.Reserved3);
		printf("路径by InMemoryOrderModuleList\n%-10d%ws\n",dwPid,ImagePath);


	   //CheckRemoteDebuggerPresent 功能相同
	   printf("\n是否被调试by peb->BeingDebugged:%u\n",pi.PebBaseAddress->BeingDebugged);

		
		//printf("\n\t-------ProcessParameters-----\n");
		PRTL_USER_PROCESS_PARAMETERS pParam=NULL;
		pParam=pi.PebBaseAddress->ProcessParameters;
		
		WCHAR wszfakepath[MAX_PATH]=L"C:xxxx\\xxxx.exe";
		lstrcpyW(pParam->ImagePathName.Buffer,wszfakepath);
		printf("路径by ProcessParameters\n%-10d%ws\n",dwPid,pParam->ImagePathName.Buffer);
		printf("命令行%ws\n",pParam->CommandLine.Buffer);
	}
	else
		printf("errno\n");

	if (hProcess)
	{
		CloseHandle(hProcess);
	}
	WCHAR wszmypath[MAX_PATH]={0};
	//win10即使断链了也能正常获取 其他系统不行  win10应该是通过ProcessParameters获得的
	GetModuleFileNameW(GetModuleHandleA("AboutPeb.exe"),wszmypath,sizeof(wszmypath));
	printf("路径by GetModuleFileNameW\n%-10d%ws\n",dwPid,wszmypath);

	return bRet;
}

void ListProcessByApi(DWORD dwPid)
{
	BOOL bRet=FALSE;
	int i=0;
	HANDLE hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPid);
	MODULEENTRY32W Module;
	Module.dwSize=sizeof(MODULEENTRY32W);
	bRet=Module32FirstW(hSnap,&Module);
	printf("\n-----------CreateToolhelp32Snapshot----------\n\n");
	while(bRet)
	{   i++;
		printf("%2d:%-10ws:%ws\n",i,Module.szModule,Module.szExePath);
		bRet=Module32NextW(hSnap,&Module);
	}

}