线程切换小结

Windows线程切换

本来是想直接研究Win10 X64的内核,但是资料还是XP的最多,所以还是以Xp的为基础吧,毕竟win10仍然是NT架构

Vmware高版本(16)对XP的支持已经不行了(装不上VmwareTools),同时微软关闭了Xp的符号下载,windbg也没办法带符号调试,搭环境实在过于不理想,所以这里仅是对一些大佬的书面资料梳理一下

ntoskrnl.exe

ntoskrnl是windows的核心内核文件,在这里可以下载到所有Windows版本的内核文件

Download Ntoskrnl.exe and Fix Runtime Errors (exefiles.com)

image-20220212100020593

线程切换

image-20220212110803080

线程发生切换一般有两种情况:主动切换和被动切换,主动切换是调调用一些系统API时,里面调用的KiSwapThread导致的切换,被动切换发生于线程时间片用完,或者被抢占的时候,但是两种路径最后都会调用SwapContext来完成线程切换

会用相当多的系统调用调用到KiSwapThread,所以线程切换还是很频繁的

从KiSwapThread开始分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.text:004050BF ; _DWORD __cdecl KiSwapThread()
.text:004050BF @KiSwapThread@0 proc near
.text:004050BF
.text:004050BF ; FUNCTION CHUNK AT .text:0040EA85 SIZE 00000015 BYTES
.text:004050BF ; FUNCTION CHUNK AT .text:004109AF SIZE 00000009 BYTES
.text:004050BF
.text:004050BF mov edi, edi
.text:004050C1 push esi
.text:004050C2 push edi
.text:004050C3 db 3Eh ; KPRCB给eax
.text:004050C3 mov eax, ds:0FFDFF020h
.text:004050C9 mov esi, eax
.text:004050CB mov eax, [esi+_KPRCB.NextThread]
.text:004050CE test eax, eax
.text:004050D0 mov edi, [esi+_KPRCB.CurrentThread]
.text:004050D3 jnz loc_4109AF ; 判断是否有下一个线程

如果有下一个函数,就直接调用把NextThread作为参数,调用KiSwapContext进行切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.text:004109AF ; START OF FUNCTION CHUNK FOR KiSwapThread()
.text:004109AF
.text:004109AF loc_4109AF:
.text:004109AF and [esi+_KPRCB.NextThread], 0
.text:004109B3 jmp loc_4050F0
.text:004109B3 ; END OF FUNCTION CHUNK FOR KiSwapThread()


.text:004050F0 loc_4050F0:
.text:004050F0 mov ecx, eax
.text:004050F2 call @KiSwapContext@4 ; KiSwapContext(x)
.text:004050F7 test al, al
.text:004050F9 mov cl, [edi+58h] ; NewIrql
.text:004050FC mov edi, [edi+54h]
.text:004050FF mov esi, ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x)
.text:00405105 jnz loc_415ADB

如果没有NextThread,就调用KiFindReadyThread寻找要切换的线程

1
2
3
4
5
6
7
.text:004050D9 push    ebx
.text:004050DA movsx ebx, [esi+_KPRCB.Number]
.text:004050DE xor edx, edx
.text:004050E0 mov ecx, ebx
.text:004050E2 call @KiFindReadyThread@8 ; KiFindReadyThread(x,x)
.text:004050E7 test eax, eax
.text:004050E9 jz loc_40EA85

还找不到线程就是用IdleThread

1
2
3
4
5
6
7
8
9
10
11
.text:0040EA85 ; START OF FUNCTION CHUNK FOR KiSwapThread()
.text:0040EA85
.text:0040EA85 loc_40EA85:
.text:0040EA85 mov eax, [esi+_KPRCB.IdleThread]
.text:0040EA88 xor edx, edx
.text:0040EA8A inc edx
.text:0040EA8B mov ecx, ebx
.text:0040EA8D shl edx, cl
.text:0040EA8F or ds:_KiIdleSummary, edx
.text:0040EA95 jmp loc_4050EF
.text:0040EA95 ; END OF FUNCTION CHUNK FOR KiSwapThread()

最终都是到004050F0调用KiSwapContext进一步操作,KiSwapContext就是调用SwapContext

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
.text:00404828 ; __fastcall KiSwapContext(x)
.text:00404828 @KiSwapContext@4 proc near
.text:00404828
.text:00404828 var_10= dword ptr -10h
.text:00404828 var_C= dword ptr -0Ch
.text:00404828 var_8= dword ptr -8
.text:00404828 var_4= dword ptr -4
.text:00404828
.text:00404828 sub esp, 10h
.text:0040482B mov [esp+10h+var_4], ebx
.text:0040482F mov [esp+10h+var_8], esi
.text:00404833 mov [esp+10h+var_C], edi
.text:00404837 mov [esp+10h+var_10], ebp
.text:0040483A mov ebx, ds:0FFDFF01Ch
.text:00404840 mov esi, ecx
.text:00404842 mov edi, [ebx+_KPCR.PrcbData.CurrentThread]
.text:00404848 mov [ebx+_KPCR.PrcbData.CurrentThread], esi
.text:0040484E mov cl, [edi+_ETHREAD.Tcb.WaitIrql]
.text:00404851 call SwapContext
.text:00404856 mov ebp, [esp+10h+var_10]
.text:00404859 mov edi, [esp+10h+var_C]
.text:0040485D mov esi, [esp+10h+var_8]
.text:00404861 mov ebx, [esp+10h+var_4]
.text:00404865 add esp, 10h
.text:00404868 retn

分析SwapContext,首先修改要切换到的线程的状态为Running

1
2
3
4
.text:00404924 SwapContext proc near
.text:00404924 or cl, cl
.text:00404926 mov es:[esi+_ETHREAD.Tcb.State], 2 ; 修改线程状态为Running
.text:0040492B pushf

保存下异常链表

1
2
3
4
5
6
.text:0040492C
.text:0040492C loc_40492C:
.text:0040492C mov ecx, [ebx+_KPCR.NtTib.ExceptionList]
.text:0040492E cmp [ebx+_KPCR.PrcbData.DpcRoutineActive], 0
.text:00404935 push ecx ; 保存异常链表
.text:00404936 jnz loc_404A70

