PEB,Process Environment Block ,進程環境塊。位於用戶地址空間。在地址 0x7FFDF000 處。所以用戶進程可以直接訪問自己的 PEB 結構。Win2k Build 2195 中進程的 EPROCESS 結構偏移+1b0 處的 *Peb 也指向 PEB 結構。在 undocumented.ntinternals.net (需要注意的是這是個非官方的站點)我們可以找到 PEB 及其相關結構的定義。我們首先列出結構的定義,然後對一些內容進行說明。
typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PVOID FastPebLock; PPEBLOCKROUTINE FastPebLockRoutine; PPEBLOCKROUTINE FastPebUnlockRoutine; ULONG EnvironmentUpdateCount; PPVOID KernelCallbackTable; PVOID EventLogSection; PVOID EventLog; PPEB_FREE_BLOCK FreeList; ULONG TlsExpansionCounter; PVOID TlsBitmap; 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;
typedef void (*PPEBLOCKROUTINE)(PVOID PebLock);
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_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;
typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING;
typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; PVOID ConsoleHandle; ULONG ConsoleFlags; HANDLE StdInputHandle; HANDLE StdOutputHandle; HANDLE StdErrorHandle; UNICODE_STRING CurrentDirectoryPath; HANDLE CurrentDirectoryHandle; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; PVOID Environment; ULONG StartingPositionLeft; ULONG StartingPositionTop; ULONG Width; ULONG Height; ULONG CharWidth; ULONG CharHeight; ULONG ConsoleTextAttributes; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopName; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; UNICODE_STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _PEB_FREE_BLOCK { _PEB_FREE_BLOCK *Next; ULONG Size; } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
我寫了一個叫 JiurlPebSee 的程序來分析指定進程的 PEB。下面我結合 JiurlPebSee 的輸出來對 PEB 及其相關結構的一些內容進行說明。
ProcessId(Decimal): 516 Explorer.exe:
PEB at 0x7ffdf000
LoaderData: 0x00071e90 ProcessParameters: 0x00020000 ProcessHeap: 0x00070000 NumberOfHeaps: 11 MaximumNumberOfHeaps: 16 *ProcessHeaps: 0x77fce380
7ffdf000: 00000000 ffffffff 00400000 00071e90 7ffdf010: 00020000 00000000 00070000 77fcd170 7ffdf020: 77f8aa4c 77f8aa7d 00000001 77e14380 7ffdf030: 00000000 00000000 00000000 00000000 7ffdf040: 77fcd1a8 03cfffff 00000000 7f6f0000 7ffdf050: 7f6f0000 7f6f0688 7ffa0000 7ffa0000 7ffdf060: 7ffd1000 00000001 00000000 00000000 7ffdf070: 079b8000 ffffe86d 00100000 00002000 7ffdf080: 00010000 00001000 0000000b 00000010 7ffdf090: 77fce380 00350000 00000000 00000014 7ffdf0a0: 77fcd348 00000005 00000000 00000893 7ffdf0b0: 00000002 00000002 00000004 00000000 7ffdf0c0: 00000000 00000000 00000002 00000000 7ffdf0d0: 00000004 00000000 b51003ba 391001e4 7ffdf0e0: 00000000 00000000 00000000 00000000 7ffdf0f0: 00000000 00000000 00000000 00000000 7ffdf100: 00000000 00000000 00000000 00000000 7ffdf110: 00000000 00000000 00000000 00000000 7ffdf120: 8204019c 7004019b cf04019e a104019d 7ffdf130: 00000000 00000000 00000000 00000000 7ffdf140: 00000000 00000000 00000000 00000000 7ffdf150: 77fcdcc0 00000000 00000000 00000000 7ffdf160: 00000000 00000000 00000000 00000000 7ffdf170: 00000000 00000000 00000000 00000000 7ffdf180: 00000000 00000000 00000000 00000000 7ffdf190: 00000000 00000000 00000000 00000000 7ffdf1a0: 00000000 00000000 00000000 00000000 7ffdf1b0: 00000000 00000000 00000000 00000000 7ffdf1c0: 00000000 00000000 00000000 00000000 7ffdf1d0: 00000000 00000000 00000000 00020000 7ffdf1e0: 7f6f06c2 00000000 00000000 00000000 7ffdf1f0: 00000000 00000000 00000000 00000000 7ffdf200: 00000000 00000000 00000000 00000000 ...
我們以進程 Explorer.exe 進行分析。 LoaderData 是指向 PEB_LDR_DATA 的指針,通過 PEB_LDR_DATA ,我們可以找到進程載入的所有模組。 ProcessParameters 是指向 RTL_USER_PROCESS_PARAMETERS 的指針,RTL_USER_PROCESS_PARAMETERS 中是一些進程的參數。 進程通常有多個用戶堆。ProcessHeap 是進程堆(默認的那個)的首地址。NumberOfHeaps 是當前進程的堆的個數。MaximumNumberOfHeaps 是進程的堆的最大個數。*ProcessHeaps 是一個堆指針數組的首地址,每個數組元素長4個字節,是一個堆的指針。
LoaderData at 0x00071e90
Length: 36 Bytes Initialized: 1 SsHandle: 0x00000000 InLoadOrderModuleList Flink: 0x00071ec0 Blink: 0x000a0508 InMemoryOrderModuleList Flink: 0x00071ec8 Blink: 0x000a0510 InInitializationOrderModuleList Flink: 0x00071f48 Blink: 0x000a0518
Module at 0x00071ec0 FullDllName: D:/WINNT/Explorer.exe BaseDllName: Explorer.exe BaseAddress: 0x00400000 SizeOfImage: 0x0003c000
Module at 0x00071f38 FullDllName: D:/WINNT/System32/ntdll.dll BaseDllName: ntdll.dll BaseAddress: 0x77f80000 SizeOfImage: 0x00079000
Module at 0x00072470 FullDllName: D:/WINNT/system32/ADVAPI32.DLL BaseDllName: ADVAPI32.DLL BaseAddress: 0x77d90000 SizeOfImage: 0x0005a000
...
從PEB可以找到 PEB_LDR_DATA ,PEB_LDR_DATA 中有三個雙向循環鏈表的表頭,分別是 InLoadOrderModuleList,InMemoryOrderModuleList,InInitializationOrderModuleList。 每個鏈表項都是一個 LDR_MODULE 結構。
ProcessParameters at 0x00020000
MaximumLength: 0x00001000 Length: 0x00000838 ...
Environment at 0x00010000
00010000: 004c0041 0055004c 00450053 00530052 A.L.L.U.S.E.R.S. 00010010: 00520050 0046004f 004c0049 003d0045 P.R.O.F.I.L.E.=. 00010020: 003a0049 0044005c 0063006f 006d0075 I.:./.D.o.c.u.m. 00010030: 006e0065 00730074 00610020 0064006e e.n.t.s. .a.n.d. 00010040: 00530020 00740065 00690074 0067006e .S.e.t.t.i.n.g. ... 00010340: 00640075 00000065 0069006c 003d0062 u.d.e...l.i.b.=. 00010350: 003a0047 004d005c 00630069 006f0072 G.:./.M.i.c.r.o. 00010360: 006f0073 00740066 00560020 00730069 s.o.f.t. .V.i.s. 00010370: 00610075 0020006c 00740053 00640075 u.a.l. .S.t.u.d. ... 00010a70: 005c0031 00650054 0070006d 00540000 1./.T.e.m.p...T. ... 00010b80: 003a0044 0057005c 004e0049 0054004e D.:./.W.I.N.N.T. 00010b90: 00000000 00000000 00000000 00000000 ................ ... 00010ff0: 00000000 00000000 00000000 00000000 ................
RTL_USER_PROCESS_PARAMETERS 中的 PVOID Environment; 指明瞭環境變量的地址。
從結構定義中就可以看出 是象 StdInputHandle,ImagePathName 這樣的參數。
ProcessHeaps at 0x77fce380
ProcessHeaps[0]: 0x00070000 ProcessHeaps[1]: 0x00170000 ProcessHeaps[2]: 0x008c0000 ProcessHeaps[3]: 0x00cd0000 ProcessHeaps[4]: 0x00ed0000 ProcessHeaps[5]: 0x00f10000 ProcessHeaps[6]: 0x01290000 ProcessHeaps[7]: 0x013e0000 ProcessHeaps[8]: 0x01ce0000 ProcessHeaps[9]: 0x01f50000 ProcessHeaps[10]: 0x03bf0000
77fce380: 00070000 00170000 008c0000 00cd0000 77fce390: 00ed0000 00f10000 01290000 013e0000 77fce3a0: 01ce0000 01f50000 03bf0000 00000000 77fce3b0: 00000000 00000000 00000000 00000000
從 ProcessHeaps 數組,我們可以找到進程的每一個堆。
爲了方便觀察某個進程地址空間中內容,我寫了一個叫 JiurlProcessMemSee 的程序,可以獲得指定進程地址空間中的內容。
使用 KD(內核調試器) 我們也可以找到 PEB 及其相關結構的定義。
kd> !strct PEB !strct PEB struct _PEB (sizeof=488) +000 byte InheritedAddressSpace +001 byte ReadImageFileExecOptions +002 byte BeingDebugged +003 byte SpareBool +004 void *Mutant +008 void *ImageBaseAddress +00c struct _PEB_LDR_DATA *Ldr +010 struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters +014 void *SubSystemData +018 void *ProcessHeap +01c void *FastPebLock +020 void *FastPebLockRoutine +024 void *FastPebUnlockRoutine +028 uint32 EnvironmentUpdateCount +02c void *KernelCallbackTable +030 uint32 SystemReserved[2] +038 struct _PEB_FREE_BLOCK *FreeList +03c uint32 TlsExpansionCounter +040 void *TlsBitmap +044 uint32 TlsBitmapBits[2] +04c void *ReadOnlySharedMemoryBase +050 void *ReadOnlySharedMemoryHeap +054 void **ReadOnlyStaticServerData +058 void *AnsiCodePageData +05c void *OemCodePageData +060 void *UnicodeCaseTableData +064 uint32 NumberOfProcessors +068 uint32 NtGlobalFlag +070 union _LARGE_INTEGER CriticalSectionTimeout +070 uint32 LowPart +074 int32 HighPart +070 struct __unnamed3 u +070 uint32 LowPart +074 int32 HighPart +070 int64 QuadPart +078 uint32 HeapSegmentReserve +07c uint32 HeapSegmentCommit +080 uint32 HeapDeCommitTotalFreeThreshold +084 uint32 HeapDeCommitFreeBlockThreshold +088 uint32 NumberOfHeaps +08c uint32 MaximumNumberOfHeaps +090 void **ProcessHeaps +094 void *GdiSharedHandleTable +098 void *ProcessStarterHelper +09c uint32 GdiDCAttributeList +0a0 void *LoaderLock +0a4 uint32 OSMajorVersion +0a8 uint32 OSMinorVersion +0ac uint16 OSBuildNumber +0ae uint16 OSCSDVersion +0b0 uint32 OSPlatformId +0b4 uint32 ImageSubsystem +0b8 uint32 ImageSubsystemMajorVersion +0bc uint32 ImageSubsystemMinorVersion +0c0 uint32 ImageProcessAffinityMask +0c4 uint32 GdiHandleBuffer[34] +14c function *PostProcessInitRoutine +150 void *TlsExpansionBitmap +154 uint32 TlsExpansionBitmapBits[32] +1d4 uint32 SessionId +1d8 void *AppCompatInfo +1dc struct _UNICODE_STRING CSDVersion +1dc uint16 Length +1de uint16 MaximumLength +1e0 uint16 *Buffer
kd> !strct PEB_LDR_DATA !strct PEB_LDR_DATA struct _PEB_LDR_DATA (sizeof=36) +00 uint32 Length +04 byte Initialized +08 void *SsHandle +0c struct _LIST_ENTRY InLoadOrderModuleList +0c struct _LIST_ENTRY *Flink +10 struct _LIST_ENTRY *Blink +14 struct _LIST_ENTRY InMemoryOrderModuleList +14 struct _LIST_ENTRY *Flink +18 struct _LIST_ENTRY *Blink +1c struct _LIST_ENTRY InInitializationOrderModuleList +1c struct _LIST_ENTRY *Flink +20 struct _LIST_ENTRY *Blink
kd> !strct RTL_USER_PROCESS_PARAMETERS !strct RTL_USER_PROCESS_PARAMETERS struct _RTL_USER_PROCESS_PARAMETERS (sizeof=656) +000 uint32 MaximumLength +004 uint32 Length +008 uint32 Flags +00c uint32 DebugFlags +010 void *ConsoleHandle +014 uint32 ConsoleFlags +018 void *StandardInput +01c void *StandardOutput +020 void *StandardError +024 struct _CURDIR CurrentDirectory +024 struct _UNICODE_STRING DosPath +024 uint16 Length +026 uint16 MaximumLength +028 uint16 *Buffer +02c void *Handle +030 struct _UNICODE_STRING DllPath +030 uint16 Length +032 uint16 MaximumLength +034 uint16 *Buffer +038 struct _UNICODE_STRING ImagePathName +038 uint16 Length +03a uint16 MaximumLength +03c uint16 *Buffer +040 struct _UNICODE_STRING CommandLine +040 uint16 Length +042 uint16 MaximumLength +044 uint16 *Buffer +048 void *Environment +04c uint32 StartingX +050 uint32 StartingY +054 uint32 CountX +058 uint32 CountY +05c uint32 CountCharsX +060 uint32 CountCharsY +064 uint32 FillAttribute +068 uint32 WindowFlags +06c uint32 ShowWindowFlags +070 struct _UNICODE_STRING WindowTitle +070 uint16 Length +072 uint16 MaximumLength +074 uint16 *Buffer +078 struct _UNICODE_STRING DesktopInfo +078 uint16 Length +07a uint16 MaximumLength +07c uint16 *Buffer +080 struct _UNICODE_STRING ShellInfo +080 uint16 Length +082 uint16 MaximumLength +084 uint16 *Buffer +088 struct _UNICODE_STRING RuntimeData +088 uint16 Length +08a uint16 MaximumLength +08c uint16 *Buffer +090 struct _RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32] uint16 Flags uint16 Length uint32 TimeStamp struct _STRING DosPath uint16 Length uint16 MaximumLength char *Buffer
kd> !strct RTL_DRIVE_LETTER_CURDIR !strct RTL_DRIVE_LETTER_CURDIR struct _RTL_DRIVE_LETTER_CURDIR (sizeof=16) +00 uint16 Flags +02 uint16 Length +04 uint32 TimeStamp +08 struct _STRING DosPath +08 uint16 Length +0a uint16 MaximumLength +0c char *Buffer
kd> !strct PEB_FREE_BLOCK !strct PEB_FREE_BLOCK struct _PEB_FREE_BLOCK (sizeof=8) +0 struct _PEB_FREE_BLOCK *Next +4 uint32 Size
歡迎交流,歡迎交朋友, 歡迎訪問 http://jiurl.yeah.net http://jiurl.cosoft.org.cn/forum
下載 JiurlPebSee 可執行文件及源程序 下載 JiurlProcessMemSee 可執行文件及源程序
|