FS TIB TEB PEB
本篇发表我的TEB 和 PEB的一些见解,我把它图形化了,更形象便于理解。
首先对于TIB TEB PEB的概念我引用一下别人的blog了,以下内容取自看雪:
TEB(Thread Environment Block,线程环境块):系统在此TEB中保存频繁使用的线程相关的数据。位于用户地址空间。进程中的每个线程都有自己的一个TEB。一个进程的所有TEB都以堆栈的方式,存放在从0x7FFDE000(WinXP,当然,不同的系统可能位于不同的地址)开始的线性内存中,每4KB为一个完整的TEB,不过该内存区域是向下扩展的。在用户模式下,当前线程的TEB位于独立的4KB段,可通过CPU的FS寄存器来访问该段,一般存储在[FS:0]。在用户态下WinDbg中可用命令$thread取得TEB地址。
PEB(Process Environment Block,进程环境块)存放进程信息,每个进程都有自己的PEB信息。位于用户地址空间。在Win XP下,进程环境块的地址对于每个进程来说是固定的,在0x7FFDF000处,这是用户地址空间,所以程序能够直接访问。
首先,来借助于windbg工具来观察 TEB 结构。
0:000:x86> dt ntdll32!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
+0x034 LastErrorValue : Uint4B
+0x038 CountOfOwnedCriticalSections : Uint4B
+0x03c CsrClientThread : Ptr32 Void
+0x040 Win32ThreadInfo : Ptr32 Void
+0x044 User32Reserved : [26] Uint4B
+0x0ac UserReserved : [5] Uint4B
+0x0c0 WOW32Reserved : Ptr32 Void
+0x0c4 CurrentLocale : Uint4B
+0x0c8 FpSoftwareStatusRegister : Uint4B
+0x0cc SystemReserved1 : [54] Ptr32 Void
+0x1a4 ExceptionCode : Int4B
+0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK
+0x1ac SpareBytes : [36] UChar
+0x1d0 TxFsContext : Uint4B
+0x1d4 GdiTebBatch : _GDI_TEB_BATCH
+0x6b4 RealClientId : _CLIENT_ID
+0x6bc GdiCachedProcessHandle : Ptr32 Void
+0x6c0 GdiClientPID : Uint4B
+0x6c4 GdiClientTID : Uint4B
+0x6c8 GdiThreadLocalInfo : Ptr32 Void
+0x6cc Win32ClientInfo : [62] Uint4B
+0x7c4 glDispatchTable : [233] Ptr32 Void
+0xb68 glReserved1 : [29] Uint4B
+0xbdc glReserved2 : Ptr32 Void
+0xbe0 glSectionInfo : Ptr32 Void
+0xbe4 glSection : Ptr32 Void
+0xbe8 glTable : Ptr32 Void
+0xbec glCurrentRC : Ptr32 Void
+0xbf0 glContext : Ptr32 Void
+0xbf4 LastStatusValue : Uint4B
+0xbf8 StaticUnicodeString : _UNICODE_STRING
+0xc00 StaticUnicodeBuffer : [261] Wchar
+0xe0c DeallocationStack : Ptr32 Void
+0xe10 TlsSlots : [64] Ptr32 Void
+0xf10 TlsLinks : _LIST_ENTRY
+0xf18 Vdm : Ptr32 Void
+0xf1c ReservedForNtRpc : Ptr32 Void
+0xf20 DbgSsReserved : [2] Ptr32 Void
+0xf28 HardErrorMode : Uint4B
+0xf2c Instrumentation : [9] Ptr32 Void
+0xf50 ActivityId : _GUID
+0xf60 SubProcessTag : Ptr32 Void
+0xf64 EtwLocalData : Ptr32 Void
+0xf68 EtwTraceData : Ptr32 Void
+0xf6c WinSockData : Ptr32 Void
+0xf70 GdiBatchCount : Uint4B
+0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER
+0xf74 IdealProcessorValue : Uint4B
+0xf74 ReservedPad0 : UChar
+0xf75 ReservedPad1 : UChar
+0xf76 ReservedPad2 : UChar
+0xf77 IdealProcessor : UChar
+0xf78 GuaranteedStackBytes : Uint4B
+0xf7c ReservedForPerf : Ptr32 Void
+0xf80 ReservedForOle : Ptr32 Void
+0xf84 WaitingOnLoaderLock : Uint4B
+0xf88 SavedPriorityState : Ptr32 Void
+0xf8c SoftPatchPtr1 : Uint4B
+0xf90 ThreadPoolData : Ptr32 Void
+0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
+0xf98 MuiGeneration : Uint4B
+0xf9c IsImpersonating : Uint4B
+0xfa0 NlsCache : Ptr32 Void
+0xfa4 pShimData : Ptr32 Void
+0xfa8 HeapVirtualAffinity : Uint4B
+0xfac CurrentTransactionHandle : Ptr32 Void
+0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME
+0xfb4 FlsData : Ptr32 Void
+0xfb8 PreferredLanguages : Ptr32 Void
+0xfbc UserPrefLanguages : Ptr32 Void
+0xfc0 MergedPrefLanguages : Ptr32 Void
+0xfc4 MuiImpersonation : Uint4B
+0xfc8 CrossTebFlags : Uint2B
+0xfc8 SpareCrossTebBits : Pos 0, 16 Bits
+0xfca SameTebFlags : Uint2B
+0xfca SafeThunkCall : Pos 0, 1 Bit
+0xfca InDebugPrint : Pos 1, 1 Bit
+0xfca HasFiberData : Pos 2, 1 Bit
+0xfca SkipThreadAttach : Pos 3, 1 Bit
+0xfca WerInShipAssertCode : Pos 4, 1 Bit
+0xfca RanProcessInit : Pos 5, 1 Bit
+0xfca ClonedThread : Pos 6, 1 Bit
+0xfca SuppressDebugMsg : Pos 7, 1 Bit
+0xfca DisableUserStackWalk : Pos 8, 1 Bit
+0xfca RtlExceptionAttached : Pos 9, 1 Bit
+0xfca InitialThread : Pos 10, 1 Bit
+0xfca SpareSameTebBits : Pos 11, 5 Bits
+0xfcc TxnScopeEnterCallback : Ptr32 Void
+0xfd0 TxnScopeExitCallback : Ptr32 Void
+0xfd4 TxnScopeContext : Ptr32 Void
+0xfd8 LockCount : Uint4B
+0xfdc SpareUlong0 : Uint4B
+0xfe0 ResourceRetValue : Ptr32 Void
这是一个完整的TEB结构,我这里也有一份pteb.h的头文件
typedef struct _NT_TEB
{
NT_TIB Tib; // 00h
PVOID EnvironmentPointer; // 1Ch
CLIENT_ID Cid; // 20h
PVOID ActiveRpcInfo; // 28h
PVOID ThreadLocalStoragePointer; // 2Ch
PPEB Peb; // 30h
ULONG LastErrorValue; // 34h
ULONG CountOfOwnedCriticalSections; // 38h
PVOID CsrClientThread; // 3Ch
PVOID Win32ThreadInfo; // 40h
ULONG Win32ClientInfo[0x1F]; // 44h
PVOID WOW32Reserved; // C0h
ULONG CurrentLocale; // C4h
ULONG FpSoftwareStatusRegister; // C8h
PVOID SystemReserved1[0x36]; // CCh
PVOID Spare1; // 1A4h
LONG ExceptionCode; // 1A8h
ULONG SpareBytes1[0x28]; // 1ACh
PVOID SystemReserved2[0xA]; // 1D4h
GDI_TEB_BATCH GdiTebBatch; // 1FCh
ULONG gdiRgn; // 6DCh
ULONG gdiPen; // 6E0h
ULONG gdiBrush; // 6E4h
CLIENT_ID RealClientId; // 6E8h
PVOID GdiCachedProcessHandle; // 6F0h
ULONG GdiClientPID; // 6F4h
ULONG GdiClientTID; // 6F8h
PVOID GdiThreadLocaleInfo; // 6FCh
PVOID UserReserved[5]; // 700h
PVOID glDispatchTable[0x118]; // 714h
ULONG glReserved1[0x1A]; // B74h
PVOID glReserved2; // BDCh
PVOID glSectionInfo; // BE0h
PVOID glSection; // BE4h
PVOID glTable; // BE8h
PVOID glCurrentRC; // BECh
PVOID glContext; // BF0h
NTSTATUS LastStatusValue; // BF4h
UNICODE_STRING StaticUnicodeString; // BF8h
WCHAR StaticUnicodeBuffer[0x105]; // C00h
PVOID DeallocationStack; // E0Ch
PVOID TlsSlots[0x40]; // E10h
LIST_ENTRY TlsLinks; // F10h
PVOID Vdm; // F18h
PVOID ReservedForNtRpc; // F1Ch
PVOID DbgSsReserved[0x2]; // F20h
ULONG HardErrorDisabled; // F28h
PVOID Instrumentation[0x10]; // F2Ch
PVOID WinSockData; // F6Ch
ULONG GdiBatchCount; // F70h
ULONG Spare2; // F74h
ULONG Spare3; // F78h
ULONG Spare4; // F7Ch
PVOID ReservedForOle; // F80h
ULONG WaitingOnLoaderLock; // F84h
PVOID StackCommit; // F88h
PVOID StackCommitMax; // F8Ch
PVOID StackReserve; // F90h
PVOID MessageQueue; // ???
} NT_TEB, *PNT_TEB;
看到没有 :
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
PPEB Peb; // 30h
TEB偏移的0x30地址就是PEB的地址,下面来看看PEB的结构:
typedef struct _PEB
{
UCHAR InheritedAddressSpace; // 00h
UCHAR ReadImageFileExecOptions; // 01h
UCHAR BeingDebugged; // 02h
UCHAR Spare; // 03h
PVOID Mutant; // 04h
PVOID ImageBaseAddress; // 08h
PPEB_LDR_DATA Ldr; // 0Ch
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h
PVOID SubSystemData; // 14h
PVOID ProcessHeap; // 18h
PVOID FastPebLock; // 1Ch
PPEBLOCKROUTINE FastPebLockRoutine; // 20h
PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h
ULONG EnvironmentUpdateCount; // 28h
PVOID* KernelCallbackTable; // 2Ch
PVOID EventLogSection; // 30h
PVOID EventLog; // 34h
PPEB_FREE_BLOCK FreeList; // 38h
ULONG TlsExpansionCounter; // 3Ch
PVOID TlsBitmap; // 40h
ULONG TlsBitmapBits[0x2]; // 44h
PVOID ReadOnlySharedMemoryBase; // 4Ch
PVOID ReadOnlySharedMemoryHeap; // 50h
PVOID* ReadOnlyStaticServerData; // 54h
PVOID AnsiCodePageData; // 58h
PVOID OemCodePageData; // 5Ch
PVOID UnicodeCaseTableData; // 60h
ULONG NumberOfProcessors; // 64h
ULONG NtGlobalFlag; // 68h
UCHAR Spare2[0x4]; // 6Ch
LARGE_INTEGER CriticalSectionTimeout; // 70h
ULONG HeapSegmentReserve; // 78h
ULONG HeapSegmentCommit; // 7Ch
ULONG HeapDeCommitTotalFreeThreshold; // 80h
ULONG HeapDeCommitFreeBlockThreshold; // 84h
ULONG NumberOfHeaps; // 88h
ULONG MaximumNumberOfHeaps; // 8Ch
PVOID** ProcessHeaps; // 90h
PVOID GdiSharedHandleTable; // 94h
PVOID ProcessStarterHelper; // 98h
PVOID GdiDCAttributeList; // 9Ch
PVOID LoaderLock; // A0h
ULONG OSMajorVersion; // A4h
ULONG OSMinorVersion; // A8h
ULONG OSBuildNumber; // ACh
ULONG OSPlatformId; // B0h
ULONG ImageSubSystem; // B4h
ULONG ImageSubSystemMajorVersion; // B8h
ULONG ImageSubSystemMinorVersion; // C0h
ULONG GdiHandleBuffer[0x22]; // C4h
PVOID ProcessWindowStation; // ???
} PEB, *PPEB;
PVOID ImageBaseAddress; // 08h
//偏移08h的地址就是程序的基址,往上看,
UCHAR BeingDebugged; // 02h,这里就表示程序是否是在被调试模式了。
接下来,咱们就用ollydbg来调试看看这些数据了,记住,并没有那么神秘的。
我这里写一个小程序里面就调用一个函数GetModuleHandle,咱们要做的就是跟进这个函数去看看
这个就是这个函数的执行体了,咱们要关心的就是7C80B764这个地址的一句:
mov eax,dword ptr fs:[18]
fs:[0]寄存器里面存的就是指向TEB的地址,看看是什么地址啊,
看到没eax指向的就是TEB的地址,接着执行,teb地址偏移30由上面的头文件就可以看出是peb的地址了,
此时可以确定peb的地址就是0x7FFDE000了
由上面的PEB结构
PVOID ImageBaseAddress; // 08h
再偏移08h就是基址了
UCHAR BeingDebugged; // 02h
偏移2字节就是表示是否被调试跟踪了
偏移2处就是01了 ,呵呵 ,表示被调试跟踪了,偏移8是00400000,这就是基址了,可以证明了
如果自己用代码可以这么测试了:
mov eax, fs:[30h] ;指向 PEB
movzx eax, byte ptr [eax + 2h]
or al, al
jz _Fine
如果等于0就是ok得了否则就被跟踪了。
//-----------------------------------------------------------------------------------------------------------------------------------------------------------
以上某些描述有些偏颇,以下是个人见解:
1、fs:[0]寄存器里面存的就是指向_NT_TIB.ExceptionList 指针
2、在Win XP下,进程环境块的地址对于每个进程来说并不固定,我在windows server2003 sp2和winxp sp2上测试过,其它版本上没有测试过
3、fs:[0x18] 地址指向线程环境块_TEB
上面两幅图诠释了内部结构:
1、取PEB地址指针有两种手段:
手段一、FS:[0x18]+0x30
手段二、FS:[0x30]
2、TIB结构实际被包含在TEB的首部
3、FS:[0]存放的是指向TIB结构的Exception List成员的指针
4、PEB首地址加上偏移0xC的位置存放的指向PEB_LDR_DATA的指针
5、PEB_LDR_DATA结构尾部实际上存放的是LIST_ENTRY的数组
6、InLoadOrderModuleList的FLINK存放的是指向LDR_MODULE的指针
7、LDR_MODULE结构的首部存放的是LIST_ENTRY结构的数组
基于以上实现遍历当前进程所有加载的模块:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int __cdecl _tmain(int argc, _TCHAR **argv, _TCHAR **envp)
{
void *pebAddr = NULL;
void *ldrAddr = NULL;
void *fLink = NULL;
void *p = NULL;
void *baseAddr = NULL;
void *dllName = NULL;
void *fullDllName = NULL;
void *entryPoint = NULL;
void *imageOfSize = NULL;
void *isDebuged = NULL;
__asm
{
mov eax,fs:[0x18] ;取TEB首地址
add eax,0x30 ;PEB地址的指针
mov eax,[eax] ;取PEB首地址
mov pebAddr,eax
}
ldrAddr = *(( void ** )(( BYTE* )pebAddr+0xC));
isDebuged = *(( void ** )(( BYTE* )pebAddr+0x02));
printf("当前程序%s被调试\n",((WORD)isDebuged) & 0x1?"正在":"没有");
printf("\n--------------------------按加载顺序遍历双向循环链表----------------------------\n\n");
fLink = *(( void ** )(( BYTE* )ldrAddr+0xC));//按加载顺序遍历双向循环链表
p = fLink;
printf(TEXT("\tPEB ADDRESS = \t0x%08X\n"),pebAddr);
printf(TEXT("\tLDR ADDRESS = \t0x%08X\n"),ldrAddr);
printf(TEXT("----------------------------------------------------\n"));
do
{
baseAddr = *(( void ** )(( BYTE* )p+0x18));
dllName = *(( void ** )(( BYTE* )p+0x30));
fullDllName = *(( void ** )(( BYTE* )p+0x28));
entryPoint = *(( void ** )(( BYTE* )p+0x1C));
imageOfSize = *(( void ** )(( BYTE* )p+0x20));
wprintf(L"\tModuleName:%s\n",dllName);
printf(TEXT("\t\tBase Address:0x%08X\n"),baseAddr);
wprintf(L"\t\tFull Module Name:%s\n",fullDllName);
printf(TEXT("\t\tentryPoint:0x%08X\n"),entryPoint);
printf(TEXT("\t\timageOfSize:0x%08X\n"),imageOfSize);
p = *( void ** )p;
} while (p!=fLink);
return (0);
}
FS TIB TEB PEB相关推荐
- 反调试/反汇编技术、TEB/PEB部分说明
反调试技术 WindowsAPI ISDebuggerPresent 查询PEB进程环境块中的ISDebugged标志 CheckRemoteDebuggerPresent 类似于IsDebugger ...
- TEB,PEB,LDR结构
首先查看TEB结构 TEB结构中第一个成员为TIB结构,从偏移量可以看出从0x00到0x1C之间的内容均为TIB结构的成员,为了方便理解,我将TIB结构在TEB中展开来查看 ntdll!_TEB+0x ...
- php滑动teb效果,PEB和TEB资料整合
一.概念 TEB(Thread Environment Block,线程环境块)系统在此TEB中保存频繁使用的线程相关的数据.位于用户地址空间,在比 PEB 所在地址低的地方.进程中的每个线程都有自己 ...
- Thread Environment Block(TEB)
TEB简介 TEB(Thread Environment Block,线程环境块)指线程环境块,该结构体包含进程中运行线程的各种信息,进程中的每个线程都对应着一个TEB结构体.不同OS中TEB结构体的 ...
- 通过PEB获取模块基址
TEB偏移0x30处,即FS:[0x30]地址处保存着一个指针,指向PEB,PEB结构的偏移0xC处保存着另外一个指针ldr,该指针执行PEB_LDR_DATA PEB结构 typedef struc ...
- Windows 中 FS 段寄存器
代码运行在RING0(系统地址空间)和RING3(用户地址空间)时,FS段寄存器分别指向GDT(全局描述符表)中不同段:在RING3下,FS段值是0x3B(这是WindowsXP下值:在Windows ...
- 利用FS寄存器获取KERNEL32.DLL基址算法的证明
FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移 说明 000 指向SEH链指针 004 线程堆栈顶部 008 线程堆栈底部 00C SubSystemTib 010 FiberD ...
- mov eax,dword ptr fs:[0] 指令
FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移 说明 000 指向SEH链指针 004 线程堆栈顶部 008 线程堆栈底部 00C SubSystemTib 010 FiberData 01 ...
- 利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ)
转自:http://blog.csdn.net/int2e/archive/2008/01/09/2032732.aspx FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移 说明 000 ...
最新文章
- matlab入门学习2
- sap内表 table_LINE
- 服务器维护 测试化验加工费,测试化验加工费.PPT
- Image:介绍一些跟图片有关的控件,如图片展示特效,图片生产,图片保护等
- tomcat路径配置详解
- jsencrypt代码分析——openssl的rsa加密解密在js的实现
- 计算机四级网络工程师考点速查,计算机四级《网络工程师》考点习题
- 梅州市2021普通高考成绩查询,梅州高考成绩查询入口
- css3-伪元素与伪类
- Codeforces 448 D. Multiplication Table
- 苹果CMSv10新手入门安装必看教程
- 微信朋友圈点赞生成器
- 超级右键-Mac右键扩展工具
- img和文字都居中对齐
- 【开发环境】Ubuntu 安装 Visual Studio Code 开发环境 ( 下载 Visual Studio Code 安装器 | Ubuntu 安装 deb 包 )
- python过去电脑网关不可用怎么办_电脑默认网关不可用怎么解决 Win7系统默认网关不可用终极解决方法...
- Android、iPhone和Java三个平台一致的加密方法
- 垃圾回收之G1收集过程
- R绘制股票走势图及年份成交量图
- 安装RHEL7.5超详细教程