Thread Environment Block
Thread Environment Block
TEB는 스레드에 대한 정보를 포함하고 있는 구조체입니다.
프로세스 가상 메모리 영역에 존재하며, NtCurrentTEB 함수를 통해 획득할 수 있습니다.
함수 내부에서는 Segment Register를 통해 TEB 주소를 획득합니다.
1
2
3
4
// x86 architecture
ntdll!NtdllNtCurrentTeb:
77de9fe0 64a118000000 mov eax,dword ptr fs:[00000018h]
77de9fe6 c3 ret
x64 아키텍처에서는 NtCurrentTEB 함수 자체는 지원하나, 인라인 함수로 대체되었습니다.
1
2
3
4
__forceinline struct _TEB* NtCurrentTeb (VOID)
{
return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self));
}
마찬가지로 함수 내부에서는 세그먼트 레지스터를 통해 주소를 가져옵니다.
1
2
// x64 architecture
00007FF62BDD225B mov rax,qword ptr gs:[30h]
Windbg !teb 명령을 통해서도 확인이 가능하며, 파라미터로 주소가 전달되지 않으면 현재 스레드에 대한 TEB 정보가 조회됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:000> !teb
TEB at 003f9000
ExceptionList: 0019f810
StackBase: 001a0000
StackLimit: 0019d000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 003f9000
EnvironmentPointer: 00000000
ClientId: 00003844 . 00004dd8
RpcHandle: 00000000
Tls Storage: 00724068
PEB Address: 003f6000
LastErrorValue: 0
LastStatusValue: c0000034
Count Owned Locks: 0
HardErrorMode: 0
dt_TEB
Windbg를 통해 확인한 TEB 구조체는 다음과 같습니다.
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
0:000> dt_teb
ntdll!_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 ReservedForDebuggerInstrumentation : [16] Ptr32 Void
+0x10c SystemReserved1 : [26] Ptr32 Void
+0x174 PlaceholderCompatibilityMode : Char
+0x175 PlaceholderHydrationAlwaysExplicit : UChar
+0x176 PlaceholderReserved : [10] Char
+0x180 ProxiedProcessId : Uint4B
+0x184 _ActivationStack : _ACTIVATION_CONTEXT_STACK
+0x19c WorkingOnBehalfTicket : [8] UChar
+0x1a4 ExceptionCode : Int4B
+0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK
+0x1ac InstrumentationCallbackSp : Uint4B
+0x1b0 InstrumentationCallbackPreviousPc : Uint4B
+0x1b4 InstrumentationCallbackPreviousSp : Uint4B
+0x1b8 InstrumentationCallbackDisabled : UChar
+0x1b9 SpareBytes : [23] 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 PerflibData : 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 ReservedForCodeCoverage : 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 HeapData : 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 SessionAware : Pos 11, 1 Bit
+0xfca LoadOwner : Pos 12, 1 Bit
+0xfca LoaderWorker : Pos 13, 1 Bit
+0xfca SkipLoaderInit : Pos 14, 1 Bit
+0xfca SkipFileAPIBrokering : Pos 15, 1 Bit
+0xfcc TxnScopeEnterCallback : Ptr32 Void
+0xfd0 TxnScopeExitCallback : Ptr32 Void
+0xfd4 TxnScopeContext : Ptr32 Void
+0xfd8 LockCount : Uint4B
+0xfdc WowTebOffset : Int4B
+0xfe0 ResourceRetValue : Ptr32 Void
+0xfe4 ReservedForWdf : Ptr32 Void
+0xfe8 ReservedForCrt : Uint8B
+0xff0 EffectiveContainerId : _GUID
+0x1000 LastSleepCounter : Uint8B
+0x1008 SpinCallCount : Uint4B
+0x1010 ExtendedFeatureDisableMask : Uint8B
NtTib
ExceptionList
SEH에 대한 엔트리 주소입니다. try~catch와 같은 예외처리를 사용한 경우, 세그먼트 레지스터를 통해 SEH 최상단에 등록됩니다.
해당 핸들러는 안티 디버깅에도 활용될 수 있습니다.
1
2
3
4
5
6
7
8
9
10
0:000> dx -r1 (*((ntdll!_NT_TIB *)0x2cc000))
(*((ntdll!_NT_TIB *)0x2cc000)) [Type: _NT_TIB]
[+0x000] ExceptionList : 0x57f4b8 [Type: _EXCEPTION_REGISTRATION_RECORD *]
[+0x004] StackBase : 0x580000 [Type: void *]
[+0x008] StackLimit : 0x57d000 [Type: void *]
[+0x00c] SubSystemTib : 0x0 [Type: void *]
[+0x010] FiberData : 0x1e00 [Type: void *]
[+0x010] Version : 0x1e00 [Type: unsigned long]
[+0x014] ArbitraryUserPointer : 0x0 [Type: void *]
[+0x018] Self : 0x2cc000 [Type: _NT_TIB *]
StackBase
해당 스레드에서 사용되는 스택의 시작 주소입니다. StackLimit에서 해당 값을 빼면 스택 크기를 구할 수 있습니다.
1
2
0:000> ?? int(@$teb->NtTib.StackBase) - int(@$teb->NtTib.StackLimit)
int 0n1044480
ThreadLocalStoragePointer
TLS에 대한 포인터입니다. 스레드 생성 시, 호출되는 콜백 함수는 안티 디버깅에 활용될 수 있습니다.
ProcessEnvironmentBlock
현재 프로세스의 PEB 주소를 나타냅니다.
DbgSsReserved
해당 값은 DebugActiveProcess 내부에서 참조됩니다.
1
2
3
4
5
6
7
0:013> u DebugActiveProcess
KERNELBASE!DebugActiveProcess:
00007ffc`7aa93b10 48895c2408 mov qword ptr [rsp+8],rbx
00007ffc`7aa93b15 57 push rdi
00007ffc`7aa93b16 4883ec20 sub rsp,20h
00007ffc`7aa93b1a 8bd9 mov ebx,ecx
00007ffc`7aa93b1c 48ff1595cd1000 call qword ptr [KERNELBASE!_imp_DbgUiConnectToDbg (00007ffc`7aba08b8)]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0:013> uf ntdll!DbgUiConnectToDbg
ntdll!DbgUiConnectToDbg:
00007ffc`7d246e40 4883ec58 sub rsp,58h
00007ffc`7d246e44 65488b042530000000 mov rax,qword ptr gs:[30h]
00007ffc`7d246e4d 33c9 xor ecx,ecx
00007ffc`7d246e4f 483988a8160000 cmp qword ptr [rax+16A8h],rcx
00007ffc`7d246e56 7546 jne ntdll!DbgUiConnectToDbg+0x5e (00007ffc`7d246e9e) Branch
ntdll!DbgUiConnectToDbg+0x18:
00007ffc`7d246e58 48894c2428 mov qword ptr [rsp+28h],rcx
00007ffc`7d246e5d 4c8d442420 lea r8,[rsp+20h]
00007ffc`7d246e62 894c2438 mov dword ptr [rsp+38h],ecx
00007ffc`7d246e66 0f57c0 xorps xmm0,xmm0
00007ffc`7d246e69 48894c2430 mov qword ptr [rsp+30h],rcx
00007ffc`7d246e6e 41b901000000 mov r9d,1
00007ffc`7d246e74 f30f7f442440 movdqu xmmword ptr [rsp+40h],xmm0
00007ffc`7d246e7a c744242030000000 mov dword ptr [rsp+20h],30h
00007ffc`7d246e82 ba0f001f00 mov edx,1F000Fh
00007ffc`7d246e87 65488b0c2530000000 mov rcx,qword ptr gs:[30h]
00007ffc`7d246e90 4881c1a8160000 add rcx,16A8h
00007ffc`7d246e97 e834a8fcff call ntdll!NtCreateDebugObject (00007ffc`7d2116d0)
다른 프로세스를 디버깅 중인 경우, DbgSsReserved 값은 0이 아닙니다. (디버거에 해당됨)
크기가 2인 배열이며 DbgSsReserved[1]에는 DebugObject 핸들이 존재합니다.
1
2
0:013> dt 0x0000000000228000 ntdll!_TEB
+0x16a0 DbgSsReserved : [2] 0x00000000`0800bfc0 Void
1
2
3
4
0:013> dx -r1 (*((ntdll!void * (*)[2])0x2296a0))
(*((ntdll!void * (*)[2])0x2296a0)) [Type: void * [2]]
[0] : 0x800bfc0 [Type: void *]
[1] : 0x770 [Type: void *]
References
This post is licensed under CC BY 4.0 by the author.