从TEB到PEB再到SEH(一)
什么是TEB?
TEB(Thread Environment Block,线程环境块)
线程环境块中存放着进程中所有线程的各种信息
这里我们了解到了TEB即为线程环境块, 进程中每一条线程都对应着的自己的“TEB”。
TEB的访问方法
ntdll.NtCurrentTeb() 函数用来返回当前线程的TEB结构体指针
从图中我们可以看到NtCurrentTeb() 函数所返回的结构体指针即为 fs:[0x18] 的值,里面的值即为TEB的结构体指针,对比数据窗口即可发现
了解TEB的结构
因为TEB的结构MSDN中没有明确的说明,这里我们利用windbg和符号文件查看它的数据结构:
Windows XP SP3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
nt!_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 ActivationContextStack : _ACTIVATION_CONTEXT_STACK + 0x1bc SpareBytes1 : [ 24 ] UChar + 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 ] Uint2B + 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 HardErrorsAreDisabled : Uint4B + 0xf2c Instrumentation : [ 16 ] Ptr32 Void + 0xf6c WinSockData : Ptr32 Void + 0xf70 GdiBatchCount : Uint4B + 0xf74 InDbgPrint : UChar + 0xf75 FreeStackOnTermination : UChar + 0xf76 HasFiberData : UChar + 0xf77 IdealProcessor : UChar + 0xf78 Spare3 : Uint4B + 0xf7c ReservedForPerf : Ptr32 Void + 0xf80 ReservedForOle : Ptr32 Void + 0xf84 WaitingOnLoaderLock : Uint4B + 0xf88 Wx86Thread : _Wx86ThreadState + 0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void + 0xf98 ImpersonationLocale : 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 SafeThunkCall : UChar + 0xfb5 BooleanSpare : [ 3 ] UChar |
这里我们详细的介绍常用的结构体成员及作用:
- +0x000 NtTib : _NT_TIB
TEB的结构体的第一个成员NtTib即为我们常说的TIB(Thread Information Block,线程信息块)typedef struct _NT_TIB //sizeof 1ch
{
00h struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; //即为指向_EXCEPTION_REGISTRATION_RECORD结构体的链表指针(SEH)
04h PVOID StackBase;//这里为线程堆栈顶部
08h PVOID StackLimit;//这里为线程堆栈底部
0ch PVOID SubSystemTib;
union {
PVOID FiberData;
10h DWORD Version;
};
14h PVOID ArbitraryUserPointer;
18h struct _NT_TIB *Self; //这为_NT_TIB结构体的自引用指针,即为NtCurrentTeb() 函数所读出的TEB结构体指针
}NT_TIB; - +0x020 ClientId : _CLIENT_ID
这个结构体成员挺有趣的,我们用windbg查询下结构:
UniqueProcess:这个为当前进程的的Pid,可用函数 GetCurrentProcessId() 访问当前结构体成员获取进程标识符:
可以看到TEB+0x20即为 UniqueProcess 的成员变量。UniqueThread:
这个为当前进程的的Tid,可用函数 GetCurrentThreadId() 访问当前结构体成员获取线程标识符:
可以看到TEB+0x20即为 UniqueThread 的成员变量。
- +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
这个即为PEB结构体的指针,所以说一般 fs:[0x30] 即为PEB的起始地址。
什么是PEB?
PEB( Process Envirorment Block ,进程环境块),PEB是存放着进程信息的结构体,线程TEB结构体中,每个TEB+0x30(fs:[0x30])中都指向同一个地址(TEB.ProcessEnvironmentBlock),我们可以用fs:[0x30]来访问PEB的结构体地址