最重要的保存当前线程的esp到KernelStack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.text:00404949
.text:00404949 loc_404949:
.text:00404949 mov ebp, cr0
.text:0040494C mov edx, ebp ; edx赋值为CR0
.text:0040494E mov cl, [esi+_ETHREAD.Tcb.DebugActive]
.text:00404951 mov [ebx+_KPCR.DebugActive], cl
.text:00404954 cli
.text:00404955 mov [edi+_KTHREAD.KernelStack], esp ; 保存当前的esp到KernelStack
.text:00404958 mov eax, [esi+_ETHREAD.Tcb.InitialStack]
.text:0040495B mov ecx, [esi+_ETHREAD.Tcb.StackLimit]
.text:0040495E sub eax, 210h ; stack_base 减到trapframe
.text:00404963 mov [ebx+_KPCR.NtTib.StackLimit], ecx
.text:00404966 mov [ebx+_KPCR.NtTib.StackBase], eax
.text:00404969 xor ecx, ecx
.text:0040496B mov cl, [esi+_KTHREAD.NpxState]
.text:0040496E and edx, 0FFFFFFF1h
.text:00404971 or ecx, edx
.text:00404973 or ecx, [eax+20Ch]
.text:00404979 cmp ebp, ecx
.text:0040497B jnz loc_404A3F

把esp恢复成新线程的堆栈

1
2
3
4
5
6
7
8
9
10
11
.text:0040498F loc_40498F:
.text:0040498F mov ecx, [ebx+_KPCR.TSS]
.text:00404992 mov [ecx+4], eax ; 将eax赋值给TSS里的esp0
.text:00404995 mov esp, [esi+_KTHREAD.KernelStack] ; 恢复到新线程的堆栈
.text:00404998 mov eax, [esi+_KTHREAD.Teb]
.text:0040499B mov [ebx+_KPCR.NtTib.Self], eax
.text:0040499E sti
.text:0040499F mov eax, [edi+_KTHREAD.ApcState.Process]
.text:004049A2 cmp eax, [esi+_KTHREAD.ApcState.Process] ; 判断要切换到的线程和当前线程是否是在同一个进程
.text:004049A5 mov [edi+_KTHREAD.IdleSwapBlock], 0
.text:004049A9 jz short loc_4049D7 ; KPCR的地址赋值给eax

把gs寄存器清零,确保fs:[0]指向KPCR

1
2
3
4
5
6
7
8
9
10
11
12
.text:004049B8 loc_4049B8:
.text:004049B8 lldt ax
.text:004049BB xor eax, eax
.text:004049BD mov gs, eax ; gs寄存器清零
.text:004049BF assume gs:GAP
.text:004049BF mov eax, [edi+_KPROCESS.DirectoryTableBase]
.text:004049C2 mov ebp, [ebx+40h]
.text:004049C5 mov ecx, [edi+30h]
.text:004049C8 mov [ebp+1Ch], eax
.text:004049CB mov cr3, eax ; 把目标进程的页目录换到CR3上
.text:004049CE mov [ebp+66h], cx
.text:004049D2 jmp short loc_4049D7 ; KPCR的地址赋值给eax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text:004049D7
.text:004049D7 loc_4049D7: ; KPCR的地址赋值给eax
.text:004049D7 mov eax, [ebx+_KPCR.NtTib.Self]
.text:004049DA mov ecx, [ebx+_KPCR.GDT]
.text:004049DD mov [ecx+3Ah], ax ; 修改GDT中的段描述符,确保fs:{0}指向正确的KPCR地址
.text:004049E1 shr eax, 10h
.text:004049E4 mov [ecx+3Ch], al
.text:004049E7 mov [ecx+3Fh], ah
.text:004049EA inc [esi+_ETHREAD.Tcb.ContextSwitches] ; 增加线程的切换次数计数
.text:004049ED inc [ebx+_KPCR.PrcbData.KeContextSwitches]
.text:004049F3 pop ecx
.text:004049F4 mov [ebx], ecx
.text:004049F6 cmp byte ptr [esi+49h], 0
.text:004049FA jnz short loc_404A00

总结:

  • 线程的切换本质上就是堆栈的切换
  • 在切换线程时会清空GS寄存器
  • 本质上不会进行进程切换,只不过如果切换的线程不在同一个进程,就顺带切换CR3

被动切换 时钟中断

触发流程,时钟中断注册的中断处理函数是HalpHpetClockInterrupt,其最终会调用到KiDispatchInterrupt来实施SwapContext的调用

1
2
3
4
5
6
7
8
9
hal!HalpHpetClockInterrupt
->nt!KeUpdateSystemTime
->nt!KeUpdateRunTime
->hal!HalRequestSoftwareInterrupt
->hal!KfLowerIrql
->hal!HalpCheckForSoftwareInterrupt
->hal!HalpDispatchSoftwareInterrupt
->nt!KiDispatchInterrupt
->SwapContext

KeUpdateRunTime,把线程的Quantum-3,如果小于0了,且当前线程不是IdleThread(IdleThread当然随便运行),就给QuantumEnd赋值一个非0值标记时间片已经用完了

image-20220213115329705

KiDispatchInterrupt和其派发中断的名称不是很相符(派发中断),这个函数首先就会判断时间片有没有用完

1
2
3
4
5
.text:004048A2
.text:004048A2 loc_4048A2:
.text:004048A2 sti
.text:004048A3 cmp [ebx+_KPCR.PrcbData.QuantumEnd], 0 ; 判断时间片有没有用完
.text:004048AA jnz short loc_404902 ; 线程时间片用完

如果时间片已经用完,重新分配时间片

1
2
3
4
5
6
.text:00404902
.text:00404902 loc_404902: ; 线程时间片用完
.text:00404902 mov [ebx+_KPCR.PrcbData.QuantumEnd], 0
.text:0040490C call _KiQuantumEnd@0 ; 重新分配时间片
.text:00404911 or eax, eax
.text:00404913 jnz short loc_4048BB

然后下面会切换线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.text:004048B5 mov     eax, [ebx+_KPCR.PrcbData.NextThread] ; 有下一个线程,就将其赋值给eax


.text:004048BB loc_4048BB:
.text:004048BB sub esp, 0Ch
.text:004048BE mov [esp+0Ch+var_4], esi
.text:004048C2 mov [esp+0Ch+var_8], edi
.text:004048C6 mov [esp+0Ch+var_C], ebp
.text:004048C9 mov esi, eax
.text:004048CB mov edi, [ebx+_KPCR.PrcbData.CurrentThread]
.text:004048D1 mov [ebx+_KPCR.PrcbData.NextThread], 0
.text:004048DB mov [ebx+124h], esi
.text:004048E1 mov ecx, edi ; 当前线程传给ecx
.text:004048E3 mov byte ptr [edi+50h], 1
.text:004048E7 call @KiReadyThread@4 ; ecx传参,插入到就绪链表里
.text:004048EC mov cl, 1
.text:004048EE call SwapContext ; 切换到NextThread
.text:004048F3 mov ebp, [esp+0Ch+var_C]
.text:004048F6 mov edi, [esp+0Ch+var_8]
.text:004048FA mov esi, [esp+0Ch+var_4]
.text:004048FE add esp, 0Ch

