一个比较重要的 Windows 结构
该结构在不同版本的 Windows 下不同!具体可以参考 https://www.vergiliusproject.com/
参考链接
https://bbs.kanxue.com/thread-266678.htm
https://blog.csdn.net/CSNN2019/article/details/113113347
https://blog.csdn.net/simon798/article/details/107128069
https://blog.csdn.net/zhoujiaxq/article/details/23169587
定义
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;
Win7
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
Win7 下的结构更大
PEB 的重要结构
+0x002 BeingDebugged : UChar
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x018 ProcessHeap : Ptr32 Void
+0x068 NtGlobalFlag : Uint4B
BeingDebugged
kernel32.dll 中有一个函数如下:
BOOL WINAPI IsDebuggerPresent()
该 API 用来判断当前进程是否处于调试状态,并返回判断结果。而该 API 就是通过检测 PEB.BeingDebugged 成员来确定是否正在调试程序(是,则返回 1;否,则返回 0)。Win7 中,IsDebuggerPresent()是在 Kernelbase.dll 中实现的。而在 Windows XP 及以前版本的操作系统中,它是在 kernel32.dll 中。Win10 中也是在 Kernel32.dll 中。
ImageBaseAddress
ImageBaseAddress 成员用来表示进程的 ImageBase。Windows 用 GetModuleHandle 函数获取 ImageBase:
HMODULE WINAPI GetModuleHandle(
__in_opt LPCTSTR lpModuleName
)
函数返回值被存在 EAX 中。
Ldr
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)加载到进程后,通过 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 结构体的信息。
//0x78 bytes (sizeof) Win7 下
struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x8
struct _LIST_ENTRY InInitializationOrderLinks; //0x10
VOID* DllBase; //0x18
VOID* EntryPoint; //0x1c
ULONG SizeOfImage; //0x20
struct _UNICODE_STRING FullDllName; //0x24
struct _UNICODE_STRING BaseDllName; //0x2c
ULONG Flags; //0x34
USHORT LoadCount; //0x38
USHORT TlsIndex; //0x3a
union
{
struct _LIST_ENTRY HashLinks; //0x3c
struct
{
VOID* SectionPointer; //0x3c
ULONG CheckSum; //0x40
};
};
union
{
ULONG TimeDateStamp; //0x44
VOID* LoadedImports; //0x44
};
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x48
VOID* PatchInformation; //0x4c
struct _LIST_ENTRY ForwarderLinks; //0x50
struct _LIST_ENTRY ServiceTagLinks; //0x58
struct _LIST_ENTRY StaticLinks; //0x60
VOID* ContextInformation; //0x68
ULONG OriginalBase; //0x6c
union _LARGE_INTEGER LoadTime; //0x70
};
每个加载到进程中的 DLL 模块都有与之对应的 _LDR_DATA_TABLE_EBTRY 结构体,这些结构体相互链接,最终形成 _LIST_ENTRY 双向链表。
需要注意的是,_PEB_LDR_DATA 结构体中存在 3 种链表。也就说,存在多个 _LDR_DATA_TABLE_ENTRY 结构体,有三种链接方式可以把它们链接起来。
借用下前人的图:
ProcessHeap
x64 中 ProcessHeap 在 PEB 的偏移是 0x30.
x86 中 ProcessHeap 在 PEB 的偏移是 0x18.
ProcessHeap 是指向 HEAP 结构体的指针,在 HEAP 结构体中的两个成员 Flags 和 Force Flags 。 进程运行正常时,Heap.Flags 的成员值为0x2,HEAP.ForceFlags 成员的值为0x0
HeapFlags
对于 x64 系统,vista 以上版本的 HeapFlags 位于 ProcessHeap + 0x70,剩余低版本的 windows 中的 HeapFlags 位于 ProcessHeap+ 0x14。
对于 x86 系统 vista 以上版本的 HeapFlags 位于 ProcessHeap + 0x40,剩余低版本的 windows 中的 HeapFlags 位于 ProcessHeap + 0x0c。
如果 HeapFlags 的值 大于 2 说明程序处于调试状态。示例代码如下:
// 环境 - win10 x64
ULONG64 ul_processHeap = (ULONG64)(__readgsqword(0x60) + 0x30);
ULONG64 ul_heapFlags = (ULONG64)(*ul_processHeap + 0x70);
if(*ul_heapFlags > 2){
cout << "发现调试器" << endl;
}
else{
cout << "没有调试器" << endl;
}
HeapForceFlags
对于 x64 系统,vista 以上版本的 HeapForceFlags位于 ProcessHeap+ 0x74,剩余低版本的 windows 中的 HeapForceFlags 位于 ProcessHeap+ 0x18。
对于 x86 系统 vista 以上版本的 HeapForceFlags 位于 ProcessHeap + 0x44,剩余低版本的 windows 中的 HeapForceFlags 位于 ProcessHeap + 0x10。
如果 HeapForceFlags 的值 大于 0 则说明处于调试状态。
// 环境 - win10 x64
ULONG64 ul_processHeap = (ULONG64)(__readgsqword(0x60) + 0x30);
ULONG64 ul_heapForceFlags = (ULONG64)(*ul_processHeap + 0x74);
if(*ul_heapForceFlags > 0){
cout << "发现调试器" << endl;
}
else{
cout << "没有调试器" << endl;
}
NtGlobalFlag
通常程序没有被调试时,NtGlobalFlag成员值为0,如果进程被调试这个成员通常值为0x70(代表下述标志被设置):
FLG_HEAP_ENABLE_TAIL_CHECK(0X10)
FLG_HEAP_ENABLE_FREE_CHECK(0X20)
FLG_HEAP_VALIDATE_PARAMETERS(0X40)