PEB的数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
nt!_PEB + 0x000 InheritedAddressSpace : UChar + 0x001 ReadImageFileExecOptions : UChar + 0x002 BeingDebugged : UChar + 0x003 SpareBool : UChar + 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 FastPebLockRoutine : Ptr32 Void + 0x024 FastPebUnlockRoutine : Ptr32 Void + 0x028 EnvironmentUpdateCount : Uint4B + 0x02c KernelCallbackTable : Ptr32 Void + 0x030 SystemReserved : [ 1 ] Uint4B + 0x034 AtlThunkSListPtr32 : Uint4B + 0x038 FreeList : Ptr32 _PEB_FREE_BLOCK + 0x03c TlsExpansionCounter : Uint4B + 0x040 TlsBitmap : Ptr32 Void + 0x044 TlsBitmapBits : [ 2 ] Uint4B + 0x04c ReadOnlySharedMemoryBase : Ptr32 Void + 0x050 ReadOnlySharedMemoryHeap : 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 Void + 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 ImageProcessAffinityMask : 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 Void + 0x1fc ProcessAssemblyStorageMap : Ptr32 Void + 0x200 SystemDefaultActivationContextData : Ptr32 Void + 0x204 SystemAssemblyStorageMap : Ptr32 Void + 0x208 MinimumStackCommit : Uint4B |
下面我来举例几个常用的结构体成员:
- +0x002 BeingDebugged : UChar
这个结构体成员大家应该都懂,表示当前进程是否处于调试状态,也就是函数 IsDebuggerPresent() 所访问的结构体成员.
这里我看可以看到先是取出PEB的结构体地址,在取出PEB.BeingDebugged 结构体成员然后返回,因为我们这里有海风月影大牛的SOD插件所以我们不必担心,包括下面的几个结构体成员都一起处理掉的。
- +0x008 ImageBaseAddress : Ptr32 Void
这个结构体成员我们也经常用到,也就是自身的 ImageBase ,和PE结构中的 IMAGE_OPTIONAL_HEADER.ImageBase 。
可用函 GetModuleHandle (0) 获取自身模块句柄来访问这个结构体成员:
这里判断参数是否为0,也就是取自身的模块句柄 (ImaheBase)这里也同上,先是取出PEB结构体地址,再取出 ImageBaseAddress 。
- +0x00c Ldr : Ptr32 _PEB_LDR_DATA
这个结构体成员就很复杂了,它是指向 _PEB_LDR_DATA 的结构体指针,当DLL加载到进程,可从 PEB.Ldr 中获取该模块的基址和其他信息:
12345678910ntdll!_PEB_LDR_DATA
+
0x000
Length
/
/
结构体大小
+
0x004
Initialized
/
/
进程是否初始化完成
+
0x008
SsHandle
+
0x00c
InLoadOrderModuleList : _LIST_ENTRY
+
0x014
InMemoryOrderModuleList : _LIST_ENTRY
+
0x01c
InInitializationOrderModuleList : _LIST_ENTRY
+
0x024
EntryInProgress
+
0x028
ShutdownInProgress
+
0x02c
ShutdownThreadId
InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList 这三个结构体成员都是指向LIST_ENTRY
的结构体指针,我们查询下这个数据结构:可以看出这是一个双向链表,链表中存放着 _LDR_DATA_TABLE_ENTRY 的结构体信息:
每个进程中的DLL加载进来都有与之对于的_LDR_DATA_TABLE_ENTRY 结构体,这些结构相互链接就形成了双向链表
- +0x018 ProcessHeap : Ptr32 Void
这个结构体成员就是进程堆的句柄,也就是指向结构体HEAP的指针,我们查询下结构体成员:
程序正常运行时,ProcessHeap.Flags的值为2 ,ProcessHeap.
ForceFlags 的值为0,也常用于反调试。
ProcessHeap结构体成员指向的HEAP结构体指针可用函数 GetProcessHeap()获取:
- +0x068 NtGlobalFlag : Uint4B
再调试状态时,PEB.NtGlobalFlag 的值为0x70 ,这个值我也不清楚 只记得几个Flages的值进行 OR(位或) 的结果
转自https://bbs.pediy.com/thread-223816.htm
从TEB到PEB再到SEH(一)的更多相关文章
- 从TEB到PEB再到SEH(二)
什么是SEH? SEH( Structured Exception Handling , 结构化异常处理 ) 结构化异常处理(SEH)是Windows操作系统提供的强大异常处理功能.而Visual C ...
- 旧书重温:0day2【3】 详细解读PEB法 查找kener32地址
题外话:上一篇文章中的 PEB法查找kerner32地址的方法 对TEB.PEB .PE结构 知识要求很高,确实在写汇编代码时候小编 感觉自己能力,信手啪啪一顿乱撸,结果一运行,非法访问了,没办法翻阅 ...
- KPROCESS IDT PEB Ldr 《寒江独钓》内核学习笔记(3)
继续上一篇(2)未完成的研究,我们接下来学习 KPROCESS这个数据结构. 1. 相关阅读材料 <深入理解计算机系统(原书第2版)> 二. KPROCESS KPROCESS,也叫内核进 ...
- 【旧文章搬运】获取并修改PEB中的映像路径,命令行和当前目录
原文发表于百度空间,2008-7-24 当时对UNICODE_STRING的使用还有点问题,导致最终效果图中字符串被截断了======================================= ...
- 栈溢出笔记1.9 认识SEH
从本节開始,我们就要研究一些略微高级点的话题了,如同在1.2节中看到的,Windows中为抵抗栈溢出做了非常多保护性的检查工作,编译的程序默认开启了这些保护. 假设我们不能绕过这些保护.那么我们的Sh ...
- windows的SEH异常处理以及顶层异常处理
前言 windows的SEH结构化异常处理是基于线程的,传统的SEH结构化异常会基于堆栈形成一条包含异常回调函数地址的链(SEH链).而fs:[0](TEB的第一个字段)指向这条链的链头,当有异常发生 ...
- 第23章 SEH结构化异常处理(3)_终止处理程序
23.3 终止处理程序 23.3.1 程序的结构 (1)框架 __try{ //被保护的代码块 …… } __finally{ //终止处理 } (2)__try/__finally的特点 ①fina ...
- 结构化异常SEH处理机制详细介绍(二)
本文将全面阐述__try,__except,__finally,__leave异常模型机制,它也即是Windows系列操作系统平台上提供的SEH模型.SEH实际包含两个主要功能:结束处理(termin ...
- OD: Memory Attach Technology - Exception
看到第六章了:形形色色的内存攻击技术 异常处理结构体 S.E.H Structure Exception Handler S.E.H 是 Windows 处理异常的重要数据结构.每个 S.E.H 为 ...
随机推荐
- 牛客CSP-S提高组赛前集训营2 T2沙漠点列
原题链接 算法不难,比赛的时候就和cyc大佬一起yy了正解,不过因为交的时候比较急(要回寝室惹),我有两数组开错大小直接爆到50,cyc大佬则只把文件输入关了一半,直接爆零(╯ ̄Д ̄)╯┻━┻ 要尽量 ...
- FORM表单 onclick()与onsubmit()
FORM表单中onclick().submit()与onsubmit()的问题 最近遇到一次处理form数据的过滤,采用了button的onclick事件来检查,发现return false后表单仍然 ...
- 没有15k薪资都不会了解的测试内幕
软件测试的工程师阶层是指随着行业的飞速发展,测试人员犹如身在洪流之中“逆水行舟不进则退”.知其然已经无法满足当今的测试人员,还要知其所以然.所以测试人员不仅仅要关注系统外部结构,还得了解系统内部的逻辑 ...
- Angular使用操作事件指令ng-click传多个参数示例
本文实例讲述了Angular使用操作事件指令ng-click传多个参数功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html ng-app="m ...
- 深入了解Cookie和Session
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...
- 常用的User-Agent
window.navigator.userAgent 1) ChromeWin7:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTM ...
- C语言判断字符串是否是 hex string的代码
把写内容过程中经常用到的一些内容段备份一下,如下内容内容是关于C语言判断字符串是否是 hex string的内容. { static unsigned int hex2bin[256]={0}; me ...
- python基础-模块(全是理论,没有代码)
模块 概念:一系列功能的结合体.相当于模块包着一堆函数与代码.本质上是py文件. 来源: python内置的模块----→ python解释器的模块 第三方的模块 -----→ 其他人编写提供的 自定 ...
- E2E测试工具之--01 Cypress 上手使用
The web has evolved. Finally, testing has too. 1. 简介 cypress 最近很火的e2e(即end to end(端到端))测试框架,它基于node ...
- selenium 定位元素方法
1.通过id定位元素 写法1: element = driver.find_element_by_id("kw") 写法2: from selenium.webdriver.com ...