常用结构体

KPCR

KPCR是描述CPU信息的结构体,一个CPU有自己的一个KPCR

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
//0x3748 bytes (sizeof)
struct _KPCR
{
union
{
struct _NT_TIB NtTib; //0x0
struct
{
struct _EXCEPTION_REGISTRATION_RECORD* Used_ExceptionList; //0x0
VOID* Used_StackBase; //0x4
VOID* Spare2; //0x8
VOID* TssCopy; //0xc
ULONG ContextSwitches; //0x10
ULONG SetMemberCopy; //0x14
VOID* Used_Self; //0x18
};
};
struct _KPCR* SelfPcr; //0x1c
struct _KPRCB* Prcb; //0x20
UCHAR Irql; //0x24
ULONG IRR; //0x28
ULONG IrrActive; //0x2c
ULONG IDR; //0x30
VOID* KdVersionBlock; //0x34
struct _KIDTENTRY* IDT; //0x38
struct _KGDTENTRY* GDT; //0x3c
struct _KTSS* TSS; //0x40
USHORT MajorVersion; //0x44
USHORT MinorVersion; //0x46
ULONG SetMember; //0x48
ULONG StallScaleFactor; //0x4c
UCHAR SpareUnused; //0x50
UCHAR Number; //0x51
UCHAR Spare0; //0x52
UCHAR SecondLevelCacheAssociativity; //0x53
ULONG VdmAlert; //0x54
ULONG KernelReserved[14]; //0x58
ULONG SecondLevelCacheSize; //0x90
ULONG HalReserved[16]; //0x94
ULONG InterruptMode; //0xd4
UCHAR Spare1; //0xd8
ULONG KernelReserved2[17]; //0xdc
struct _KPRCB PrcbData; //0x120
};

SelfPcr; //0x1c 指向自身的指针

Prcb; //0x20 指向KPRCB的指针

IDT TSS GDT 是这个CPU的三个表

KPRCB

