1. TEB结构
TEB全称是线程环境块,它是一个包含每个Windows线程状态和数据的核心数据结构,存储了线程执行上下文所需的数据,每个线程都有一个TEB ,包含了线程的状态、运行时所需的数据等等,最重要的是包含了指向PEB的指针,也就是说通过TEB结构就能找到PEB的入口。
TEB32位结构体定义:
//0x1000
struct _TEB32
{
struct _NT_TIB32 NtTib; //0x0
ULONG EnvironmentPointer; //0x1c
struct _CLIENT_ID32 ClientId; //0x20
ULONG ActiveRpcHandle; //0x28
ULONG ThreadLocalStoragePointer; //0x2c
ULONG ProcessEnvironmentBlock; //0x30
ULONG LastErrorValue; //0x34
ULONG CountOfOwnedCriticalSections; //0x38
ULONG CsrClientThread; //0x3c
ULONG Win32ThreadInfo; //0x40
ULONG User32Reserved[26]; //0x44
ULONG UserReserved[5]; //0xac
ULONG WOW32Reserved; //0xc0
ULONG CurrentLocale; //0xc4
ULONG FpSoftwareStatusRegister; //0xc8
ULONG ReservedForDebuggerInstrumentation[16]; //0xcc
ULONG SystemReserved1[26]; //0x10c
CHAR PlaceholderCompatibilityMode; //0x174
UCHAR PlaceholderHydrationAlwaysExplicit; //0x175
CHAR PlaceholderReserved[10]; //0x176
ULONG ProxiedProcessId; //0x180
struct _ACTIVATION_CONTEXT_STACK32 _ActivationStack; //0x184
UCHAR WorkingOnBehalfTicket[8]; //0x19c
LONG ExceptionCode; //0x1a4
ULONG ActivationContextStackPointer; //0x1a8
ULONG InstrumentationCallbackSp; //0x1ac
ULONG InstrumentationCallbackPreviousPc; //0x1b0
ULONG InstrumentationCallbackPreviousSp; //0x1b4
UCHAR InstrumentationCallbackDisabled; //0x1b8
UCHAR SpareBytes[23]; //0x1b9
ULONG TxFsContext; //0x1d0
struct _GDI_TEB_BATCH32 GdiTebBatch; //0x1d4
struct _CLIENT_ID32 RealClientId; //0x6b4
ULONG GdiCachedProcessHandle; //0x6bc
ULONG GdiClientPID; //0x6c0
ULONG GdiClientTID; //0x6c4
ULONG GdiThreadLocalInfo; //0x6c8
ULONG Win32ClientInfo[62]; //0x6cc
ULONG glDispatchTable[233]; //0x7c4
ULONG glReserved1[29]; //0xb68
ULONG glReserved2; //0xbdc
ULONG glSectionInfo; //0xbe0
ULONG glSection; //0xbe4
ULONG glTable; //0xbe8
ULONG glCurrentRC; //0xbec
ULONG glContext; //0xbf0
ULONG LastStatusValue; //0xbf4
struct _STRING32 StaticUnicodeString; //0xbf8
WCHAR StaticUnicodeBuffer[261]; //0xc00
ULONG DeallocationStack; //0xe0c
ULONG TlsSlots[64]; //0xe10
struct LIST_ENTRY32 TlsLinks; //0xf10
ULONG Vdm; //0xf18
ULONG ReservedForNtRpc; //0xf1c
ULONG DbgSsReserved[2]; //0xf20
ULONG HardErrorMode; //0xf28
ULONG Instrumentation[9]; //0xf2c
struct _GUID ActivityId; //0xf50
ULONG SubProcessTag; //0xf60
ULONG PerflibData; //0xf64
ULONG EtwTraceData; //0xf68
ULONG WinSockData; //0xf6c
ULONG GdiBatchCount; //0xf70
union
{
struct _PROCESSOR_NUMBER CurrentIdealProcessor; //0xf74
ULONG IdealProcessorValue; //0xf74
struct
{
UCHAR ReservedPad0; //0xf74
UCHAR ReservedPad1; //0xf75
UCHAR ReservedPad2; //0xf76
UCHAR IdealProcessor; //0xf77
};
};
ULONG GuaranteedStackBytes; //0xf78
ULONG ReservedForPerf; //0xf7c
ULONG ReservedForOle; //0xf80
ULONG WaitingOnLoaderLock; //0xf84
ULONG SavedPriorityState; //0xf88
ULONG ReservedForCodeCoverage; //0xf8c
ULONG ThreadPoolData; //0xf90
ULONG TlsExpansionSlots; //0xf94
ULONG MuiGeneration; //0xf98
ULONG IsImpersonating; //0xf9c
ULONG NlsCache; //0xfa0
ULONG pShimData; //0xfa4
ULONG HeapData; //0xfa8
ULONG CurrentTransactionHandle; //0xfac
ULONG ActiveFrame; //0xfb0
ULONG FlsData; //0xfb4
ULONG PreferredLanguages; //0xfb8
ULONG UserPrefLanguages; //0xfbc
ULONG MergedPrefLanguages; //0xfc0
ULONG MuiImpersonation; //0xfc4
union
{
volatile USHORT CrossTebFlags; //0xfc8
USHORT SpareCrossTebBits:16; //0xfc8
};
union
{
USHORT SameTebFlags; //0xfca
struct
{
USHORT SafeThunkCall:1; //0xfca
USHORT InDebugPrint:1; //0xfca
USHORT HasFiberData:1; //0xfca
USHORT SkipThreadAttach:1; //0xfca
USHORT WerInShipAssertCode:1; //0xfca
USHORT RanProcessInit:1; //0xfca
USHORT ClonedThread:1; //0xfca
USHORT SuppressDebugMsg:1; //0xfca
USHORT DisableUserStackWalk:1; //0xfca
USHORT RtlExceptionAttached:1; //0xfca
USHORT InitialThread:1; //0xfca
USHORT SessionAware:1; //0xfca
USHORT LoadOwner:1; //0xfca
USHORT LoaderWorker:1; //0xfca
USHORT SkipLoaderInit:1; //0xfca
USHORT SpareSameTebBits:1; //0xfca
};
};
ULONG TxnScopeEnterCallback; //0xfcc
ULONG TxnScopeExitCallback; //0xfd0
ULONG TxnScopeContext; //0xfd4
ULONG LockCount; //0xfd8
LONG WowTebOffset; //0xfdc
ULONG ResourceRetValue; //0xfe0
ULONG ReservedForWdf; //0xfe4
ULONGLONG ReservedForCrt; //0xfe8
struct _GUID EffectiveContainerId; //0xff0
};
TEB32结构中有一个很重要的成员:ProcessEnvironmentBlock (PEB) ,也就是说TEB结构的这个成员(0x30位置处)指向了PEB结构体,因此可以通过FS:[0x30]获取PEB的基地址。
TEB64位结构体定义如下:
//0x1838
struct _TEB64
{
struct _NT_TIB64 NtTib; //0x0
ULONGLONG EnvironmentPointer; //0x38
struct _CLIENT_ID64 ClientId; //0x40
ULONGLONG ActiveRpcHandle; //0x50
ULONGLONG ThreadLocalStoragePointer; //0x58
ULONGLONG ProcessEnvironmentBlock; //0x60
ULONG LastErrorValue; //0x68
ULONG CountOfOwnedCriticalSections; //0x6c
ULONGLONG CsrClientThread; //0x70
ULONGLONG Win32ThreadInfo; //0x78
ULONG User32Reserved[26]; //0x80
ULONG UserReserved[5]; //0xe8
ULONGLONG WOW32Reserved; //0x100
ULONG CurrentLocale; //0x108
ULONG FpSoftwareStatusRegister; //0x10c
ULONGLONG ReservedForDebuggerInstrumentation[16]; //0x110
ULONGLONG SystemReserved1[30]; //0x190
CHAR PlaceholderCompatibilityMode; //0x280
UCHAR PlaceholderHydrationAlwaysExplicit; //0x281
CHAR PlaceholderReserved[10]; //0x282
ULONG ProxiedProcessId; //0x28c
struct _ACTIVATION_CONTEXT_STACK64 _ActivationStack; //0x290
UCHAR WorkingOnBehalfTicket[8]; //0x2b8
LONG ExceptionCode; //0x2c0
UCHAR Padding0[4]; //0x2c4
ULONGLONG ActivationContextStackPointer; //0x2c8
ULONGLONG InstrumentationCallbackSp; //0x2d0
ULONGLONG InstrumentationCallbackPreviousPc; //0x2d8
ULONGLONG InstrumentationCallbackPreviousSp; //0x2e0
ULONG TxFsContext; //0x2e8
UCHAR InstrumentationCallbackDisabled; //0x2ec
UCHAR UnalignedLoadStoreExceptions; //0x2ed
UCHAR Padding1[2]; //0x2ee
struct _GDI_TEB_BATCH64 GdiTebBatch; //0x2f0
struct _CLIENT_ID64 RealClientId; //0x7d8
ULONGLONG GdiCachedProcessHandle; //0x7e8
ULONG GdiClientPID; //0x7f0
ULONG GdiClientTID; //0x7f4
ULONGLONG GdiThreadLocalInfo; //0x7f8
ULONGLONG Win32ClientInfo[62]; //0x800
ULONGLONG glDispatchTable[233]; //0x9f0
ULONGLONG glReserved1[29]; //0x1138
ULONGLONG glReserved2; //0x1220
ULONGLONG glSectionInfo; //0x1228
ULONGLONG glSection; //0x1230
ULONGLONG glTable; //0x1238
ULONGLONG glCurrentRC; //0x1240
ULONGLONG glContext; //0x1248
ULONG LastStatusValue; //0x1250
UCHAR Padding2[4]; //0x1254
struct _STRING64 StaticUnicodeString; //0x1258
WCHAR StaticUnicodeBuffer[261]; //0x1268
UCHAR Padding3[6]; //0x1472
ULONGLONG DeallocationStack; //0x1478
ULONGLONG TlsSlots[64]; //0x1480
struct LIST_ENTRY64 TlsLinks; //0x1680
ULONGLONG Vdm; //0x1690
ULONGLONG ReservedForNtRpc; //0x1698
ULONGLONG DbgSsReserved[2]; //0x16a0
ULONG HardErrorMode; //0x16b0
UCHAR Padding4[4]; //0x16b4
ULONGLONG Instrumentation[11]; //0x16b8
struct _GUID ActivityId; //0x1710
ULONGLONG SubProcessTag; //0x1720
ULONGLONG PerflibData; //0x1728
ULONGLONG EtwTraceData; //0x1730
ULONGLONG WinSockData; //0x1738
ULONG GdiBatchCount; //0x1740
union
{
struct _PROCESSOR_NUMBER CurrentIdealProcessor; //0x1744
ULONG IdealProcessorValue; //0x1744
struct
{
UCHAR ReservedPad0; //0x1744
UCHAR ReservedPad1; //0x1745
UCHAR ReservedPad2; //0x1746
UCHAR IdealProcessor; //0x1747
};
};
ULONG GuaranteedStackBytes; //0x1748
UCHAR Padding5[4]; //0x174c
ULONGLONG ReservedForPerf; //0x1750
ULONGLONG ReservedForOle; //0x1758
ULONG WaitingOnLoaderLock; //0x1760
UCHAR Padding6[4]; //0x1764
ULONGLONG SavedPriorityState; //0x1768
ULONGLONG ReservedForCodeCoverage; //0x1770
ULONGLONG ThreadPoolData; //0x1778
ULONGLONG TlsExpansionSlots; //0x1780
ULONGLONG DeallocationBStore; //0x1788
ULONGLONG BStoreLimit; //0x1790
ULONG MuiGeneration; //0x1798
ULONG IsImpersonating; //0x179c
ULONGLONG NlsCache; //0x17a0
ULONGLONG pShimData; //0x17a8
ULONG HeapData; //0x17b0
UCHAR Padding7[4]; //0x17b4
ULONGLONG CurrentTransactionHandle; //0x17b8
ULONGLONG ActiveFrame; //0x17c0
ULONGLONG FlsData; //0x17c8
ULONGLONG PreferredLanguages; //0x17d0
ULONGLONG UserPrefLanguages; //0x17d8
ULONGLONG MergedPrefLanguages; //0x17e0
ULONG MuiImpersonation; //0x17e8
union
{
volatile USHORT CrossTebFlags; //0x17ec
USHORT SpareCrossTebBits:16; //0x17ec
};
union
{
USHORT SameTebFlags; //0x17ee
struct
{
USHORT SafeThunkCall:1; //0x17ee
USHORT InDebugPrint:1; //0x17ee
USHORT HasFiberData:1; //0x17ee
USHORT SkipThreadAttach:1; //0x17ee
USHORT WerInShipAssertCode:1; //0x17ee
USHORT RanProcessInit:1; //0x17ee
USHORT ClonedThread:1; //0x17ee
USHORT SuppressDebugMsg:1; //0x17ee
USHORT DisableUserStackWalk:1; //0x17ee
USHORT RtlExceptionAttached:1; //0x17ee
USHORT InitialThread:1; //0x17ee
USHORT SessionAware:1; //0x17ee
USHORT LoadOwner:1; //0x17ee
USHORT LoaderWorker:1; //0x17ee
USHORT SkipLoaderInit:1; //0x17ee
USHORT SpareSameTebBits:1; //0x17ee
};
};
ULONGLONG TxnScopeEnterCallback; //0x17f0
ULONGLONG TxnScopeExitCallback; //0x17f8
ULONGLONG TxnScopeContext; //0x1800
ULONG LockCount; //0x1808
LONG WowTebOffset; //0x180c
ULONGLONG ResourceRetValue; //0x1810
ULONGLONG ReservedForWdf; //0x1818
ULONGLONG ReservedForCrt; //0x1820
struct _GUID EffectiveContainerId; //0x1828
};
TEB64位和32位的成员基本类似,就是成员大小不一样,所以使用GS:[0x60]获取PEB的基址。
2. PEB结构
PEB全称是进程环境块,它是WIndows系统下用于存储特定进程运行时信息的关键数据结构,每个进程都有一个PEB结构,包含了进程的加载模块、命令行参数、环境变量、堆信息等信息。
PEB32位结构体定义如下:
//0x480
struct _PEB32
{
UCHAR InheritedAddressSpace; //0x0
UCHAR ReadImageFileExecOptions; //0x1
UCHAR BeingDebugged; //0x2
union
{
UCHAR BitField; //0x3
struct
{
UCHAR ImageUsesLargePages:1; //0x3
UCHAR IsProtectedProcess:1; //0x3
UCHAR IsImageDynamicallyRelocated:1; //0x3
UCHAR SkipPatchingUser32Forwarders:1; //0x3
UCHAR IsPackagedProcess:1; //0x3
UCHAR IsAppContainer:1; //0x3
UCHAR IsProtectedProcessLight:1; //0x3
UCHAR IsLongPathAwareProcess:1; //0x3
};
};
ULONG Mutant; //0x4
ULONG ImageBaseAddress; //0x8
ULONG Ldr; //0xc
ULONG ProcessParameters; //0x10
ULONG SubSystemData; //0x14
ULONG ProcessHeap; //0x18
ULONG FastPebLock; //0x1c
ULONG AtlThunkSListPtr; //0x20
ULONG IFEOKey; //0x24
union
{
ULONG CrossProcessFlags; //0x28
struct
{
ULONG ProcessInJob:1; //0x28
ULONG ProcessInitializing:1; //0x28
ULONG ProcessUsingVEH:1; //0x28
ULONG ProcessUsingVCH:1; //0x28
ULONG ProcessUsingFTH:1; //0x28
ULONG ProcessPreviouslyThrottled:1; //0x28
ULONG ProcessCurrentlyThrottled:1; //0x28
ULONG ProcessImagesHotPatched:1; //0x28
ULONG ReservedBits0:24; //0x28
};
};
union
{
ULONG KernelCallbackTable; //0x2c
ULONG UserSharedInfoPtr; //0x2c
};
ULONG SystemReserved; //0x30
ULONG AtlThunkSListPtr32; //0x34
ULONG ApiSetMap; //0x38
ULONG TlsExpansionCounter; //0x3c
ULONG TlsBitmap; //0x40
ULONG TlsBitmapBits[2]; //0x44
ULONG ReadOnlySharedMemoryBase; //0x4c
ULONG SharedData; //0x50
ULONG ReadOnlyStaticServerData; //0x54
ULONG AnsiCodePageData; //0x58
ULONG OemCodePageData; //0x5c
ULONG UnicodeCaseTableData; //0x60
ULONG NumberOfProcessors; //0x64
ULONG NtGlobalFlag; //0x68
union _LARGE_INTEGER CriticalSectionTimeout; //0x70
ULONG HeapSegmentReserve; //0x78
ULONG HeapSegmentCommit; //0x7c
ULONG HeapDeCommitTotalFreeThreshold; //0x80
ULONG HeapDeCommitFreeBlockThreshold; //0x84
ULONG NumberOfHeaps; //0x88
ULONG MaximumNumberOfHeaps; //0x8c
ULONG ProcessHeaps; //0x90
ULONG GdiSharedHandleTable; //0x94
ULONG ProcessStarterHelper; //0x98
ULONG GdiDCAttributeList; //0x9c
ULONG LoaderLock; //0xa0
ULONG OSMajorVersion; //0xa4
ULONG OSMinorVersion; //0xa8
USHORT OSBuildNumber; //0xac
USHORT OSCSDVersion; //0xae
ULONG OSPlatformId; //0xb0
ULONG ImageSubsystem; //0xb4
ULONG ImageSubsystemMajorVersion; //0xb8
ULONG ImageSubsystemMinorVersion; //0xbc
ULONG ActiveProcessAffinityMask; //0xc0
ULONG GdiHandleBuffer[34]; //0xc4
ULONG PostProcessInitRoutine; //0x14c
ULONG TlsExpansionBitmap; //0x150
ULONG TlsExpansionBitmapBits[32]; //0x154
ULONG SessionId; //0x1d4
union _ULARGE_INTEGER AppCompatFlags; //0x1d8
union _ULARGE_INTEGER AppCompatFlagsUser; //0x1e0
ULONG pShimData; //0x1e8
ULONG AppCompatInfo; //0x1ec
struct _STRING32 CSDVersion; //0x1f0
ULONG ActivationContextData; //0x1f8
ULONG ProcessAssemblyStorageMap; //0x1fc
ULONG SystemDefaultActivationContextData; //0x200
ULONG SystemAssemblyStorageMap; //0x204
ULONG MinimumStackCommit; //0x208
ULONG SparePointers[4]; //0x20c
ULONG SpareUlongs[5]; //0x21c
ULONG WerRegistrationData; //0x230
ULONG WerShipAssertPtr; //0x234
ULONG pUnused; //0x238
ULONG pImageHeaderHash; //0x23c
union
{
ULONG TracingFlags; //0x240
struct
{
ULONG HeapTracingEnabled:1; //0x240
ULONG CritSecTracingEnabled:1; //0x240
ULONG LibLoaderTracingEnabled:1; //0x240
ULONG SpareTracingBits:29; //0x240
};
};
ULONGLONG CsrServerReadOnlySharedMemoryBase; //0x248
ULONG TppWorkerpListLock; //0x250
struct LIST_ENTRY32 TppWorkerpList; //0x254
ULONG WaitOnAddressHashTable[128]; //0x25c
ULONG TelemetryCoverageHeader; //0x45c
ULONG CloudFileFlags; //0x460
ULONG CloudFileDiagFlags; //0x464
CHAR PlaceholderCompatibilityMode; //0x468
CHAR PlaceholderCompatibilityModeReserved[7]; //0x469
ULONG LeapSecondData; //0x470
union
{
ULONG LeapSecondFlags; //0x474
struct
{
ULONG SixtySecondEnabled:1; //0x474
ULONG Reserved:31; //0x474
};
};
ULONG NtGlobalFlag2; //0x478
};
PEB64位结构体定义如下:
//0x7c8
struct _PEB
{
UCHAR InheritedAddressSpace; //0x0
UCHAR ReadImageFileExecOptions; //0x1
UCHAR BeingDebugged; //0x2
union
{
UCHAR BitField; //0x3
struct
{
UCHAR ImageUsesLargePages:1; //0x3
UCHAR IsProtectedProcess:1; //0x3
UCHAR IsImageDynamicallyRelocated:1; //0x3
UCHAR SkipPatchingUser32Forwarders:1; //0x3
UCHAR IsPackagedProcess:1; //0x3
UCHAR IsAppContainer:1; //0x3
UCHAR IsProtectedProcessLight:1; //0x3
UCHAR IsLongPathAwareProcess:1; //0x3
};
};
UCHAR Padding0[4]; //0x4
VOID* Mutant; //0x8
VOID* ImageBaseAddress; //0x10
struct _PEB_LDR_DATA* Ldr; //0x18
struct _RTL_USER_PROCESS_PARAMETERS* ProcessParameters; //0x20
VOID* SubSystemData; //0x28
VOID* ProcessHeap; //0x30
struct _RTL_CRITICAL_SECTION* FastPebLock; //0x38
union _SLIST_HEADER* volatile AtlThunkSListPtr; //0x40
VOID* IFEOKey; //0x48
union
{
ULONG CrossProcessFlags; //0x50
struct
{
ULONG ProcessInJob:1; //0x50
ULONG ProcessInitializing:1; //0x50
ULONG ProcessUsingVEH:1; //0x50
ULONG ProcessUsingVCH:1; //0x50
ULONG ProcessUsingFTH:1; //0x50
ULONG ProcessPreviouslyThrottled:1; //0x50
ULONG ProcessCurrentlyThrottled:1; //0x50
ULONG ProcessImagesHotPatched:1; //0x50
ULONG ReservedBits0:24; //0x50
};
};
UCHAR Padding1[4]; //0x54
union
{
VOID* KernelCallbackTable; //0x58
VOID* UserSharedInfoPtr; //0x58
};
ULONG SystemReserved; //0x60
ULONG AtlThunkSListPtr32; //0x64
VOID* ApiSetMap; //0x68
ULONG TlsExpansionCounter; //0x70
UCHAR Padding2[4]; //0x74
VOID* TlsBitmap; //0x78
ULONG TlsBitmapBits[2]; //0x80
VOID* ReadOnlySharedMemoryBase; //0x88
VOID* SharedData; //0x90
VOID** ReadOnlyStaticServerData; //0x98
VOID* AnsiCodePageData; //0xa0
VOID* OemCodePageData; //0xa8
VOID* UnicodeCaseTableData; //0xb0
ULONG NumberOfProcessors; //0xb8
ULONG NtGlobalFlag; //0xbc
union _LARGE_INTEGER CriticalSectionTimeout; //0xc0
ULONGLONG HeapSegmentReserve; //0xc8
ULONGLONG HeapSegmentCommit; //0xd0
ULONGLONG HeapDeCommitTotalFreeThreshold; //0xd8
ULONGLONG HeapDeCommitFreeBlockThreshold; //0xe0
ULONG NumberOfHeaps; //0xe8
ULONG MaximumNumberOfHeaps; //0xec
VOID** ProcessHeaps; //0xf0
VOID* GdiSharedHandleTable; //0xf8
VOID* ProcessStarterHelper; //0x100
ULONG GdiDCAttributeList; //0x108
UCHAR Padding3[4]; //0x10c
struct _RTL_CRITICAL_SECTION* LoaderLock; //0x110
ULONG OSMajorVersion; //0x118
ULONG OSMinorVersion; //0x11c
USHORT OSBuildNumber; //0x120
USHORT OSCSDVersion; //0x122
ULONG OSPlatformId; //0x124
ULONG ImageSubsystem; //0x128
ULONG ImageSubsystemMajorVersion; //0x12c
ULONG ImageSubsystemMinorVersion; //0x130
UCHAR Padding4[4]; //0x134
ULONGLONG ActiveProcessAffinityMask; //0x138
ULONG GdiHandleBuffer[60]; //0x140
VOID (*PostProcessInitRoutine)(); //0x230
VOID* TlsExpansionBitmap; //0x238
ULONG TlsExpansionBitmapBits[32]; //0x240
ULONG SessionId; //0x2c0
UCHAR Padding5[4]; //0x2c4
union _ULARGE_INTEGER AppCompatFlags; //0x2c8
union _ULARGE_INTEGER AppCompatFlagsUser; //0x2d0
VOID* pShimData; //0x2d8
VOID* AppCompatInfo; //0x2e0
struct _UNICODE_STRING CSDVersion; //0x2e8
struct _ACTIVATION_CONTEXT_DATA* ActivationContextData; //0x2f8
struct _ASSEMBLY_STORAGE_MAP* ProcessAssemblyStorageMap; //0x300
struct _ACTIVATION_CONTEXT_DATA* SystemDefaultActivationContextData; //0x308
struct _ASSEMBLY_STORAGE_MAP* SystemAssemblyStorageMap; //0x310
ULONGLONG MinimumStackCommit; //0x318
VOID* SparePointers[4]; //0x320
ULONG SpareUlongs[5]; //0x340
VOID* WerRegistrationData; //0x358
VOID* WerShipAssertPtr; //0x360
VOID* pUnused; //0x368
VOID* pImageHeaderHash; //0x370
union
{
ULONG TracingFlags; //0x378
struct
{
ULONG HeapTracingEnabled:1; //0x378
ULONG CritSecTracingEnabled:1; //0x378
ULONG LibLoaderTracingEnabled:1; //0x378
ULONG SpareTracingBits:29; //0x378
};
};
UCHAR Padding6[4]; //0x37c
ULONGLONG CsrServerReadOnlySharedMemoryBase; //0x380
ULONGLONG TppWorkerpListLock; //0x388
struct _LIST_ENTRY TppWorkerpList; //0x390
VOID* WaitOnAddressHashTable[128]; //0x3a0
VOID* TelemetryCoverageHeader; //0x7a0
ULONG CloudFileFlags; //0x7a8
ULONG CloudFileDiagFlags; //0x7ac
CHAR PlaceholderCompatibilityMode; //0x7b0
CHAR PlaceholderCompatibilityModeReserved[7]; //0x7b1
struct _LEAP_SECOND_DATA* LeapSecondData; //0x7b8
union
{
ULONG LeapSecondFlags; //0x7c0
struct
{
ULONG SixtySecondEnabled:1; //0x7c0
ULONG Reserved:31; //0x7c0
};
};
ULONG NtGlobalFlag2; //0x7c4
};
PEB32位里面有2个成员非常重要:
- 0x08 ULONG ImageBaseAddress:4字节大小,表示实际装载的映像基址,和PE文件中的不是一回事,这个PEB字段记录了程序实际开始执行的内存位置;
- 0x0c ULONG Ldr:8字节大小,它是一个指向_PEB_LDR_DATA的结构体指针;
PEB64位里面也是一样:
- 0x10 VOID* ImageBaseAddress:8字节大小,由32位的4字节扩展到8字节,类型也改成了void*;
- 0x18 ULONG Ldr:8字节大小,由32位的4字节扩展到8字节;
3. _PEB_LDR_DATA结构
_PEB_LDR_DATA结构体是Windows加载器用来跟踪当前进程已加载的所有模块主要是(EXE和DLL文件)的核心数据结构,它由操作系统加载器维护,并通过PEB结构体中的Ldr字段引用。
_PEB_LDR_DATA结构体32位定义如下:
//0x30
struct _PEB_LDR_DATA
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; //0xc
struct _LIST_ENTRY InMemoryOrderModuleList; //0x14
struct _LIST_ENTRY InInitializationOrderModuleList; //0x1c
VOID* EntryInProgress; //0x24
UCHAR ShutdownInProgress; //0x28
VOID* ShutdownThreadId; //0x2c
};
_PEB_LDR_DATA结构体64位定义如下:
//0x58
struct _PEB_LDR_DATA
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; //0x10
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
VOID* EntryInProgress; //0x40
UCHAR ShutdownInProgress; //0x48
VOID* ShutdownThreadId; //0x50
};
这个结构体的核心部分是三个双向链表,而且都是_LIST_ENTRY结构体,这三个链表使用了三种不同的方式来遍历进程的所有加载模块,三个链表都指向了_LDR_DATA_TABLE_ENTRY结构体,只是顺序不同:
- InLoadOrderModuleList:按照加载顺序遍历模块,它列出了模块(DLL 和 EXE)被操作系统加载器加载到内存中的顺序,第一项通常是ntdll.dll,然后是主程序exe,接着是其他DLL;
- InMemoryOrderModuleList:按内存顺序,按照模块在内存虚拟地址空间的起始地址升序排列;
- InInitializationOrderModuleList:按初始化顺序加载;
4. _LIST_ENTRY结构
_LIST_ENTRY结构体被设计用来实现双向循环链表,结构体定义如下:
//32位0x08
struct _LIST_ENTRY
{
struct _LIST_ENTRY* Flink; //0x00:指向链表中下一个元素的_LIST_ENTRY部分
struct _LIST_ENTRY* Blink; //0x04:指向链表中上一个元素的_LIST_ENTRY部分
};
//64位 0x10
struct _LIST_ENTRY
{
struct _LIST_ENTRY* Flink; //0x00:指向链表中下一个元素的_LIST_ENTRY部分
struct _LIST_ENTRY* Blink; //0x08:指向链表中上一个元素的_LIST_ENTRY部分
};
_LIST_ENTRY结构体很简洁,仅包含2个指针,32位结构中是4字节指针,64位结构中是8字节指针。
5. _LDR_DATA_TABLE_ENTRY
该结构体是双向循环链表_LIST_ENTRY的实际数据节点,操作系统加载器每加载一个模块(exe或dll),都会创建一个_LDR_DATA_TABLE_ENTRY结构来链接到_PEB_LDR_DATA结构体维护的三个链表中,用于描述每一个已加载模块(exe或dll)在内存的详细信息。
_LDR_DATA_TABLE_ENTRY结构体32位定义如下:
//0xA8字节
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
union
{
UCHAR FlagGroup[4]; //0x34
ULONG Flags; //0x34
struct
{
ULONG PackagedBinary:1; //0x34
ULONG MarkedForRemoval:1; //0x34
ULONG ImageDll:1; //0x34
ULONG LoadNotificationsSent:1; //0x34
ULONG TelemetryEntryProcessed:1; //0x34
ULONG ProcessStaticImport:1; //0x34
ULONG InLegacyLists:1; //0x34
ULONG InIndexes:1; //0x34
ULONG ShimDll:1; //0x34
ULONG InExceptionTable:1; //0x34
ULONG ReservedFlags1:2; //0x34
ULONG LoadInProgress:1; //0x34
ULONG LoadConfigProcessed:1; //0x34
ULONG EntryProcessed:1; //0x34
ULONG ProtectDelayLoad:1; //0x34
ULONG ReservedFlags3:2; //0x34
ULONG DontCallForThreads:1; //0x34
ULONG ProcessAttachCalled:1; //0x34
ULONG ProcessAttachFailed:1; //0x34
ULONG CorDeferredValidate:1; //0x34
ULONG CorImage:1; //0x34
ULONG DontRelocate:1; //0x34
ULONG CorILOnly:1; //0x34
ULONG ChpeImage:1; //0x34
ULONG ReservedFlags5:2; //0x34
ULONG Redirected:1; //0x34
ULONG ReservedFlags6:2; //0x34
ULONG CompatDatabaseProcessed:1; //0x34
};
};
USHORT ObsoleteLoadCount; //0x38
USHORT TlsIndex; //0x3a
struct _LIST_ENTRY HashLinks; //0x3c
ULONG TimeDateStamp; //0x44
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x48
VOID* Lock; //0x4c
struct _LDR_DDAG_NODE* DdagNode; //0x50
struct _LIST_ENTRY NodeModuleLink; //0x54
struct _LDRP_LOAD_CONTEXT* LoadContext; //0x5c
VOID* ParentDllBase; //0x60
VOID* SwitchBackContext; //0x64
struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0x68
struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0x74
ULONG OriginalBase; //0x80
union _LARGE_INTEGER LoadTime; //0x88
ULONG BaseNameHashValue; //0x90
enum _LDR_DLL_LOAD_REASON LoadReason; //0x94
ULONG ImplicitPathOptions; //0x98
ULONG ReferenceCount; //0x9c
ULONG DependentLoadFlags; //0xa0
UCHAR SigningLevel; //0xa4
};
_LDR_DATA_TABLE_ENTRY结构体64位定义如下:
//0x120字节
struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
VOID* DllBase; //0x30
VOID* EntryPoint; //0x38
ULONG SizeOfImage; //0x40
struct _UNICODE_STRING FullDllName; //0x48
struct _UNICODE_STRING BaseDllName; //0x58
union
{
UCHAR FlagGroup[4]; //0x68
ULONG Flags; //0x68
struct
{
ULONG PackagedBinary:1; //0x68
ULONG MarkedForRemoval:1; //0x68
ULONG ImageDll:1; //0x68
ULONG LoadNotificationsSent:1; //0x68
ULONG TelemetryEntryProcessed:1; //0x68
ULONG ProcessStaticImport:1; //0x68
ULONG InLegacyLists:1; //0x68
ULONG InIndexes:1; //0x68
ULONG ShimDll:1; //0x68
ULONG InExceptionTable:1; //0x68
ULONG ReservedFlags1:2; //0x68
ULONG LoadInProgress:1; //0x68
ULONG LoadConfigProcessed:1; //0x68
ULONG EntryProcessed:1; //0x68
ULONG ProtectDelayLoad:1; //0x68
ULONG ReservedFlags3:2; //0x68
ULONG DontCallForThreads:1; //0x68
ULONG ProcessAttachCalled:1; //0x68
ULONG ProcessAttachFailed:1; //0x68
ULONG CorDeferredValidate:1; //0x68
ULONG CorImage:1; //0x68
ULONG DontRelocate:1; //0x68
ULONG CorILOnly:1; //0x68
ULONG ChpeImage:1; //0x68
ULONG ReservedFlags5:2; //0x68
ULONG Redirected:1; //0x68
ULONG ReservedFlags6:2; //0x68
ULONG CompatDatabaseProcessed:1; //0x68
};
};
USHORT ObsoleteLoadCount; //0x6c
USHORT TlsIndex; //0x6e
struct _LIST_ENTRY HashLinks; //0x70
ULONG TimeDateStamp; //0x80
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
VOID* Lock; //0x90
struct _LDR_DDAG_NODE* DdagNode; //0x98
struct _LIST_ENTRY NodeModuleLink; //0xa0
struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0
VOID* ParentDllBase; //0xb8
VOID* SwitchBackContext; //0xc0
struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
ULONGLONG OriginalBase; //0xf8
union _LARGE_INTEGER LoadTime; //0x100
ULONG BaseNameHashValue; //0x108
enum _LDR_DLL_LOAD_REASON LoadReason; //0x10c
ULONG ImplicitPathOptions; //0x110
ULONG ReferenceCount; //0x114
ULONG DependentLoadFlags; //0x118
UCHAR SigningLevel; //0x11c
};
重要成员说明:
- InLoadOrderLinks:LIST_ENTRY结构,用于连接到InLoadOrderModuleList链表;
- InMemoryOrderLinks:LIST_ENTRY结构,用于连接到InMemoryOrderModuleList链表;
- InInitializationOrderLinks:LIST_ENTRY结构,用于连接到InInitializationOrderModuleList链表;
- DllBase:32位下是0x18,64位下是0x30,4字节大小,模块(exe或dll)的基地址(VA),即加载到虚拟内存的起始地址,指向MZ-DOS头;
- EntryPoint:32位0x1c,64位0x38,表示模块的入口点地址;
- SizeOfImage:32位0x20,64位0x40,模块在内存中所占用的总大小(字节);
- FullDllName:32位0x24,64位0x48,它是一个_UNICODE_STRING结构体,后面会说;
- BaseDllName:32位0x2c,64位0x58,也是一个_UNICODE_STRING结构体,只包含模块名称;
6. _UNICODE_STRING结构
_UNICODE_STRING结构体定义非常简洁,用于管理Unicode编码的字符串:
//32位0x08
struct _UNICODE_STRING
{
USHORT Length; //0x0
USHORT MaximumLength; //0x2
WCHAR* Buffer; //0x4
};
//64位0x10
struct _UNICODE_STRING
{
USHORT Length; //0x0
USHORT MaximumLength; //0x2
WCHAR* Buffer; //0x8
};
FullDllName和BaseDllName都引用了_UNICODE_STRING结构体:
- Length:字符串的实际长度(以字节为单位),不包含末尾的\0;
- MaximumLength:Buffer成员指向的内存块总大小(以字节为单位);
- Buffer:指向实际存储Unicode字符数组的内存地址,也就是说FullDllName获取模块的路径,需要偏移到第三个参数才能获取;
到了这一步,基本上就摸清了动态获取函数地址的方法,通过遍历_PEB_LDR_DATA中的链表,就可以找到目标模块的LDR_DATA_TABLE_ENTRY。一旦获取到DllBase地址,就可以解析模块的PE头部,读取导出地址表(EAT),从而找到所需的 API 函数的内存地址。
1. 一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
评论