简介
PEB(Process Environment Block,进程环境块)是存放进程信息的结构体,尺寸非常大,其大部分内容都已被文档化
PEB访问方法
TEB.ProcessEnvironmentBlock成员就是PEB 结构体的地址。TEB结构体位于FS段选择符所指的段内存的起始地址处,且ProcessEnvironmentBlock成员位于距TEB结构体Offest 30的位置。
即如下式子成立:
FS:[30]=TEB.ProcessEnvironmentBlock=address of PEB
用汇编代码表述上面式子:
代码1:
MOV EAX,DWORD PTR FS:[0x30]
代码2:
MOV EAX,DWORD PTR FS:[0x18]
MOV EAX,DWORD PTR FS:[EAX+0x30]
接下来用OD工具查看PEB结构体
执行此行代码后,查看eax
PEB结构体定义
Windows XP SP3下
typedef struct _PEB { // Size: 0x1D8
000h UCHAR InheritedAddressSpace;
001h UCHAR ReadImageFileExecOptions;
002h UCHAR BeingDebugged; //Debug运行标志
003h UCHAR SpareBool;
004h HANDLE Mutant;
008h HINSTANCE ImageBaseAddress; //程序加载的基地址
00Ch struct _PEB_LDR_DATA *Ldr //Ptr32 _PEB_LDR_DATA
010h struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters;
014h ULONG SubSystemData;
018h HANDLE DefaultHeap;
01Ch KSPIN_LOCK FastPebLock;
020h ULONG FastPebLockRoutine;
024h ULONG FastPebUnlockRoutine;
028h ULONG EnvironmentUpdateCount;
02Ch ULONG KernelCallbackTable;
030h LARGE_INTEGER SystemReserved;
038h struct _PEB_FREE_BLOCK *FreeList
03Ch ULONG TlsExpansionCounter;
040h ULONG TlsBitmap;
044h LARGE_INTEGER TlsBitmapBits;
04Ch ULONG ReadOnlySharedMemoryBase;
050h ULONG ReadOnlySharedMemoryHeap;
054h ULONG ReadOnlyStaticServerData;
058h ULONG AnsiCodePageData;
05Ch ULONG OemCodePageData;
060h ULONG UnicodeCaseTableData;
064h ULONG NumberOfProcessors;
068h LARGE_INTEGER NtGlobalFlag; // Address of a local copy
070h LARGE_INTEGER CriticalSectionTimeout;
078h ULONG HeapSegmentReserve;
07Ch ULONG HeapSegmentCommit;
080h ULONG HeapDeCommitTotalFreeThreshold;
084h ULONG HeapDeCommitFreeBlockThreshold;
088h ULONG NumberOfHeaps;
08Ch ULONG MaximumNumberOfHeaps;
090h ULONG ProcessHeaps;
094h ULONG GdiSharedHandleTable;
098h ULONG ProcessStarterHelper;
09Ch ULONG GdiDCAttributeList;
0A0h KSPIN_LOCK LoaderLock;
0A4h ULONG OSMajorVersion;
0A8h ULONG OSMinorVersion;
0ACh USHORT OSBuildNumber;
0AEh USHORT OSCSDVersion;
0B0h ULONG OSPlatformId;
0B4h ULONG ImageSubsystem;
0B8h ULONG ImageSubsystemMajorVersion;
0BCh ULONG ImageSubsystemMinorVersion;
0C0h ULONG ImageProcessAffinityMask;
0C4h ULONG GdiHandleBuffer[0x22];
14Ch ULONG PostProcessInitRoutine;
150h ULONG TlsExpansionBitmap;
154h UCHAR TlsExpansionBitmapBits[0x80];
1D4h ULONG SessionId;
1d8h AppCompatFlags : _ULARGE_INTEGER
1e0h AppCompatFlagsUser : _ULARGE_INTEGER
1e8h pShimData : Ptr32 Void
1ech AppCompatInfo : Ptr32 Void
1f0h CSDVersion : _UNICODE_STRING
1f8h ActivationContextData : Ptr32 Void
1fch ProcessAssemblyStorageMap :Ptr32 Void
200h SystemDefaultActivationContextData : Ptr32 Void
204h SystemAssemblyStorageMap : Ptr32 Void
208h MinimumStackCommit : Uint4B
} PEB, *PPEB;
Windows 7下
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
据上观察Windows7下的PEB结构体更大。
PEB的重要成员
+0x002 BeingDebugged : UChar
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x018 ProcessHeap : Ptr32 Void
+0x068 NtGlobalFlag : Uint4B
PEB.BeingDebugged
kernel32.dll中有个名Kernel32!IsDebuggerPresent()
的API,但普通的应用程序开发中并不常用:
BOOL WINAPI IsDebuggerPresent()
该API就是用来判断当前进程是否处于调试状态,并返回判断结果。而该API就是通过检测PEB.BeingDebugged成员来确定是否正在调试程序(是,则返回1;否,则返回0)。
老办法,查看一下OD:
代码如下:
75074E80 > 64:A1 30000000 mov eax,dword ptr fs:[0x30]
75074E86 0FB640 02 movzx eax,byte ptr ds:[eax+0x2]
75074E8A C3 retn
提示:
Windows 7中,IsDebuggerPresent()
API是在Kernelbase.dll
中实现的。而在Windows XP 及以前版本的操作系统中,它是在kernel32.dll
中。
先获取FS:[30]地址,即PEB地址,然后通过[PEB+2]访问BeingDebugged
这里取出来的是0的原因呢,是因为吾爱破解OD太强悍了,加了很多插件。。。
慢慢关闭就行,用原版OD或者IDA就能返回1。
PEB.ImageBaseAddress
PEB.ImageBaseAddress成员用来表示进程的ImageBase。
GetModuleHandle()
API用来获取ImageBase
。
HMODULE WINAPI GetModuleHandle(
__in_opt LPCTSTR lpModuleName
)
向lpModuleName
参数赋值为NULL,调用GetModuleHandle()
函数将返回进程被加载的ImageBase
。
查看了一下代码:
00821C70 55 push ebp
00821C71 8BEC mov ebp,esp
00821C73 6A FE push -0x2
00821C75 68 D0908200 push test1.008290D0
00821C7A 68 F0378200 push test1.008237F0
00821C7F 64:A1 00000000 mov eax,dword ptr fs:[0]
00821C85 50 push eax
00821C86 83C4 CC add esp,-0x34
00821C89 53 push ebx
00821C8A 56 push esi ; test1.<ModuleEntryPoint>
00821C8B 57 push edi ; test1.<ModuleEntryPoint>
00821C8C A1 24A08200 mov eax,dword ptr ds:[0x82A024]
00821C91 3145 F8 xor dword ptr ss:[ebp-0x8],eax
00821C94 33C5 xor eax,ebp
00821C96 50 push eax
00821C97 8D45 F0 lea eax,dword ptr ss:[ebp-0x10]
00821C9A 64:A3 00000000 mov dword ptr fs:[0],eax
00821CA0 8965 E8 mov dword ptr ss:[ebp-0x18],esp
00821CA3 6A 01 push 0x1
00821CA5 E8 EFF5FFFF call test1.00821299
怎么说呢。。。VS编译链接出来的程序跟我想象中不太一样。。。我感觉应该是下面这样。。。
mov eax,dword ptr fs:[18]
mov eax,dword ptr fs:[eax+30]
mov eax,dword ptr fs:[eax+8]
调用GetModuleHandle()
函数将执行上述代码,也就是PEB.ImageBaseAddress
成员的值被设置在EAX寄存器里。(函数返回值)
PEB.Ldr
PEB.Ldr成员是指向了_ PEB _ LDR _ DATA结构体指针。如下:
ypedef struct _PEB_LDR_DATA
{
ULONG Length; // 00h
BOOLEAN Initialized; // 04h
PVOID SsHandle; // 08h
LIST_ENTRY InLoadOrderModuleList; // 0ch
LIST_ENTRY InMemoryOrderModuleList; // 14h
LIST_ENTRY InInitializationOrderModuleList; // 1ch
EntryInProgress //Ptr32 Void
ShutdownInProgress //Uchar
ShutdownThreadId //Ptr32 Void
}
PEB_LDR_DATA,
*PPEB_LDR_DATA; // 24h
当模块(DLL)加载到进程后,通过PEB.ldr
成员可以直接获得该模块的加载基地址。
_PEB_LDR_DATA
结构体成员中有3个LIST_ENTRY
类型的成员(InLoadOrderModuleList;InMemoryOrderModuleList; InInitializationOrderModuleList;
),LIST_ENTRY
结构体的定义如下所示:
typedef struct _LIST_ENTRY{
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
}LIST_ENTRY,*LIST_ENTRY
从上面可看出,_LIST_ENTRY
结构体提供了双向链表机制。而链表中保存了_LDR_DATA_TABLE_ENTRY
结构体的信息。
typedef struct _LDR_DATA_TABLE_EBTRY{ // Start from Windows XP
PVOID Reservedl[2];
LIST_ENTRY InMemoryOrderLinks;
PVOID Reserved2[2];
PVOID DllBase;
PVOID EntryPoint;
PVOID Reserved3;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
PVOID Reserved4[8];
PVOID Reserved5[3];
union {
PVOID SectionPointer;
ULONG CheckSum;
}
ULONG TimeDateStamp;
}
每个加载到进程中的DLL模块都有与之对应的_LDR_DATA_TABLE_EBTRY
结构体,这些结构体相互链接,最终形成_LIST_ENTRY
双向链表。
需要注意的是,_PEB_LDR_DATA
结构体中存在3种链表。也就说,存在多个_LDR_DATA_TABLE_ENTRY
结构体,有三种链接方式可以把它们链接起来。
PEB.ProcessHeap & PEB.NtGlobalFlag
PEB.ProcessHeap & PEB.NtGlobalFlag (和PEB.BeingDebugger成员一样)应用于反调试技术。若处于被调试状态,则它们会被赋于特定的值。(反调试会讲解)