KPRCB是紧跟在KPCR后面的,作为拓展结构体

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
//0x3628 bytes (sizeof)
struct _KPRCB
{
USHORT MinorVersion; //0x0
USHORT MajorVersion; //0x2
struct _KTHREAD* CurrentThread; //0x4
struct _KTHREAD* NextThread; //0x8
struct _KTHREAD* IdleThread; //0xc
UCHAR LegacyNumber; //0x10
UCHAR NestingLevel; //0x11
USHORT BuildType; //0x12
CHAR CpuType; //0x14
CHAR CpuID; //0x15
union
{
USHORT CpuStep; //0x16
struct
{
UCHAR CpuStepping; //0x16
UCHAR CpuModel; //0x17
};
};
struct _KPROCESSOR_STATE ProcessorState; //0x18
ULONG KernelReserved[16]; //0x338
ULONG HalReserved[16]; //0x378
ULONG CFlushSize; //0x3b8
UCHAR CoresPerPhysicalProcessor; //0x3bc
UCHAR LogicalProcessorsPerCore; //0x3bd
UCHAR PrcbPad0[2]; //0x3be
ULONG MHz; //0x3c0
UCHAR CpuVendor; //0x3c4
UCHAR GroupIndex; //0x3c5
USHORT Group; //0x3c6
ULONG GroupSetMember; //0x3c8
ULONG Number; //0x3cc
UCHAR PrcbPad1[72]; //0x3d0
struct _KSPIN_LOCK_QUEUE LockQueue[17]; //0x418
struct _KTHREAD* NpxThread; //0x4a0
ULONG InterruptCount; //0x4a4
ULONG KernelTime; //0x4a8
ULONG UserTime; //0x4ac
ULONG DpcTime; //0x4b0
ULONG DpcTimeCount; //0x4b4
ULONG InterruptTime; //0x4b8
ULONG AdjustDpcThreshold; //0x4bc
ULONG PageColor; //0x4c0
UCHAR DebuggerSavedIRQL; //0x4c4
UCHAR NodeColor; //0x4c5
UCHAR PrcbPad20[2]; //0x4c6
ULONG NodeShiftedColor; //0x4c8
struct _KNODE* ParentNode; //0x4cc
ULONG SecondaryColorMask; //0x4d0
ULONG DpcTimeLimit; //0x4d4
ULONG PrcbPad21[2]; //0x4d8
ULONG CcFastReadNoWait; //0x4e0
ULONG CcFastReadWait; //0x4e4
ULONG CcFastReadNotPossible; //0x4e8
ULONG CcCopyReadNoWait; //0x4ec
ULONG CcCopyReadWait; //0x4f0
ULONG CcCopyReadNoWaitMiss; //0x4f4
volatile LONG MmSpinLockOrdering; //0x4f8
volatile LONG IoReadOperationCount; //0x4fc
volatile LONG IoWriteOperationCount; //0x500
volatile LONG IoOtherOperationCount; //0x504
union _LARGE_INTEGER IoReadTransferCount; //0x508
union _LARGE_INTEGER IoWriteTransferCount; //0x510
union _LARGE_INTEGER IoOtherTransferCount; //0x518
ULONG CcFastMdlReadNoWait; //0x520
ULONG CcFastMdlReadWait; //0x524
ULONG CcFastMdlReadNotPossible; //0x528
ULONG CcMapDataNoWait; //0x52c
ULONG CcMapDataWait; //0x530
ULONG CcPinMappedDataCount; //0x534
ULONG CcPinReadNoWait; //0x538
ULONG CcPinReadWait; //0x53c
ULONG CcMdlReadNoWait; //0x540
ULONG CcMdlReadWait; //0x544
ULONG CcLazyWriteHotSpots; //0x548
ULONG CcLazyWriteIos; //0x54c
ULONG CcLazyWritePages; //0x550
ULONG CcDataFlushes; //0x554
ULONG CcDataPages; //0x558
ULONG CcLostDelayedWrites; //0x55c
ULONG CcFastReadResourceMiss; //0x560
ULONG CcCopyReadWaitMiss; //0x564
ULONG CcFastMdlReadResourceMiss; //0x568
ULONG CcMapDataNoWaitMiss; //0x56c
ULONG CcMapDataWaitMiss; //0x570
ULONG CcPinReadNoWaitMiss; //0x574
ULONG CcPinReadWaitMiss; //0x578
ULONG CcMdlReadNoWaitMiss; //0x57c
ULONG CcMdlReadWaitMiss; //0x580
ULONG CcReadAheadIos; //0x584
ULONG KeAlignmentFixupCount; //0x588
ULONG KeExceptionDispatchCount; //0x58c
ULONG KeSystemCalls; //0x590
ULONG AvailableTime; //0x594
ULONG PrcbPad22[2]; //0x598
struct _PP_LOOKASIDE_LIST PPLookasideList[16]; //0x5a0
struct _GENERAL_LOOKASIDE_POOL PPNPagedLookasideList[32]; //0x620
struct _GENERAL_LOOKASIDE_POOL PPPagedLookasideList[32]; //0xf20
volatile ULONG PacketBarrier; //0x1820
volatile LONG ReverseStall; //0x1824
VOID* IpiFrame; //0x1828
UCHAR PrcbPad3[52]; //0x182c
VOID* volatile CurrentPacket[3]; //0x1860
volatile ULONG TargetSet; //0x186c
VOID (* volatileWorkerRoutine)(VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4); //0x1870
volatile ULONG IpiFrozen; //0x1874
UCHAR PrcbPad4[40]; //0x1878
volatile ULONG RequestSummary; //0x18a0
struct _KPRCB* volatile SignalDone; //0x18a4
UCHAR PrcbPad50[56]; //0x18a8
struct _KDPC_DATA DpcData[2]; //0x18e0
VOID* DpcStack; //0x1908
LONG MaximumDpcQueueDepth; //0x190c
ULONG DpcRequestRate; //0x1910
ULONG MinimumDpcRate; //0x1914
ULONG DpcLastCount; //0x1918
ULONG PrcbLock; //0x191c
struct _KGATE DpcGate; //0x1920
UCHAR ThreadDpcEnable; //0x1930
volatile UCHAR QuantumEnd; //0x1931
volatile UCHAR DpcRoutineActive; //0x1932
volatile UCHAR IdleSchedule; //0x1933
union
{
volatile LONG DpcRequestSummary; //0x1934
SHORT DpcRequestSlot[2]; //0x1934
struct
{
SHORT NormalDpcState; //0x1934
union
{
volatile USHORT DpcThreadActive:1; //0x1936
SHORT ThreadDpcState; //0x1936
};
};
};
volatile ULONG TimerHand; //0x1938
ULONG LastTick; //0x193c
LONG MasterOffset; //0x1940
ULONG PrcbPad41[2]; //0x1944
ULONG PeriodicCount; //0x194c
ULONG PeriodicBias; //0x1950
ULONGLONG TickOffset; //0x1958
struct _KTIMER_TABLE TimerTable; //0x1960
struct _KDPC CallDpc; //0x31a0
LONG ClockKeepAlive; //0x31c0
UCHAR ClockCheckSlot; //0x31c4
UCHAR ClockPollCycle; //0x31c5
UCHAR PrcbPad6[2]; //0x31c6
LONG DpcWatchdogPeriod; //0x31c8
LONG DpcWatchdogCount; //0x31cc
LONG ThreadWatchdogPeriod; //0x31d0
LONG ThreadWatchdogCount; //0x31d4
volatile LONG KeSpinLockOrdering; //0x31d8
ULONG PrcbPad70[1]; //0x31dc
struct _LIST_ENTRY WaitListHead; //0x31e0
ULONG WaitLock; //0x31e8
ULONG ReadySummary; //0x31ec
ULONG QueueIndex; //0x31f0
struct _SINGLE_LIST_ENTRY DeferredReadyListHead; //0x31f4
ULONGLONG StartCycles; //0x31f8
volatile ULONGLONG CycleTime; //0x3200
volatile ULONG HighCycleTime; //0x3208
ULONG PrcbPad71; //0x320c
ULONGLONG PrcbPad72[2]; //0x3210
struct _LIST_ENTRY DispatcherReadyListHead[32]; //0x3220
VOID* ChainedInterruptList; //0x3320
LONG LookasideIrpFloat; //0x3324
volatile LONG MmPageFaultCount; //0x3328
volatile LONG MmCopyOnWriteCount; //0x332c
volatile LONG MmTransitionCount; //0x3330
volatile LONG MmCacheTransitionCount; //0x3334
volatile LONG MmDemandZeroCount; //0x3338
volatile LONG MmPageReadCount; //0x333c
volatile LONG MmPageReadIoCount; //0x3340
volatile LONG MmCacheReadCount; //0x3344
volatile LONG MmCacheIoCount; //0x3348
volatile LONG MmDirtyPagesWriteCount; //0x334c
volatile LONG MmDirtyWriteIoCount; //0x3350
volatile LONG MmMappedPagesWriteCount; //0x3354
volatile LONG MmMappedWriteIoCount; //0x3358
volatile ULONG CachedCommit; //0x335c
volatile ULONG CachedResidentAvailable; //0x3360
VOID* HyperPte; //0x3364
UCHAR PrcbPad8[4]; //0x3368
UCHAR VendorString[13]; //0x336c
UCHAR InitialApicId; //0x3379
UCHAR LogicalProcessorsPerPhysicalProcessor; //0x337a
UCHAR PrcbPad9[5]; //0x337b
ULONG FeatureBits; //0x3380
union _LARGE_INTEGER UpdateSignature; //0x3388
volatile ULONGLONG IsrTime; //0x3390
ULONGLONG RuntimeAccumulation; //0x3398
struct _PROCESSOR_POWER_STATE PowerState; //0x33a0
struct _KDPC DpcWatchdogDpc; //0x3468
struct _KTIMER DpcWatchdogTimer; //0x3488
VOID* WheaInfo; //0x34b0
VOID* EtwSupport; //0x34b4
union _SLIST_HEADER InterruptObjectPool; //0x34b8
union _SLIST_HEADER HypercallPageList; //0x34c0
VOID* HypercallPageVirtual; //0x34c8
VOID* VirtualApicAssist; //0x34cc
ULONGLONG* StatisticsPage; //0x34d0
VOID* RateControl; //0x34d4
struct _CACHE_DESCRIPTOR Cache[5]; //0x34d8
ULONG CacheCount; //0x3514
ULONG CacheProcessorMask[5]; //0x3518
struct _KAFFINITY_EX PackageProcessorSet; //0x352c
ULONG PrcbPad91[1]; //0x3538
ULONG CoreProcessorSet; //0x353c
struct _KDPC TimerExpirationDpc; //0x3540
ULONG SpinLockAcquireCount; //0x3560
ULONG SpinLockContentionCount; //0x3564
ULONG SpinLockSpinCount; //0x3568
ULONG IpiSendRequestBroadcastCount; //0x356c
ULONG IpiSendRequestRoutineCount; //0x3570
ULONG IpiSendSoftwareInterruptCount; //0x3574
ULONG ExInitializeResourceCount; //0x3578
ULONG ExReInitializeResourceCount; //0x357c
ULONG ExDeleteResourceCount; //0x3580
ULONG ExecutiveResourceAcquiresCount; //0x3584
ULONG ExecutiveResourceContentionsCount; //0x3588
ULONG ExecutiveResourceReleaseExclusiveCount; //0x358c
ULONG ExecutiveResourceReleaseSharedCount; //0x3590
ULONG ExecutiveResourceConvertsCount; //0x3594
ULONG ExAcqResExclusiveAttempts; //0x3598
ULONG ExAcqResExclusiveAcquiresExclusive; //0x359c
ULONG ExAcqResExclusiveAcquiresExclusiveRecursive; //0x35a0
ULONG ExAcqResExclusiveWaits; //0x35a4
ULONG ExAcqResExclusiveNotAcquires; //0x35a8
ULONG ExAcqResSharedAttempts; //0x35ac
ULONG ExAcqResSharedAcquiresExclusive; //0x35b0
ULONG ExAcqResSharedAcquiresShared; //0x35b4
ULONG ExAcqResSharedAcquiresSharedRecursive; //0x35b8
ULONG ExAcqResSharedWaits; //0x35bc
ULONG ExAcqResSharedNotAcquires; //0x35c0
ULONG ExAcqResSharedStarveExclusiveAttempts; //0x35c4
ULONG ExAcqResSharedStarveExclusiveAcquiresExclusive; //0x35c8
ULONG ExAcqResSharedStarveExclusiveAcquiresShared; //0x35cc
ULONG ExAcqResSharedStarveExclusiveAcquiresSharedRecursive; //0x35d0
ULONG ExAcqResSharedStarveExclusiveWaits; //0x35d4
ULONG ExAcqResSharedStarveExclusiveNotAcquires; //0x35d8
ULONG ExAcqResSharedWaitForExclusiveAttempts; //0x35dc
ULONG ExAcqResSharedWaitForExclusiveAcquiresExclusive; //0x35e0
ULONG ExAcqResSharedWaitForExclusiveAcquiresShared; //0x35e4
ULONG ExAcqResSharedWaitForExclusiveAcquiresSharedRecursive; //0x35e8
ULONG ExAcqResSharedWaitForExclusiveWaits; //0x35ec
ULONG ExAcqResSharedWaitForExclusiveNotAcquires; //0x35f0
ULONG ExSetResOwnerPointerExclusive; //0x35f4
ULONG ExSetResOwnerPointerSharedNew; //0x35f8
ULONG ExSetResOwnerPointerSharedOld; //0x35fc
ULONG ExTryToAcqExclusiveAttempts; //0x3600
ULONG ExTryToAcqExclusiveAcquires; //0x3604
ULONG ExBoostExclusiveOwner; //0x3608
ULONG ExBoostSharedOwners; //0x360c
ULONG ExEtwSynchTrackingNotificationsCount; //0x3610
ULONG ExEtwSynchTrackingNotificationsAccountedCount; //0x3614
struct _CONTEXT* Context; //0x3618
ULONG ContextFlags; //0x361c
struct _XSAVE_AREA* ExtendedState; //0x3620
};

CurrentThread; //0x4 当前线程

NextThread; //0x8 下个线程

IdleThread; //0xc 这个CPU的空闲线程

EPROCESS

进程结构体,进程的本体

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//0x2c0 bytes (sizeof)
struct _EPROCESS
{
struct _KPROCESS Pcb; //0x0
struct _EX_PUSH_LOCK ProcessLock; //0x98
union _LARGE_INTEGER CreateTime; //0xa0
union _LARGE_INTEGER ExitTime; //0xa8
struct _EX_RUNDOWN_REF RundownProtect; //0xb0
VOID* UniqueProcessId; //0xb4
struct _LIST_ENTRY ActiveProcessLinks; //0xb8
ULONG ProcessQuotaUsage[2]; //0xc0
ULONG ProcessQuotaPeak[2]; //0xc8
volatile ULONG CommitCharge; //0xd0
struct _EPROCESS_QUOTA_BLOCK* QuotaBlock; //0xd4
struct _PS_CPU_QUOTA_BLOCK* CpuQuotaBlock; //0xd8
ULONG PeakVirtualSize; //0xdc
ULONG VirtualSize; //0xe0
struct _LIST_ENTRY SessionProcessLinks; //0xe4
VOID* DebugPort; //0xec
union
{
VOID* ExceptionPortData; //0xf0
ULONG ExceptionPortValue; //0xf0
ULONG ExceptionPortState:3; //0xf0
};
struct _HANDLE_TABLE* ObjectTable; //0xf4
struct _EX_FAST_REF Token; //0xf8
ULONG WorkingSetPage; //0xfc
struct _EX_PUSH_LOCK AddressCreationLock; //0x100
struct _ETHREAD* RotateInProgress; //0x104
struct _ETHREAD* ForkInProgress; //0x108
ULONG HardwareTrigger; //0x10c
struct _MM_AVL_TABLE* PhysicalVadRoot; //0x110
VOID* CloneRoot; //0x114
volatile ULONG NumberOfPrivatePages; //0x118
volatile ULONG NumberOfLockedPages; //0x11c
VOID* Win32Process; //0x120
struct _EJOB* volatile Job; //0x124
VOID* SectionObject; //0x128
VOID* SectionBaseAddress; //0x12c
ULONG Cookie; //0x130
ULONG Spare8; //0x134
struct _PAGEFAULT_HISTORY* WorkingSetWatch; //0x138
VOID* Win32WindowStation; //0x13c
VOID* InheritedFromUniqueProcessId; //0x140
VOID* LdtInformation; //0x144
VOID* VdmObjects; //0x148
ULONG ConsoleHostProcess; //0x14c
VOID* DeviceMap; //0x150
VOID* EtwDataSource; //0x154
VOID* FreeTebHint; //0x158
union
{
struct _HARDWARE_PTE PageDirectoryPte; //0x160
ULONGLONG Filler; //0x160
};
VOID* Session; //0x168
UCHAR ImageFileName[15]; //0x16c
UCHAR PriorityClass; //0x17b
struct _LIST_ENTRY JobLinks; //0x17c
VOID* LockedPagesList; //0x184
struct _LIST_ENTRY ThreadListHead; //0x188
VOID* SecurityPort; //0x190
VOID* PaeTop; //0x194
volatile ULONG ActiveThreads; //0x198
ULONG ImagePathHash; //0x19c
ULONG DefaultHardErrorProcessing; //0x1a0
LONG LastThreadExitStatus; //0x1a4
struct _PEB* Peb; //0x1a8
struct _EX_FAST_REF PrefetchTrace; //0x1ac
union _LARGE_INTEGER ReadOperationCount; //0x1b0
union _LARGE_INTEGER WriteOperationCount; //0x1b8
union _LARGE_INTEGER OtherOperationCount; //0x1c0
union _LARGE_INTEGER ReadTransferCount; //0x1c8
union _LARGE_INTEGER WriteTransferCount; //0x1d0
union _LARGE_INTEGER OtherTransferCount; //0x1d8
ULONG CommitChargeLimit; //0x1e0
volatile ULONG CommitChargePeak; //0x1e4
VOID* AweInfo; //0x1e8
struct _SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; //0x1ec
struct _MMSUPPORT Vm; //0x1f0
struct _LIST_ENTRY MmProcessLinks; //0x25c
VOID* HighestUserAddress; //0x264
ULONG ModifiedPageCount; //0x268
union
{
ULONG Flags2; //0x26c
struct
{
ULONG JobNotReallyActive:1; //0x26c
ULONG AccountingFolded:1; //0x26c
ULONG NewProcessReported:1; //0x26c
ULONG ExitProcessReported:1; //0x26c
ULONG ReportCommitChanges:1; //0x26c
ULONG LastReportMemory:1; //0x26c
ULONG ReportPhysicalPageChanges:1; //0x26c
ULONG HandleTableRundown:1; //0x26c
ULONG NeedsHandleRundown:1; //0x26c
ULONG RefTraceEnabled:1; //0x26c
ULONG NumaAware:1; //0x26c
ULONG ProtectedProcess:1; //0x26c
ULONG DefaultPagePriority:3; //0x26c
ULONG PrimaryTokenFrozen:1; //0x26c
ULONG ProcessVerifierTarget:1; //0x26c
ULONG StackRandomizationDisabled:1; //0x26c
ULONG AffinityPermanent:1; //0x26c
ULONG AffinityUpdateEnable:1; //0x26c
ULONG PropagateNode:1; //0x26c
ULONG ExplicitAffinity:1; //0x26c
};
};
union
{
ULONG Flags; //0x270
struct
{
ULONG CreateReported:1; //0x270
ULONG NoDebugInherit:1; //0x270
ULONG ProcessExiting:1; //0x270
ULONG ProcessDelete:1; //0x270
ULONG Wow64SplitPages:1; //0x270
ULONG VmDeleted:1; //0x270
ULONG OutswapEnabled:1; //0x270
ULONG Outswapped:1; //0x270
ULONG ForkFailed:1; //0x270
ULONG Wow64VaSpace4Gb:1; //0x270
ULONG AddressSpaceInitialized:2; //0x270
ULONG SetTimerResolution:1; //0x270
ULONG BreakOnTermination:1; //0x270
ULONG DeprioritizeViews:1; //0x270
ULONG WriteWatch:1; //0x270
ULONG ProcessInSession:1; //0x270
ULONG OverrideAddressSpace:1; //0x270
ULONG HasAddressSpace:1; //0x270
ULONG LaunchPrefetched:1; //0x270
ULONG InjectInpageErrors:1; //0x270
ULONG VmTopDown:1; //0x270
ULONG ImageNotifyDone:1; //0x270
ULONG PdeUpdateNeeded:1; //0x270
ULONG VdmAllowed:1; //0x270
ULONG CrossSessionCreate:1; //0x270
ULONG ProcessInserted:1; //0x270
ULONG DefaultIoPriority:3; //0x270
ULONG ProcessSelfDelete:1; //0x270
ULONG SetTimerResolutionLink:1; //0x270
};
};
LONG ExitStatus; //0x274
struct _MM_AVL_TABLE VadRoot; //0x278
struct _ALPC_PROCESS_CONTEXT AlpcContext; //0x298
struct _LIST_ENTRY TimerResolutionLink; //0x2a8
ULONG RequestedTimerResolution; //0x2b0
ULONG ActiveThreadsHighWatermark; //0x2b4
ULONG SmallestTimerResolution; //0x2b8
struct _PO_DIAG_STACK_RECORD* TimerResolutionStackRecord; //0x2bc
};

struct _KPROCESS Pcb; //0x0 EPROCESS里面嵌入的KPROCESS结构体

UniqueProcessId; //0xb4 进程的PID,

DebugPort; //0xec 调试的关键

ThreadListHead; //0x188 链上了当前进程内的所有线程

ActiveThreads; //0x198 活动线程的总数量

_PEB* Peb; //0x1a8 三环下的PEB

_SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; //0x1ec 当前进程的完整路径

Flags; //0x270 进程的一些属性

  • ProcessExiting:进程退出标志位。置1后表明该进程已退出,但实际还在运行。可以达到反调试的效果。同时进程无法使用任务管理器结束。

  • ProcessDelete:进程退出标志位。置1后表明该进程已退出,但实际还在运行。可以达到反调试的效果。同时进程无法使用任务管理器结束。

    image-20210927153322421

  • BreakOnTermination:该位置1后,任务管理器结束进程时将提示“是否结束系统进程XXX”。结束后windbg将会断下。

    image-20210927152849916

  • VmTopDown:该位置1时,VirtualAlloc一类的申请内存函数将会从大地址开始申请。

  • ProcessInserted:该位置0后,OD附加进程列表找不到该进程。任务管理器结束不掉该进程。CE打不开该进程,无图标。

KPROCESS

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
//0x98 bytes (sizeof)
struct _KPROCESS
{
struct _DISPATCHER_HEADER Header; //0x0
struct _LIST_ENTRY ProfileListHead; //0x10
ULONG DirectoryTableBase; //0x18
struct _KGDTENTRY LdtDescriptor; //0x1c
struct _KIDTENTRY Int21Descriptor; //0x24
struct _LIST_ENTRY ThreadListHead; //0x2c
ULONG ProcessLock; //0x34
struct _KAFFINITY_EX Affinity; //0x38
struct _LIST_ENTRY ReadyListHead; //0x44
struct _SINGLE_LIST_ENTRY SwapListEntry; //0x4c
volatile struct _KAFFINITY_EX ActiveProcessors; //0x50
union
{
struct
{
volatile LONG AutoAlignment:1; //0x5c
volatile LONG DisableBoost:1; //0x5c
volatile LONG DisableQuantum:1; //0x5c
volatile ULONG ActiveGroupsMask:1; //0x5c
volatile LONG ReservedFlags:28; //0x5c
};
volatile LONG ProcessFlags; //0x5c
};
CHAR BasePriority; //0x60
CHAR QuantumReset; //0x61
UCHAR Visited; //0x62
UCHAR Unused3; //0x63
ULONG ThreadSeed[1]; //0x64
USHORT IdealNode[1]; //0x68
USHORT IdealGlobalNode; //0x6a
union _KEXECUTE_OPTIONS Flags; //0x6c
UCHAR Unused1; //0x6d
USHORT IopmOffset; //0x6e
ULONG Unused4; //0x70
union _KSTACK_COUNT StackCount; //0x74
struct _LIST_ENTRY ProcessListEntry; //0x78
volatile ULONGLONG CycleTime; //0x80
ULONG KernelTime; //0x88
ULONG UserTime; //0x8c
VOID* VdmTrapcHandler; //0x90
};

ETHREAD

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
123
124
125
126
127
128
//0x2b8 bytes (sizeof)
struct _ETHREAD
{
struct _KTHREAD Tcb; //0x0
union _LARGE_INTEGER CreateTime; //0x200
union
{
union _LARGE_INTEGER ExitTime; //0x208
struct _LIST_ENTRY KeyedWaitChain; //0x208
};
LONG ExitStatus; //0x210
union
{
struct _LIST_ENTRY PostBlockList; //0x214
struct
{
VOID* ForwardLinkShadow; //0x214
VOID* StartAddress; //0x218
};
};
union
{
struct _TERMINATION_PORT* TerminationPort; //0x21c
struct _ETHREAD* ReaperLink; //0x21c
VOID* KeyedWaitValue; //0x21c
};
ULONG ActiveTimerListLock; //0x220
struct _LIST_ENTRY ActiveTimerListHead; //0x224
struct _CLIENT_ID Cid; //0x22c
union
{
struct _KSEMAPHORE KeyedWaitSemaphore; //0x234
struct _KSEMAPHORE AlpcWaitSemaphore; //0x234
};
union _PS_CLIENT_SECURITY_CONTEXT ClientSecurity; //0x248
struct _LIST_ENTRY IrpList; //0x24c
ULONG TopLevelIrp; //0x254
struct _DEVICE_OBJECT* DeviceToVerify; //0x258
union _PSP_CPU_QUOTA_APC* CpuQuotaApc; //0x25c
VOID* Win32StartAddress; //0x260
VOID* LegacyPowerObject; //0x264
struct _LIST_ENTRY ThreadListEntry; //0x268
struct _EX_RUNDOWN_REF RundownProtect; //0x270
struct _EX_PUSH_LOCK ThreadLock; //0x274
ULONG ReadClusterSize; //0x278
volatile LONG MmLockOrdering; //0x27c
union
{
ULONG CrossThreadFlags; //0x280
struct
{
ULONG Terminated:1; //0x280
ULONG ThreadInserted:1; //0x280
ULONG HideFromDebugger:1; //0x280
ULONG ActiveImpersonationInfo:1; //0x280
ULONG Reserved:1; //0x280
ULONG HardErrorsAreDisabled:1; //0x280
ULONG BreakOnTermination:1; //0x280
ULONG SkipCreationMsg:1; //0x280
ULONG SkipTerminationMsg:1; //0x280
ULONG CopyTokenOnOpen:1; //0x280
ULONG ThreadIoPriority:3; //0x280
ULONG ThreadPagePriority:3; //0x280
ULONG RundownFail:1; //0x280
ULONG NeedsWorkingSetAging:1; //0x280
};
};
union
{
ULONG SameThreadPassiveFlags; //0x284
struct
{
ULONG ActiveExWorker:1; //0x284
ULONG ExWorkerCanWaitUser:1; //0x284
ULONG MemoryMaker:1; //0x284
ULONG ClonedThread:1; //0x284
ULONG KeyedEventInUse:1; //0x284
ULONG RateApcState:2; //0x284
ULONG SelfTerminate:1; //0x284
};
};
union
{
ULONG SameThreadApcFlags; //0x288
struct
{
UCHAR Spare:1; //0x288
volatile UCHAR StartAddressInvalid:1; //0x288
UCHAR EtwPageFaultCalloutActive:1; //0x288
UCHAR OwnsProcessWorkingSetExclusive:1; //0x288
UCHAR OwnsProcessWorkingSetShared:1; //0x288
UCHAR OwnsSystemCacheWorkingSetExclusive:1; //0x288
UCHAR OwnsSystemCacheWorkingSetShared:1; //0x288
UCHAR OwnsSessionWorkingSetExclusive:1; //0x288
UCHAR OwnsSessionWorkingSetShared:1; //0x289
UCHAR OwnsProcessAddressSpaceExclusive:1; //0x289
UCHAR OwnsProcessAddressSpaceShared:1; //0x289
UCHAR SuppressSymbolLoad:1; //0x289
UCHAR Prefetching:1; //0x289
UCHAR OwnsDynamicMemoryShared:1; //0x289
UCHAR OwnsChangeControlAreaExclusive:1; //0x289
UCHAR OwnsChangeControlAreaShared:1; //0x289
UCHAR OwnsPagedPoolWorkingSetExclusive:1; //0x28a
UCHAR OwnsPagedPoolWorkingSetShared:1; //0x28a
UCHAR OwnsSystemPtesWorkingSetExclusive:1; //0x28a
UCHAR OwnsSystemPtesWorkingSetShared:1; //0x28a
UCHAR TrimTrigger:2; //0x28a
UCHAR Spare1:2; //0x28a
UCHAR PriorityRegionActive; //0x28b
};
};
UCHAR CacheManagerActive; //0x28c
UCHAR DisablePageFaultClustering; //0x28d
UCHAR ActiveFaultCount; //0x28e
UCHAR LockOrderState; //0x28f
ULONG AlpcMessageId; //0x290
union
{
VOID* AlpcMessage; //0x294
ULONG AlpcReceiveAttributeSet; //0x294
};
struct _LIST_ENTRY AlpcWaitListEntry; //0x298
ULONG CacheManagerCount; //0x2a0
ULONG IoBoostCount; //0x2a4
ULONG IrpListLock; //0x2a8
VOID* ReservedForSynchTracking; //0x2ac
struct _SINGLE_LIST_ENTRY CmCallbackListHead; //0x2b0
};

_KTHREAD Tcb; //0x0 跟EPROCESS一样,第一个结构体是嵌入的KTHREAD

StartAddress; //0x218 线程函数的起始地址

ThreadListEntry; //0x268 就是在这里链到进程的双向链表

KTHREAD

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//0x200 bytes (sizeof)
struct _KTHREAD
{
struct _DISPATCHER_HEADER Header; //0x0
volatile ULONGLONG CycleTime; //0x10
volatile ULONG HighCycleTime; //0x18
ULONGLONG QuantumTarget; //0x20
VOID* InitialStack; //0x28
VOID* volatile StackLimit; //0x2c
VOID* KernelStack; //0x30
ULONG ThreadLock; //0x34
union _KWAIT_STATUS_REGISTER WaitRegister; //0x38
volatile UCHAR Running; //0x39
UCHAR Alerted[2]; //0x3a
union
{
struct
{
ULONG KernelStackResident:1; //0x3c
ULONG ReadyTransition:1; //0x3c
ULONG ProcessReadyQueue:1; //0x3c
ULONG WaitNext:1; //0x3c
ULONG SystemAffinityActive:1; //0x3c
ULONG Alertable:1; //0x3c
ULONG GdiFlushActive:1; //0x3c
ULONG UserStackWalkActive:1; //0x3c
ULONG ApcInterruptRequest:1; //0x3c
ULONG ForceDeferSchedule:1; //0x3c
ULONG QuantumEndMigrate:1; //0x3c
ULONG UmsDirectedSwitchEnable:1; //0x3c
ULONG TimerActive:1; //0x3c
ULONG SystemThread:1; //0x3c
ULONG Reserved:18; //0x3c
};
LONG MiscFlags; //0x3c
};
union
{
struct _KAPC_STATE ApcState; //0x40
struct
{
UCHAR ApcStateFill[23]; //0x40
CHAR Priority; //0x57
};
};
volatile ULONG NextProcessor; //0x58
volatile ULONG DeferredProcessor; //0x5c
ULONG ApcQueueLock; //0x60
ULONG ContextSwitches; //0x64
volatile UCHAR State; //0x68
CHAR NpxState; //0x69
UCHAR WaitIrql; //0x6a
CHAR WaitMode; //0x6b
volatile LONG WaitStatus; //0x6c
struct _KWAIT_BLOCK* WaitBlockList; //0x70
union
{
struct _LIST_ENTRY WaitListEntry; //0x74
struct _SINGLE_LIST_ENTRY SwapListEntry; //0x74
};
struct _KQUEUE* volatile Queue; //0x7c
ULONG WaitTime; //0x80
union
{
struct
{
SHORT KernelApcDisable; //0x84
SHORT SpecialApcDisable; //0x86
};
ULONG CombinedApcDisable; //0x84
};
VOID* Teb; //0x88
struct _KTIMER Timer; //0x90
union
{
struct
{
volatile ULONG AutoAlignment:1; //0xb8
volatile ULONG DisableBoost:1; //0xb8
volatile ULONG EtwStackTraceApc1Inserted:1; //0xb8
volatile ULONG EtwStackTraceApc2Inserted:1; //0xb8
volatile ULONG CalloutActive:1; //0xb8
volatile ULONG ApcQueueable:1; //0xb8
volatile ULONG EnableStackSwap:1; //0xb8
volatile ULONG GuiThread:1; //0xb8
volatile ULONG UmsPerformingSyscall:1; //0xb8
volatile ULONG VdmSafe:1; //0xb8
volatile ULONG UmsDispatched:1; //0xb8
volatile ULONG ReservedFlags:21; //0xb8
};
volatile LONG ThreadFlags; //0xb8
};
VOID* ServiceTable; //0xbc
struct _KWAIT_BLOCK WaitBlock[4]; //0xc0
struct _LIST_ENTRY QueueListEntry; //0x120
struct _KTRAP_FRAME* TrapFrame; //0x128
VOID* FirstArgument; //0x12c
union
{
VOID* CallbackStack; //0x130
ULONG CallbackDepth; //0x130
};
UCHAR ApcStateIndex; //0x134
CHAR BasePriority; //0x135
union
{
CHAR PriorityDecrement; //0x136
struct
{
UCHAR ForegroundBoost:4; //0x136
UCHAR UnusualBoost:4; //0x136
};
};
UCHAR Preempted; //0x137
UCHAR AdjustReason; //0x138
CHAR AdjustIncrement; //0x139
CHAR PreviousMode; //0x13a
CHAR Saturation; //0x13b
ULONG SystemCallNumber; //0x13c
ULONG FreezeCount; //0x140
volatile struct _GROUP_AFFINITY UserAffinity; //0x144
struct _KPROCESS* Process; //0x150
volatile struct _GROUP_AFFINITY Affinity; //0x154
ULONG IdealProcessor; //0x160
ULONG UserIdealProcessor; //0x164
struct _KAPC_STATE* ApcStatePointer[2]; //0x168
union
{
struct _KAPC_STATE SavedApcState; //0x170
struct
{
UCHAR SavedApcStateFill[23]; //0x170
UCHAR WaitReason; //0x187
};
};
CHAR SuspendCount; //0x188
CHAR Spare1; //0x189
UCHAR OtherPlatformFill; //0x18a
VOID* volatile Win32Thread; //0x18c
VOID* StackBase; //0x190
union
{
struct _KAPC SuspendApc; //0x194
struct
{
UCHAR SuspendApcFill0[1]; //0x194
UCHAR ResourceIndex; //0x195
};
struct
{
UCHAR SuspendApcFill1[3]; //0x194
UCHAR QuantumReset; //0x197
};
struct
{
UCHAR SuspendApcFill2[4]; //0x194
ULONG KernelTime; //0x198
};
struct
{
UCHAR SuspendApcFill3[36]; //0x194
struct _KPRCB* volatile WaitPrcb; //0x1b8
};
struct
{
UCHAR SuspendApcFill4[40]; //0x194
VOID* LegoData; //0x1bc
};
struct
{
UCHAR SuspendApcFill5[47]; //0x194
UCHAR LargeStack; //0x1c3
};
};
ULONG UserTime; //0x1c4
union
{
struct _KSEMAPHORE SuspendSemaphore; //0x1c8
UCHAR SuspendSemaphorefill[20]; //0x1c8
};
ULONG SListFaultCount; //0x1dc
struct _LIST_ENTRY ThreadListEntry; //0x1e0
struct _LIST_ENTRY MutantListHead; //0x1e8
VOID* SListFaultAddress; //0x1f0
struct _KTHREAD_COUNTERS* ThreadCounters; //0x1f4
struct _XSTATE_SAVE* XStateSave; //0x1f8
};

Header; //0x0 可等待对象的标准头部

InitialStack; //0x28 当前线程的栈底

StackLimit; //0x2c 当前线程的最大栈顶

KernelStack; //0x30 线程切换时,会保存当前的ESP,等到再次切换回来时,从这里恢复ESP

_LIST_ENTRY ThreadListEntry; //0x1e0 这里仍然是链在进程的双向链表中

Refs

X86内核笔记_4_进程和线程-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com

[原创]Windows内核学习笔记之线程(下)-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com