系统调用

c++

Posted by YiMiTuMi on May 17, 2021

系统调用

API函数的调用过程称为系统调用。

API函数调用过程:

Kernel32.dll:最核心的功能模块,比如管理内存、进程和线程相关的函数等。

User32.dll:是Windows用户界面相关应用程序接口,如创建窗口和发送消息等。

GDI32.dll:图形设备接口,包含用于画图和显示文本的函数,比如要显示一个进程窗口,就调用了其中的函数来画这个窗口。

Ntdll.dll:大多数API都会通过这个DLL进入内核(0环)。

_KUSER_SHARED_DATA (R3进R0的门)

1)在User层和Kernel层分别定义了一个 _KUSER_SHARED_DATA 结构区域,用于User层和Kernel层共享某些数据。

2)他们使用了固定的地址映射,_KUSER_SHARED_DATA结构体区域在User和Kernel层地址分别为:

User层地址为:0x7ffe0000

Kernel层地址为:0xffdf0000

注意:虽然指向的是同一个物理页,但在User层是只读的,在Kernel层是可写的。

结构体信息:

kd> dt _KUSER_SHARED_DATA
ntdll!_KUSER_SHARED_DATA
   +0x000 TickCountLowDeprecated : Uint4B
   +0x004 TickCountMultiplier : Uint4B
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : Uint2B
   +0x02e ImageNumberHigh  : Uint2B
   +0x030 NtSystemRoot     : [260] Wchar
   +0x238 MaxStackTraceDepth : Uint4B
   +0x23c CryptoExponent   : Uint4B
   +0x240 TimeZoneId       : Uint4B
   +0x244 LargePageMinimum : Uint4B
   +0x248 Reserved2        : [7] Uint4B
   +0x264 NtProductType    : _NT_PRODUCT_TYPE
   +0x268 ProductTypeIsValid : UChar
   +0x26c NtMajorVersion   : Uint4B
   +0x270 NtMinorVersion   : Uint4B
   +0x274 ProcessorFeatures : [64] UChar
   +0x2b4 Reserved1        : Uint4B
   +0x2b8 Reserved3        : Uint4B
   +0x2bc TimeSlip         : Uint4B
   +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
   +0x2c4 AltArchitecturePad : [1] Uint4B
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER
   +0x2d0 SuiteMask        : Uint4B
   +0x2d4 KdDebuggerEnabled : UChar
   +0x2d5 NXSupportPolicy  : UChar
   +0x2d8 ActiveConsoleId  : Uint4B
   +0x2dc DismountCount    : Uint4B
   +0x2e0 ComPlusPackage   : Uint4B
   +0x2e4 LastSystemRITEventTickCount : Uint4B
   +0x2e8 NumberOfPhysicalPages : Uint4B
   +0x2ec SafeBootMode     : UChar
   +0x2ed TscQpcData       : UChar
   +0x2ed TscQpcEnabled    : Pos 0, 1 Bit
   +0x2ed TscQpcSpareFlag  : Pos 1, 1 Bit
   +0x2ed TscQpcShift      : Pos 2, 6 Bits
   +0x2ee TscQpcPad        : [2] UChar
   +0x2f0 SharedDataFlags  : Uint4B
   +0x2f0 DbgErrorPortPresent : Pos 0, 1 Bit
   +0x2f0 DbgElevationEnabled : Pos 1, 1 Bit
   +0x2f0 DbgVirtEnabled   : Pos 2, 1 Bit
   +0x2f0 DbgInstallerDetectEnabled : Pos 3, 1 Bit
   +0x2f0 DbgSystemDllRelocated : Pos 4, 1 Bit
   +0x2f0 DbgDynProcessorEnabled : Pos 5, 1 Bit
   +0x2f0 DbgSEHValidationEnabled : Pos 6, 1 Bit
   +0x2f0 SpareBits        : Pos 7, 25 Bits
   +0x2f4 DataFlagsPad     : [1] Uint4B
   +0x2f8 TestRetInstruction : Uint8B
   +0x300 SystemCall       : Uint4B
   +0x304 SystemCallReturn : Uint4B
   +0x308 SystemCallPad    : [3] Uint8B
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : Uint8B
   +0x320 ReservedTickCountOverlay : [3] Uint4B
   +0x32c TickCountPad     : [1] Uint4B
   +0x330 Cookie           : Uint4B
   +0x334 CookiePad        : [1] Uint4B
   +0x338 ConsoleSessionForegroundProcessId : Int8B
   +0x340 Wow64SharedInformation : [16] Uint4B
   +0x380 UserModeGlobalLogger : [16] Uint2B
   +0x3a0 ImageFileExecutionOptions : Uint4B
   +0x3a4 LangGenerationCount : Uint4B
   +0x3a8 Reserved5        : Uint8B
   +0x3b0 InterruptTimeBias : Uint8B
   +0x3b8 TscQpcBias       : Uint8B
   +0x3c0 ActiveProcessorCount : Uint4B
   +0x3c4 ActiveGroupCount : Uint2B
   +0x3c6 Reserved4        : Uint2B
   +0x3c8 AitSamplingValue : Uint4B
   +0x3cc AppCompatFlag    : Uint4B
   +0x3d0 SystemDllNativeRelocation : Uint8B
   +0x3d8 SystemDllWowRelocation : Uint4B
   +0x3dc XStatePad        : [1] Uint4B
   +0x3e0 XState           : _XSTATE_CONFIGURATION

查看 SystemCall

函数从R3进入R0会调用这段代码(以NtReadVirtualMemory为例):

 						       mov     eax, 115h; 115h服务号 NtReadVirtualMemory
.text:77F062FD                 mov     edx, 7FFE0300h
.text:77F06302                 call    dword ptr [edx]
.text:77F06304                 retn    14h
					.
					.
					.

7FFE0300h是在_KUSER_SHARED_DATA的起始位置偏移300个字节,能够找到一个名为 SystemCall 的数据里面保存了代码:

先关联进程:

kd> .process 85fdcc98
Implicit process is now 85fdcc98

查看结构体:

kd> dt _KUSER_SHARED_DATA 0x7ffe0000
ntdll!_KUSER_SHARED_DATA
   +0x000 TickCountLowDeprecated : 0
   +0x004 TickCountMultiplier : 0xf99a027
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : 0x14c
   +0x02e ImageNumberHigh  : 0x14c
   +0x030 NtSystemRoot     : [260]  "C:\Windows"
   +0x238 MaxStackTraceDepth : 0
   +0x23c CryptoExponent   : 0
   +0x240 TimeZoneId       : 0
   +0x244 LargePageMinimum : 0x200000
   +0x248 Reserved2        : [7] 0
   +0x264 NtProductType    : 1 ( NtProductWinNt )
   +0x268 ProductTypeIsValid : 0x1 ''
   +0x26c NtMajorVersion   : 6
   +0x270 NtMinorVersion   : 1
   +0x274 ProcessorFeatures : [64]  ""
   +0x2b4 Reserved1        : 0x7ffeffff
   +0x2b8 Reserved3        : 0x80000000
   +0x2bc TimeSlip         : 0
   +0x2c0 AlternativeArchitecture : 0 ( StandardDesign )
   +0x2c4 AltArchitecturePad : [1] 0
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER 0x0
   +0x2d0 SuiteMask        : 0x110
   +0x2d4 KdDebuggerEnabled : 0x3 ''
   +0x2d5 NXSupportPolicy  : 0x2 ''
   +0x2d8 ActiveConsoleId  : 1
   +0x2dc DismountCount    : 0
   +0x2e0 ComPlusPackage   : 0xffffffff
   +0x2e4 LastSystemRITEventTickCount : 0xefab
   +0x2e8 NumberOfPhysicalPages : 0x3ff7e
   +0x2ec SafeBootMode     : 0 ''
   +0x2ed TscQpcData       : 0 ''
   +0x2ed TscQpcEnabled    : 0y0
   +0x2ed TscQpcSpareFlag  : 0y0
   +0x2ed TscQpcShift      : 0y000000 (0)
   +0x2ee TscQpcPad        : [2]  ""
   +0x2f0 SharedDataFlags  : 0xe
   +0x2f0 DbgErrorPortPresent : 0y0
   +0x2f0 DbgElevationEnabled : 0y1
   +0x2f0 DbgVirtEnabled   : 0y1
   +0x2f0 DbgInstallerDetectEnabled : 0y1
   +0x2f0 DbgSystemDllRelocated : 0y0
   +0x2f0 DbgDynProcessorEnabled : 0y0
   +0x2f0 DbgSEHValidationEnabled : 0y0
   +0x2f0 SpareBits        : 0y0000000000000000000000000 (0)
   +0x2f4 DataFlagsPad     : [1] 0
   +0x2f8 TestRetInstruction : 0xc3
   +0x300 SystemCall       : 0x774d70b0
   +0x304 SystemCallReturn : 0x774d70b4
   +0x308 SystemCallPad    : [3] 0
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : 0x11ba
   +0x320 ReservedTickCountOverlay : [3] 0x11ba
   +0x32c TickCountPad     : [1] 0
   +0x330 Cookie           : 0xc72ec375
   +0x334 CookiePad        : [1] 0
   +0x338 ConsoleSessionForegroundProcessId : 0n1876
   +0x340 Wow64SharedInformation : [16] 0
   +0x380 UserModeGlobalLogger : [16] 0
   +0x3a0 ImageFileExecutionOptions : 0
   +0x3a4 LangGenerationCount : 1
   +0x3a8 Reserved5        : 0
   +0x3b0 InterruptTimeBias : 0
   +0x3b8 TscQpcBias       : 0
   +0x3c0 ActiveProcessorCount : 1
   +0x3c4 ActiveGroupCount : 1
   +0x3c6 Reserved4        : 0
   +0x3c8 AitSamplingValue : 0
   +0x3cc AppCompatFlag    : 1
   +0x3d0 SystemDllNativeRelocation : 0xff5d0000
   +0x3d8 SystemDllWowRelocation : 0
   +0x3dc XStatePad        : [1] 0
   +0x3e0 XState           : _XSTATE_CONFIGURATION

查看 SystemCall:

win7 x86:

kd> u 0x774d70b0
ntdll!KiFastSystemCall:
774d70b0 8bd4            mov     edx,esp  //方便0环找到参数
774d70b2 0f34            sysenter  //快速调用

ntdll!KiFastSystemCallRet:
774d70b4 c3              ret
774d70b5 8da42400000000  lea     esp,[esp]
774d70bc 8d642400        lea     esp,[esp]

ntdll!KiIntSystemCall: //系统调用号在EAX中
774d70c0 8d542408        lea     edx,[esp+8]
774d70c4 cd2e            int     2Eh   //进入内核,自陷
774d70c6 c3              ret

xp:

kd> u 0x8693b0c9
ntdll!KiFastSystemCall:

mov edx, esp
sysenter           //快速调用

判断CPU是否支持快速调用

当同过eax = 1来执行cpuid指令时,处理器的特征信息被放在ecx和edx寄存器中,其中edx包含了一个SEP位(11位),该位指明了当前处理器是否支持sysenter/sexit指令。

支持:

ntdll.dll!KiFastSystemCall()

不支持:

ntdll.dll!IntSystemCall()

通过中断(KiIntSystemCall)进R0

流程:

						      R3的门      IDT提权           R0的门
Ker32 -> Ntdll.dll -> Call 0x7ffe0000 -> int 2EH -> nt!KiSystemService

Int 2E从IDT、TSS获取寄存器的值,这些都是内存。

通过快速调用(KiFastSystemCall)进R0

R3进R0主要就是提权,而提权主要就是换掉一些寄存器,CS、EIP、SS(TSS)、ESP(TSS),所以在执行Sysenter指令之前,操作系统必须指定0环的CS段、SS段、EIO以及ESP。

			   MSR寄存器               地址
		
			IA32_SYSENTER_CS          174H
			
			IA32_SYSENTER_ESP         175H
			
			IA32_SYSENTER_EIP         176H

可以通过RDMSR/WRMST来进行读写,(操作系统使用WRMST写该寄存器):

kd> rdmsr 174 //查看CS
kd> rdmsr 175 //查看CSP
kd> rdmsr 176 //查看CIP

Sysenter查MSR寄存器获取CS、EIP、ESP换掉其中的值,从寄存器中获取。SS是写死的,算出来的。

CS = 8,SS = CS + 8

R0函数

通过 int 0x2E进入R0调用的函数为:

KiSystemService

push 0        //0x064 ErrCode 错误码
push ebp
push ebx
push esi
push edi
push fs
mov ebx, 30h
db 66h          //改变操作数的宽度为16位的
mov Fs, bx     //加载FS,FS在R3指向TEB。

通过快速调用进R0调用的函数为:

KiFastCallEntry

_Trap_Frame结构(操作系统要求的)

windows将R0的堆栈描述为_Trap_Frame结构,即操作系统维护了一个结构 _KTRAP_FRAME ,在该结构里保存了一个线程3环的寄存器的值。

_Trap_Frame是指中断、自陷、异常进入内核后,在堆栈上形成的一种数据结构,用来存储三环的寄存器。(每一个线程有一个该结构体。)

结构:

kd> dt _KTrap_Frame
ntdll!_KTRAP_FRAME
   +0x000 DbgEbp           : Uint4B
   +0x004 DbgEip           : Uint4B
   +0x008 DbgArgMark       : Uint4B
   +0x00c DbgArgPointer    : Uint4B
   +0x010 TempSegCs        : Uint2B
   +0x012 Logging          : UChar
   +0x013 Reserved         : UChar
   +0x014 TempEsp          : Uint4B
   +0x018 Dr0              : Uint4B
   +0x01c Dr1              : Uint4B
   +0x020 Dr2              : Uint4B
   +0x024 Dr3              : Uint4B
   +0x028 Dr6              : Uint4B
   +0x02c Dr7              : Uint4B
   +0x030 SegGs            : Uint4B
   +0x034 SegEs            : Uint4B
   +0x038 SegDs            : Uint4B
   +0x03c Edx              : Uint4B
   +0x040 Ecx              : Uint4B
   +0x044 Eax              : Uint4B
   +0x048 PreviousPreviousMode : Uint4B
   +0x04c ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x050 SegFs            : Uint4B
   +0x054 Edi              : Uint4B
   +0x058 Esi              : Uint4B
   +0x05c Ebx              : Uint4B
   +0x060 Ebp              : Uint4B    //三环的ebp
   +0x064 ErrCode          : Uint4B
   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B
   +0x078 HardwareSegSs    : Uint4B
   +0x07c V86Es            : Uint4B
   +0x080 V86Ds            : Uint4B
   +0x084 V86Fs            : Uint4B
   +0x088 V86Gs            : Uint4B

int 2E进入R0后从TSS中获取了SSESP0这两个值,ESP0指向_Trap_Frame结构的0x07c的位置,之后PUSH的位置为HardwareSegSs。

ps:从TSS中获取的ESP0是一个线程一个的,每个线程都不同,所以说_Trap_Frame结构也是和线程相关的一个线程一个,所以要保存寄存器。

ps:TSS里面永远都是当前执行线程的ESP0,在线程切换的时候会更新TSS。

当我们刚进入R0后ESP0指向0x07c的位置,之后向堆栈中压入了5个值为(中断门也可以用来提权。不提权时,INT N 会压栈CS,EFLAG EIP;提权时,会依次压栈 SS ESP EFLAG CS EIP。需要用堆栈保存EFLAG是因为中断门会将EFLAG的IF位置0.):

   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B
   +0x078 HardwareSegSs    : Uint4B

所以KiSystemService函数开始向堆栈中PUSH的5个值为:

   +0x050 SegFs            : Uint4B  6 
   +0x054 Edi              : Uint4B  5
   +0x058 Esi              : Uint4B  4
   +0x05c Ebx              : Uint4B  3
   +0x060 Ebp              : Uint4B  2
   +0x064 ErrCode          : Uint4B  1

FS解析

windwos内核有个特殊的基本要求,就是只要CPU在内核中运行就要加载新的FS,FS在R3指向TEB,在R0指向一个结构体KPCR(在Windwos中线性地址为0xFFDFF000),R0的FS.base指向自己的KPCR,不是指向当前线程的。

mov ebx, 0x30
mov fs, bx

0x30为段选择子,解析后为:运行级别0环、采用GDT表、下标为6.

win7下查看段描述符:FFC093df`F0000001

FS.Base:FFDFF000指向当前CPU的KPCR.

KPCR(CPU控制区)

CPU也有自己的控制块,每个CPU有一个,叫KPCR。

KPCR:

kd> dt _KPCR
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 SpareUnused      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B
   +0x090 SecondLevelCacheSize : Uint4B
   +0x094 HalReserved      : [16] Uint4B
   +0x0d4 InterruptMode    : Uint4B
   +0x0d8 Spare1           : UChar
   +0x0dc KernelReserved2  : [17] Uint4B
   +0x120 PrcbData         : _KPRCB    //拓展结构体

查看CPU数量:

kd> dd KenumberProcessors
83fbf96c  00000001 83f4bf33 00000002 00000001
83fbf97c  00000000 00000000 00000020 1fc10000
83fbf98c  00110017 00006001 777e7058 777e6f58
83fbf99c  777e6fc0 777e7008 777d5a8f 777d5a8d
83fbf9ac  777d5a64 00000000 00869238 842185b0
83fbf9bc  841824f2 83ed3d9c 00000000 00000191
83fbf9cc  83ed43e4 00000000 00000000 00000000
83fbf9dc  00000000 83f326af 00000000 0193b6a8

00000001 一个CPU

查看每个CPU对应的KPCR:

kd> dd KiprocessorBlock
83fbf8c0  83f80d20 00000000 00000000 00000000
83fbf8d0  00000000 00000000 00000000 00000000
83fbf8e0  00000000 00000000 00000000 00000000
83fbf8f0  00000000 00000000 00000000 00000000
83fbf900  00000000 00000000 00000000 00000000
83fbf910  00000000 00000000 00000000 00000000
83fbf920  00000000 00000000 00000000 00000000
83fbf930  00000000 00000000 00000000 00000000

KPCR:

	kd> dt _kpcr 83f80d20  //如果找不到就将地址减去120
	ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : 0x00010001 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : 0x83f8a380 Void
   +0x008 Spare2           : (null) 
   +0x00c TssCopy          : 0x83f8a380 Void
   +0x010 ContextSwitches  : 0x100
   +0x014 SetMemberCopy    : 0x60010117
   +0x018 Used_Self        : 0x0001007f Void
   +0x01c SelfPcr          : (null) 
   +0x020 Prcb             : (null) 
   +0x024 Irql             : 0 ''
   +0x028 IRR              : 0
   +0x02c IrrActive        : 0
   +0x030 IDR              : 0
   +0x034 KdVersionBlock   : (null) 
   +0x038 IDT              : (null) 
   +0x03c GDT              : (null) 
   +0x040 TSS              : (null) 
   +0x044 MajorVersion     : 0
   +0x046 MinorVersion     : 0
   +0x048 SetMember        : 0
   +0x04c StallScaleFactor : 0
   +0x050 SpareUnused      : 0 ''
   +0x051 Number           : 0 ''
   +0x052 Spare0           : 0 ''
   +0x053 SecondLevelCacheAssociativity : 0 ''
   +0x054 VdmAlert         : 0
   +0x058 KernelReserved   : [14] 0
   +0x090 SecondLevelCacheSize : 0x83e5ce8d
   +0x094 HalReserved      : [16] 0
   +0x0d4 InterruptMode    : 8
   +0x0d8 Spare1           : 0x82 ''
   +0x0dc KernelReserved2  : [17] 0x83f7d9dc
   +0x120 PrcbData         : _KPRCB

0x000 NtTib: _NT_TIB:

KPCR的第一个成员是一个结构体_NT_TIB:

kd> dt _nt_tib
ntdll!_NT_TIB
   +0x000 c    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 StackBase        : Ptr32 Void
   +0x008 StackLimit       : Ptr32 Void
   +0x00c SubSystemTib     : Ptr32 Void
   +0x010 FiberData        : Ptr32 Void
   +0x010 Version          : Uint4B
   +0x014 ArbitraryUserPointer : Ptr32 Void
   +0x018 Self             : Ptr32 _NT_TIB

第一个成员ExceptionList为异常链表,里面存储的为异常的处理函数。(SEH)

0x120 PrcbData: _KPRCB:

kd> dt _KPRCB
ntdll!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD //当前CPU执行线程的_KTHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD //下一个_KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
   +0x010 LegacyNumber     : UChar          //CPU编号
   +0x011 NestingLevel     : UChar
   +0x012 BuildType        : Uint2B
   +0x014 CpuType          : Char
   +0x015 CpuID            : Char
   +0x016 CpuStep          : Uint2B         //CPU子版本号
   +0x016 CpuStepping      : UChar
   +0x017 CpuModel         : UChar
   +0x018 ProcessorState   : _KPROCESSOR_STATE //CPU状态
   +0x338 KernelReserved   : [16] Uint4B
   +0x378 HalReserved      : [16] Uint4B
   +0x3b8 CFlushSize       : Uint4B
   +0x3bc CoresPerPhysicalProcessor : UChar
   +0x3bd LogicalProcessorsPerCore : UChar
   +0x3be PrcbPad0         : [2] UChar
   +0x3c0 MHz              : Uint4B
   +0x3c4 CpuVendor        : UChar
   +0x3c5 GroupIndex       : UChar
   +0x3c6 Group            : Uint2B
   +0x3c8 GroupSetMember   : Uint4B
   +0x3cc Number           : Uint4B
   +0x3d0 PrcbPad1         : [72] UChar
   +0x418 LockQueue        : [17] _KSPIN_LOCK_QUEUE
   +0x4a0 NpxThread        : Ptr32 _KTHREAD
   +0x4a4 InterruptCount   : Uint4B
   +0x4a8 KernelTime       : Uint4B
   +0x4ac UserTime         : Uint4B
   +0x4b0 DpcTime          : Uint4B
   +0x4b4 DpcTimeCount     : Uint4B
   +0x4b8 InterruptTime    : Uint4B
   +0x4bc AdjustDpcThreshold : Uint4B
   +0x4c0 PageColor        : Uint4B
   +0x4c4 DebuggerSavedIRQL : UChar
   +0x4c5 NodeColor        : UChar
   +0x4c6 PrcbPad20        : [2] UChar
   +0x4c8 NodeShiftedColor : Uint4B
   +0x4cc ParentNode       : Ptr32 _KNODE
   +0x4d0 SecondaryColorMask : Uint4B
   +0x4d4 DpcTimeLimit     : Uint4B
   +0x4d8 PrcbPad21        : [2] Uint4B
   +0x4e0 CcFastReadNoWait : Uint4B
   +0x4e4 CcFastReadWait   : Uint4B
   +0x4e8 CcFastReadNotPossible : Uint4B
   +0x4ec CcCopyReadNoWait : Uint4B
   +0x4f0 CcCopyReadWait   : Uint4B
   +0x4f4 CcCopyReadNoWaitMiss : Uint4B
   +0x4f8 MmSpinLockOrdering : Int4B
   +0x4fc IoReadOperationCount : Int4B
   +0x500 IoWriteOperationCount : Int4B
   +0x504 IoOtherOperationCount : Int4B
   +0x508 IoReadTransferCount : _LARGE_INTEGER
   +0x510 IoWriteTransferCount : _LARGE_INTEGER
   +0x518 IoOtherTransferCount : _LARGE_INTEGER
   +0x520 CcFastMdlReadNoWait : Uint4B
   +0x524 CcFastMdlReadWait : Uint4B
   +0x528 CcFastMdlReadNotPossible : Uint4B
   +0x52c CcMapDataNoWait  : Uint4B
   +0x530 CcMapDataWait    : Uint4B
   +0x534 CcPinMappedDataCount : Uint4B
   +0x538 CcPinReadNoWait  : Uint4B
   +0x53c CcPinReadWait    : Uint4B
   +0x540 CcMdlReadNoWait  : Uint4B
   +0x544 CcMdlReadWait    : Uint4B
   +0x548 CcLazyWriteHotSpots : Uint4B
   +0x54c CcLazyWriteIos   : Uint4B
   +0x550 CcLazyWritePages : Uint4B
   +0x554 CcDataFlushes    : Uint4B
   +0x558 CcDataPages      : Uint4B
   +0x55c CcLostDelayedWrites : Uint4B
   +0x560 CcFastReadResourceMiss : Uint4B
   +0x564 CcCopyReadWaitMiss : Uint4B
   +0x568 CcFastMdlReadResourceMiss : Uint4B
   +0x56c CcMapDataNoWaitMiss : Uint4B
   +0x570 CcMapDataWaitMiss : Uint4B
   +0x574 CcPinReadNoWaitMiss : Uint4B
   +0x578 CcPinReadWaitMiss : Uint4B
   +0x57c CcMdlReadNoWaitMiss : Uint4B
   +0x580 CcMdlReadWaitMiss : Uint4B
   +0x584 CcReadAheadIos   : Uint4B
   +0x588 KeAlignmentFixupCount : Uint4B
   +0x58c KeExceptionDispatchCount : Uint4B
   +0x590 KeSystemCalls    : Uint4B
   +0x594 AvailableTime    : Uint4B
   +0x598 PrcbPad22        : [2] Uint4B
   +0x5a0 PPLookasideList  : [16] _PP_LOOKASIDE_LIST
   +0x620 PPNPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0xf20 PPPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0x1820 PacketBarrier    : Uint4B
   +0x1824 ReverseStall     : Int4B
   +0x1828 IpiFrame         : Ptr32 Void
   +0x182c PrcbPad3         : [52] UChar
   +0x1860 CurrentPacket    : [3] Ptr32 Void
   +0x186c TargetSet        : Uint4B
   +0x1870 WorkerRoutine    : Ptr32     void 
   +0x1874 IpiFrozen        : Uint4B
   +0x1878 PrcbPad4         : [40] UChar
   +0x18a0 RequestSummary   : Uint4B
   +0x18a4 SignalDone       : Ptr32 _KPRCB
   +0x18a8 PrcbPad50        : [56] UChar
   +0x18e0 DpcData          : [2] _KDPC_DATA
   +0x1908 DpcStack         : Ptr32 Void
   +0x190c MaximumDpcQueueDepth : Int4B
   +0x1910 DpcRequestRate   : Uint4B
   +0x1914 MinimumDpcRate   : Uint4B
   +0x1918 DpcLastCount     : Uint4B
   +0x191c PrcbLock         : Uint4B
   +0x1920 DpcGate          : _KGATE
   +0x1930 ThreadDpcEnable  : UChar
   +0x1931 QuantumEnd       : UChar
   +0x1932 DpcRoutineActive : UChar
   +0x1933 IdleSchedule     : UChar
   +0x1934 DpcRequestSummary : Int4B
   +0x1934 DpcRequestSlot   : [2] Int2B
   +0x1934 NormalDpcState   : Int2B
   +0x1936 DpcThreadActive  : Pos 0, 1 Bit
   +0x1936 ThreadDpcState   : Int2B
   +0x1938 TimerHand        : Uint4B
   +0x193c LastTick         : Uint4B
   +0x1940 MasterOffset     : Int4B
   +0x1944 PrcbPad41        : [2] Uint4B
   +0x194c PeriodicCount    : Uint4B
   +0x1950 PeriodicBias     : Uint4B
   +0x1958 TickOffset       : Uint8B
   +0x1960 TimerTable       : _KTIMER_TABLE
   +0x31a0 CallDpc          : _KDPC
   +0x31c0 ClockKeepAlive   : Int4B
   +0x31c4 ClockCheckSlot   : UChar
   +0x31c5 ClockPollCycle   : UChar
   +0x31c6 PrcbPad6         : [2] UChar
   +0x31c8 DpcWatchdogPeriod : Int4B
   +0x31cc DpcWatchdogCount : Int4B
   +0x31d0 ThreadWatchdogPeriod : Int4B
   +0x31d4 ThreadWatchdogCount : Int4B
   +0x31d8 KeSpinLockOrdering : Int4B
   +0x31dc PrcbPad70        : [1] Uint4B
   +0x31e0 WaitListHead     : _LIST_ENTRY
   +0x31e8 WaitLock         : Uint4B
   +0x31ec ReadySummary     : Uint4B
   +0x31f0 QueueIndex       : Uint4B
   +0x31f4 DeferredReadyListHead : _SINGLE_LIST_ENTRY
   +0x31f8 StartCycles      : Uint8B
   +0x3200 CycleTime        : Uint8B
   +0x3208 HighCycleTime    : Uint4B
   +0x320c PrcbPad71        : Uint4B
   +0x3210 PrcbPad72        : [2] Uint8B
   +0x3220 DispatcherReadyListHead : [32] _LIST_ENTRY
   +0x3320 ChainedInterruptList : Ptr32 Void
   +0x3324 LookasideIrpFloat : Int4B
   +0x3328 MmPageFaultCount : Int4B
   +0x332c MmCopyOnWriteCount : Int4B
   +0x3330 MmTransitionCount : Int4B
   +0x3334 MmCacheTransitionCount : Int4B
   +0x3338 MmDemandZeroCount : Int4B
   +0x333c MmPageReadCount  : Int4B
   +0x3340 MmPageReadIoCount : Int4B
   +0x3344 MmCacheReadCount : Int4B
   +0x3348 MmCacheIoCount   : Int4B
   +0x334c MmDirtyPagesWriteCount : Int4B
   +0x3350 MmDirtyWriteIoCount : Int4B
   +0x3354 MmMappedPagesWriteCount : Int4B
   +0x3358 MmMappedWriteIoCount : Int4B
   +0x335c CachedCommit     : Uint4B
   +0x3360 CachedResidentAvailable : Uint4B
   +0x3364 HyperPte         : Ptr32 Void
   +0x3368 PrcbPad8         : [4] UChar
   +0x336c VendorString     : [13] UChar
   +0x3379 InitialApicId    : UChar
   +0x337a LogicalProcessorsPerPhysicalProcessor : UChar
   +0x337b PrcbPad9         : [5] UChar
   +0x3380 FeatureBits      : Uint4B
   +0x3388 UpdateSignature  : _LARGE_INTEGER
   +0x3390 IsrTime          : Uint8B
   +0x3398 RuntimeAccumulation : Uint8B
   +0x33a0 PowerState       : _PROCESSOR_POWER_STATE
   +0x3468 DpcWatchdogDpc   : _KDPC
   +0x3488 DpcWatchdogTimer : _KTIMER
   +0x34b0 WheaInfo         : Ptr32 Void
   +0x34b4 EtwSupport       : Ptr32 Void
   +0x34b8 InterruptObjectPool : _SLIST_HEADER
   +0x34c0 HypercallPageList : _SLIST_HEADER
   +0x34c8 HypercallPageVirtual : Ptr32 Void
   +0x34cc VirtualApicAssist : Ptr32 Void
   +0x34d0 StatisticsPage   : Ptr32 Uint8B
   +0x34d4 RateControl      : Ptr32 Void
   +0x34d8 Cache            : [5] _CACHE_DESCRIPTOR
   +0x3514 CacheCount       : Uint4B
   +0x3518 CacheProcessorMask : [5] Uint4B
   +0x352c PackageProcessorSet : _KAFFINITY_EX
   +0x3538 PrcbPad91        : [1] Uint4B
   +0x353c CoreProcessorSet : Uint4B
   +0x3540 TimerExpirationDpc : _KDPC
   +0x3560 SpinLockAcquireCount : Uint4B
   +0x3564 SpinLockContentionCount : Uint4B
   +0x3568 SpinLockSpinCount : Uint4B
   +0x356c IpiSendRequestBroadcastCount : Uint4B
   +0x3570 IpiSendRequestRoutineCount : Uint4B
   +0x3574 IpiSendSoftwareInterruptCount : Uint4B
   +0x3578 ExInitializeResourceCount : Uint4B
   +0x357c ExReInitializeResourceCount : Uint4B
   +0x3580 ExDeleteResourceCount : Uint4B
   +0x3584 ExecutiveResourceAcquiresCount : Uint4B
   +0x3588 ExecutiveResourceContentionsCount : Uint4B
   +0x358c ExecutiveResourceReleaseExclusiveCount : Uint4B
   +0x3590 ExecutiveResourceReleaseSharedCount : Uint4B
   +0x3594 ExecutiveResourceConvertsCount : Uint4B
   +0x3598 ExAcqResExclusiveAttempts : Uint4B
   +0x359c ExAcqResExclusiveAcquiresExclusive : Uint4B
   +0x35a0 ExAcqResExclusiveAcquiresExclusiveRecursive : Uint4B
   +0x35a4 ExAcqResExclusiveWaits : Uint4B
   +0x35a8 ExAcqResExclusiveNotAcquires : Uint4B
   +0x35ac ExAcqResSharedAttempts : Uint4B
   +0x35b0 ExAcqResSharedAcquiresExclusive : Uint4B
   +0x35b4 ExAcqResSharedAcquiresShared : Uint4B
   +0x35b8 ExAcqResSharedAcquiresSharedRecursive : Uint4B
   +0x35bc ExAcqResSharedWaits : Uint4B
   +0x35c0 ExAcqResSharedNotAcquires : Uint4B
   +0x35c4 ExAcqResSharedStarveExclusiveAttempts : Uint4B
   +0x35c8 ExAcqResSharedStarveExclusiveAcquiresExclusive : Uint4B
   +0x35cc ExAcqResSharedStarveExclusiveAcquiresShared : Uint4B
   +0x35d0 ExAcqResSharedStarveExclusiveAcquiresSharedRecursive : Uint4B
   +0x35d4 ExAcqResSharedStarveExclusiveWaits : Uint4B
   +0x35d8 ExAcqResSharedStarveExclusiveNotAcquires : Uint4B
   +0x35dc ExAcqResSharedWaitForExclusiveAttempts : Uint4B
   +0x35e0 ExAcqResSharedWaitForExclusiveAcquiresExclusive : Uint4B
   +0x35e4 ExAcqResSharedWaitForExclusiveAcquiresShared : Uint4B
   +0x35e8 ExAcqResSharedWaitForExclusiveAcquiresSharedRecursive : Uint4B
   +0x35ec ExAcqResSharedWaitForExclusiveWaits : Uint4B
   +0x35f0 ExAcqResSharedWaitForExclusiveNotAcquires : Uint4B
   +0x35f4 ExSetResOwnerPointerExclusive : Uint4B
   +0x35f8 ExSetResOwnerPointerSharedNew : Uint4B
   +0x35fc ExSetResOwnerPointerSharedOld : Uint4B
   +0x3600 ExTryToAcqExclusiveAttempts : Uint4B
   +0x3604 ExTryToAcqExclusiveAcquires : Uint4B
   +0x3608 ExBoostExclusiveOwner : Uint4B
   +0x360c ExBoostSharedOwners : Uint4B
   +0x3610 ExEtwSynchTrackingNotificationsCount : Uint4B
   +0x3614 ExEtwSynchTrackingNotificationsAccountedCount : Uint4B
   +0x3618 Context          : Ptr32 _CONTEXT
   +0x361c ContextFlags     : Uint4B
   +0x3620 ExtendedState    : Ptr32 _XSAVE_AREA

_ETHREAD:

   +0x004 CurrentThread    : Ptr32 _KTHREAD  //当前CPU所执行线程的_ETHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD  //下一个_ETHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD

线程结构体_ETHREAD

kd> dt _ETHREAD
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x200 CreateTime       : _LARGE_INTEGER
   +0x208 ExitTime         : _LARGE_INTEGER
   +0x208 KeyedWaitChain   : _LIST_ENTRY
   +0x210 ExitStatus       : Int4B
   +0x214 PostBlockList    : _LIST_ENTRY
   +0x214 ForwardLinkShadow : Ptr32 Void
   +0x218 StartAddress     : Ptr32 Void
   +0x21c TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x21c ReaperLink       : Ptr32 _ETHREAD
   +0x21c KeyedWaitValue   : Ptr32 Void
   +0x220 ActiveTimerListLock : Uint4B
   +0x224 ActiveTimerListHead : _LIST_ENTRY
   +0x22c Cid              : _CLIENT_ID
   +0x234 KeyedWaitSemaphore : _KSEMAPHORE
   +0x234 AlpcWaitSemaphore : _KSEMAPHORE
   +0x248 ClientSecurity   : _PS_CLIENT_SECURITY_CONTEXT
   +0x24c IrpList          : _LIST_ENTRY
   +0x254 TopLevelIrp      : Uint4B
   +0x258 DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x25c CpuQuotaApc      : Ptr32 _PSP_CPU_QUOTA_APC
   +0x260 Win32StartAddress : Ptr32 Void
   +0x264 LegacyPowerObject : Ptr32 Void
   +0x268 ThreadListEntry  : _LIST_ENTRY
   +0x270 RundownProtect   : _EX_RUNDOWN_REF
   +0x274 ThreadLock       : _EX_PUSH_LOCK
   +0x278 ReadClusterSize  : Uint4B
   +0x27c MmLockOrdering   : Int4B
   +0x280 CrossThreadFlags : Uint4B
   +0x280 Terminated       : Pos 0, 1 Bit
   +0x280 ThreadInserted   : Pos 1, 1 Bit
   +0x280 HideFromDebugger : Pos 2, 1 Bit
   +0x280 ActiveImpersonationInfo : Pos 3, 1 Bit
   +0x280 Reserved         : Pos 4, 1 Bit
   +0x280 HardErrorsAreDisabled : Pos 5, 1 Bit
   +0x280 BreakOnTermination : Pos 6, 1 Bit
   +0x280 SkipCreationMsg  : Pos 7, 1 Bit
   +0x280 SkipTerminationMsg : Pos 8, 1 Bit
   +0x280 CopyTokenOnOpen  : Pos 9, 1 Bit
   +0x280 ThreadIoPriority : Pos 10, 3 Bits
   +0x280 ThreadPagePriority : Pos 13, 3 Bits
   +0x280 RundownFail      : Pos 16, 1 Bit
   +0x280 NeedsWorkingSetAging : Pos 17, 1 Bit
   +0x284 SameThreadPassiveFlags : Uint4B
   +0x284 ActiveExWorker   : Pos 0, 1 Bit
   +0x284 ExWorkerCanWaitUser : Pos 1, 1 Bit
   +0x284 MemoryMaker      : Pos 2, 1 Bit
   +0x284 ClonedThread     : Pos 3, 1 Bit
   +0x284 KeyedEventInUse  : Pos 4, 1 Bit
   +0x284 RateApcState     : Pos 5, 2 Bits
   +0x284 SelfTerminate    : Pos 7, 1 Bit
   +0x288 SameThreadApcFlags : Uint4B
   +0x288 Spare            : Pos 0, 1 Bit
   +0x288 StartAddressInvalid : Pos 1, 1 Bit
   +0x288 EtwPageFaultCalloutActive : Pos 2, 1 Bit
   +0x288 OwnsProcessWorkingSetExclusive : Pos 3, 1 Bit
   +0x288 OwnsProcessWorkingSetShared : Pos 4, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetExclusive : Pos 5, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetShared : Pos 6, 1 Bit
   +0x288 OwnsSessionWorkingSetExclusive : Pos 7, 1 Bit
   +0x289 OwnsSessionWorkingSetShared : Pos 0, 1 Bit
   +0x289 OwnsProcessAddressSpaceExclusive : Pos 1, 1 Bit
   +0x289 OwnsProcessAddressSpaceShared : Pos 2, 1 Bit
   +0x289 SuppressSymbolLoad : Pos 3, 1 Bit
   +0x289 Prefetching      : Pos 4, 1 Bit
   +0x289 OwnsDynamicMemoryShared : Pos 5, 1 Bit
   +0x289 OwnsChangeControlAreaExclusive : Pos 6, 1 Bit
   +0x289 OwnsChangeControlAreaShared : Pos 7, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetExclusive : Pos 0, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetShared : Pos 1, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetExclusive : Pos 2, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetShared : Pos 3, 1 Bit
   +0x28a TrimTrigger      : Pos 4, 2 Bits
   +0x28a Spare1           : Pos 6, 2 Bits
   +0x28b PriorityRegionActive : UChar
   +0x28c CacheManagerActive : UChar
   +0x28d DisablePageFaultClustering : UChar
   +0x28e ActiveFaultCount : UChar
   +0x28f LockOrderState   : UChar
   +0x290 AlpcMessageId    : Uint4B
   +0x294 AlpcMessage      : Ptr32 Void
   +0x294 AlpcReceiveAttributeSet : Uint4B
   +0x298 AlpcWaitListEntry : _LIST_ENTRY
   +0x2a0 CacheManagerCount : Uint4B
   +0x2a4 IoBoostCount     : Uint4B
   +0x2a8 IrpListLock      : Uint4B
   +0x2ac ReservedForSynchTracking : Ptr32 Void
   +0x2b0 CmCallbackListHead : _SINGLE_LIST_ENTRY

0x000 Tcb: _KTHREAD:

_ETHREAD结构体的第一个成员也是一个结构体:

kd> dt _KTHREAD
ntdll!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 CycleTime        : Uint8B
   +0x018 HighCycleTime    : Uint4B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr32 Void
   +0x02c StackLimit       : Ptr32 Void
   +0x030 KernelStack      : Ptr32 Void
   +0x034 ThreadLock       : Uint4B
   +0x038 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x039 Running          : UChar
   +0x03a Alerted          : [2] UChar
   +0x03c KernelStackResident : Pos 0, 1 Bit
   +0x03c ReadyTransition  : Pos 1, 1 Bit
   +0x03c ProcessReadyQueue : Pos 2, 1 Bit
   +0x03c WaitNext         : Pos 3, 1 Bit
   +0x03c SystemAffinityActive : Pos 4, 1 Bit
   +0x03c Alertable        : Pos 5, 1 Bit
   +0x03c GdiFlushActive   : Pos 6, 1 Bit
   +0x03c UserStackWalkActive : Pos 7, 1 Bit
   +0x03c ApcInterruptRequest : Pos 8, 1 Bit
   +0x03c ForceDeferSchedule : Pos 9, 1 Bit
   +0x03c QuantumEndMigrate : Pos 10, 1 Bit
   +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x03c TimerActive      : Pos 12, 1 Bit
   +0x03c SystemThread     : Pos 13, 1 Bit
   +0x03c Reserved         : Pos 14, 18 Bits
   +0x03c MiscFlags        : Int4B
   +0x040 ApcState         : _KAPC_STATE
   +0x040 ApcStateFill     : [23] UChar
   +0x057 Priority         : Char
   +0x058 NextProcessor    : Uint4B
   +0x05c DeferredProcessor : Uint4B
   +0x060 ApcQueueLock     : Uint4B
   +0x064 ContextSwitches  : Uint4B
   +0x068 State            : UChar
   +0x069 NpxState         : Char
   +0x06a WaitIrql         : UChar
   +0x06b WaitMode         : Char
   +0x06c WaitStatus       : Int4B
   +0x070 WaitBlockList    : Ptr32 _KWAIT_BLOCK
   +0x074 WaitListEntry    : _LIST_ENTRY
   +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x07c Queue            : Ptr32 _KQUEUE
   +0x080 WaitTime         : Uint4B
   +0x084 KernelApcDisable : Int2B
   +0x086 SpecialApcDisable : Int2B
   +0x084 CombinedApcDisable : Uint4B
   +0x088 Teb              : Ptr32 Void
   +0x090 Timer            : _KTIMER
   +0x0b8 AutoAlignment    : Pos 0, 1 Bit
   +0x0b8 DisableBoost     : Pos 1, 1 Bit
   +0x0b8 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x0b8 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x0b8 CalloutActive    : Pos 4, 1 Bit
   +0x0b8 ApcQueueable     : Pos 5, 1 Bit
   +0x0b8 EnableStackSwap  : Pos 6, 1 Bit
   +0x0b8 GuiThread        : Pos 7, 1 Bit
   +0x0b8 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x0b8 VdmSafe          : Pos 9, 1 Bit
   +0x0b8 UmsDispatched    : Pos 10, 1 Bit
   +0x0b8 ReservedFlags    : Pos 11, 21 Bits
   +0x0b8 ThreadFlags      : Int4B
   +0x0bc ServiceTable     : Ptr32 Void
   +0x0c0 WaitBlock        : [4] _KWAIT_BLOCK
   +0x120 QueueListEntry   : _LIST_ENTRY
   +0x128 TrapFrame        : Ptr32 _KTRAP_FRAME
   +0x12c FirstArgument    : Ptr32 Void
   +0x130 CallbackStack    : Ptr32 Void
   +0x130 CallbackDepth    : Uint4B
   +0x134 ApcStateIndex    : UChar
   +0x135 BasePriority     : Char
   +0x136 PriorityDecrement : Char
   +0x136 ForegroundBoost  : Pos 0, 4 Bits
   +0x136 UnusualBoost     : Pos 4, 4 Bits
   +0x137 Preempted        : UChar
   +0x138 AdjustReason     : UChar
   +0x139 AdjustIncrement  : Char
   +0x13a PreviousMode     : Char
   +0x13b Saturation       : Char
   +0x13c SystemCallNumber : Uint4B
   +0x140 FreezeCount      : Uint4B
   +0x144 UserAffinity     : _GROUP_AFFINITY
   +0x150 Process          : Ptr32 _KPROCESS
   +0x154 Affinity         : _GROUP_AFFINITY
   +0x160 IdealProcessor   : Uint4B
   +0x164 UserIdealProcessor : Uint4B
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE
   +0x170 SavedApcStateFill : [23] UChar
   +0x187 WaitReason       : UChar
   +0x188 SuspendCount     : Char
   +0x189 Spare1           : Char
   +0x18a OtherPlatformFill : UChar
   +0x18c Win32Thread      : Ptr32 Void
   +0x190 StackBase        : Ptr32 Void
   +0x194 SuspendApc       : _KAPC
   +0x194 SuspendApcFill0  : [1] UChar
   +0x195 ResourceIndex    : UChar
   +0x194 SuspendApcFill1  : [3] UChar
   +0x197 QuantumReset     : UChar
   +0x194 SuspendApcFill2  : [4] UChar
   +0x198 KernelTime       : Uint4B
   +0x194 SuspendApcFill3  : [36] UChar
   +0x1b8 WaitPrcb         : Ptr32 _KPRCB
   +0x194 SuspendApcFill4  : [40] UChar
   +0x1bc LegoData         : Ptr32 Void
   +0x194 SuspendApcFill5  : [47] UChar
   +0x1c3 LargeStack       : UChar
   +0x1c4 UserTime         : Uint4B
   +0x1c8 SuspendSemaphore : _KSEMAPHORE
   +0x1c8 SuspendSemaphorefill : [20] UChar
   +0x1dc SListFaultCount  : Uint4B
   +0x1e0 ThreadListEntry  : _LIST_ENTRY
   +0x1e8 MutantListHead   : _LIST_ENTRY
   +0x1f0 SListFaultAddress : Ptr32 Void
   +0x1f4 ThreadCounters   : Ptr32 _KTHREAD_COUNTERS
   +0x1f8 XStateSave       : Ptr32 _XSTATE_SAVE

+0x13a PreviousMode : Char:

先前模式,R0的程序可能是R0直接调的也有可能是R3直接调的(R3和R0有可能实现的方法不一样),用来记录调用这段代码之前是R0调用还是R3调用。

+0x128 TrapFrame : Ptr32 _KTRAP_FRAME:

当前线程的 _KTRAP_FRAME 结构体,_KTRAP_FRAME 一个线程一个。

SystemCall(KiIntSystemCall)函数调用解析

PS:当前函数为XP下的,上面结构体为Win7-x86的所以_KPCR的偏移不一定对应。

PS:在内核中,堆栈就是一个 _KTrap_Frame 结构体,所以每次push、pop或者操作esp、ebp都是在操作_KTrap_Frame 结构体,如push就是在向esp所指向 _KTrap_Frame 的位置赋值。

push 0       //保存系统空间的寄存器到 _Trap_Frame  ErrCode错误码
push ebp     //保存系统空间的寄存器到 _Trap_Frame  Ebp   //之前三环的数据保存
push ebx     //保存系统空间的寄存器到 _Trap_Frame  Ebx
push esi     //保存系统空间的寄存器到 _Trap_Frame  Esi
push edi     //保存系统空间的寄存器到 _Trap_Frame  Edi
push fs      //保存系统空间的寄存器到 _Trap_Frame  SegFs
mov ebx, 30h 
db 66h       //改变操作数的宽度为16位的
mov fs, bx   //加载FS,FS在R3指向TEB,在R0指向KDPR

push dword ptr ds:0FFDFF000h   //保存老的ExceptionList(异常链表SEH)
							  //_KPCR偏移 + 0x00 -> _NT_TIB -> ExceptionList

mov dword ptr ds:0FFDFF000h, 0FFFFffffh  //新的ExceptionList为空白
mov esi, ds:0FFDFF124h //取出当前CPU所执行线程的_KTHREAD
					   //_KPCR偏移 + 124h -> _KPRCB + 4h -> _ETHREAD + 0x00 -> _KTHREAD

push dword ptr [esi + 140h] //保存先前模式
							//_KTHREAD + 0x140 -> PreviousMode

sub esp - 48h               //提升栈顶,现在esp指向_Trap_Frame 第一个地方

mov ebx, [esp + 68h + 4]    //取出三环压入的参数
							//[esp + 68h + 4] 为 _KTrap_Frame->SegCs

and ebx, 1                  //判断原来所在的环,CS的段选择子,最低位,0环为0,1环为1

mov [esi + 140h], bl        //更新新的“先前模式”

mov ebp, esp				//ESP == EBP == _KTrap_Frame 开始位置

mov ebx, [esi + 134h]       //获取当前线程的 _KTrap_Frame

mov [ebp + 3Ch], ebx        //临时保存_KTHREAD -> _KTrap_Frame

mov [esi + 134h], ebp       //将新的_KTrap_Frame,保存到_KTHREAD中,即更新线程的_KTrap_Frame(堆栈)

cld

mov ebx, [ebp + 60h]        //获取三环的ebp _KTrap_Frame-> ebp(60h)
mov edi, [ebp + 68h]        //获取三环的eip _KTrap_Frame-> eip(68h)
mov [ebp + 0Ch], edx        //edx存储的是三环参数的指针 DbgArgPointer (0Ch)
							//在 !KiFastSystemCall中
							//mov edx, esp

mov dword ptr [ebp + 8], 0BADB0D00h

mov [ebp + 0], ebx          //3环的ebp保存到 _KTrap_Frame 开始的位置 dbgEbp调试使用

mov [ebp + 4], edi          //3环的eip保存到 _KTrap_Frame DbgRip的位置

test byte ptr [esi + 2Ch], 0FFh //判断是否是调试模式 esi + 2Ch 不为零则是调试模式,影响硬件断点

jnz Dr_Kss_a                 // 跳转调试

SystemServiceTable(系统服务表)

结构:(向三环提供的内核函数,全在这两个表里)

Ntoskrl.exe:

	系统服务表(4个参数)    函数地址表(编号==服务号)        Ntoskrl.exe
    ServiceTable    --->     函数地址1      --->          函数1
					         函数地址2	   --->           函数2
						     ..            --->           ..
					         函数地址N      --->          函数N										 
    Count
	ServiceLimit //系统服务表的大小

					       函数参数表(单位:字节)
	ArgmentTable    --->    参数个数1          
						    参数个数2
							..
							参数个数N

Win32K.sys:

	系统服务表(4个参数)    函数地址表(编号==服务号)        Win32K.sys
    ServiceTable    --->     函数地址1      --->          函数1
					         函数地址2	   --->           函数2
						     ..            --->           ..
					         函数地址N      --->          函数N										 
    Count
	ServiceLimit //系统服务表的大小

					       函数参数表(单位:字节)
	ArgmentTable    --->    参数个数1          
						    参数个数2
							..
							参数个数N

当eax的第12位为0查找 Ntoskrl.exe 表。(eax保存函数的调用编号)

当eax的第12位为1查找 Win32K.sys 表。

SSDT(系统服务描述符表)

SSDT就是一个导出的全局变量,这个全局变量里面包含了系统服务表。windows内核导出了一个全局变量KeServiceDescriptorTableKeServiceDescriptorTable只提供了Ntoskrl.exe的系统服务表,没有提供 Win32K.sys的。

KeServiceDescriptorTableShadow 提供了Win32K.sys的,但是并不是每一个进程都会挂物理页,只有当使用了Win32K.sys里的函数后才会挂上内存。

导出的,声明一下就可以直接使用:

kd> dd KeServiceDescriptorTable //SSDT

未导出的:

kd> dd KeServiceDescriptorTableShadow //SSDT Shadow

这两张表一直都存在,能否使用主要看是挂了这两张表的物理页。(Ntoskrl.exe和Win32K.sys系统服务表)

KeServiceDescriptorTable

结构:

kd> dd KeServiceDescriptorTable
83f7f9c0  83e93d9c 00000000 00000191 83e943e4  //函数地址表、  、多少个函数、 参数(系统服务表 Ntoskrl.exe)
83f7f9d0  00000000 00000000 00000000 00000000  //函数地址表、  、多少个函数、 参数(系统服务表 Win32K.sys)
83f7f9e0  83ef26af 00000000 0193b6a8 000000bb  //函数地址表、  、多少个函数、 参数(系统服务表)
83f7f9f0  00000011 00000100 5385d2ba d717548f  
83f7fa00  83e93d9c 00000000 00000191 83e943e4
83f7fa10  93ea6000 00000000 00000339 93ea702c
83f7fa20  00000000 00000000 83f7fa24 00000340
83f7fa30  00000340 855e6508 00000007 00000000

SSDT有4个成员,后面三个成员一般为空的,每个成员分为函数地址表、  、多少个函数、 参数。

找到 83e93d9c 地址所指向的值就是 函数表基址,

kd> dd 83ebed9c 
83ebed9c  840bac28 83f0140d 8404ab68 83e6588a
83ebedac  840bc4ff 83f3e3fa 8412cb05 8412cb4e
83ebedbc  8403f3bd 84146368 841475c1 84035b95
83ebedcc  840c6b35 8411f963 84072a56 840426cc
83ebeddc  83fd8928 84111898 8402914e 8406ba62
83ebedec  840b7df1 84019238 840b71fe 84036c0c
83ebedfc  840c85bc 8403928f 840c839c 840c0afc
83ebee0c  8404b0f0 8410c657 840bdec9 840c87ee

KeServiceDescriptorTable查看函数:

kd> dd 83ebed9c + BA * 4  //BA 为函数编号,83ebed9c是函数表基址
83e94084  83fe60f9 840780e2 83fef4b2 83ff0f07
83e94094  840289dc 8407afff 84068b37 83f940c7
83e940a4  84080674 83ffc0c6 8409d977 84064b6f
83e940b4  84074d87 8408f2e4 84068c4e 84120e0f
83e940c4  841096f1 8410a989 83ffa506 84057970
83e940d4  841092a2 84108fc2 8410935a 8410907a
83e940e4  8400d93f 83fdcf60 83ff7a51 8410b0e4
83e940f4  8410b1aa 84059403 840aa5a7 8406e9a1

kd> u 83fe60f9 
nt!NtOpenKeyTransactedEx:
83fe60f9 8bff            mov     edi,edi
83fe60fb 55              push    ebp
83fe60fc 8bec            mov     ebp,esp
83fe60fe 51              push    ecx
83fe60ff 51              push    ecx
83fe6100 64a124010000    mov     eax,dword ptr fs:[00000124h]
83fe6106 8a803a010000    mov     al,byte ptr [eax+13Ah]
83fe610c 6a00            push    0

查看参数:

kd> db 83e943e4 + BA   //BA 为函数编号,83e943e4是参数基址
83e9449e  14 0c 30 10 10 0c 10 14-0c 0c 0c 0c 10 10 14 0c  ..0.............
83e944ae  14 18 0c 14 08 08 08 08-0c 14 18 10 0c 14 08 08  ................
83e944be  08 08 08 08 04 2c 1c 08-24 14 08 14 14 14 14 14  .....,..$.......
83e944ce  14 14 14 14 14 14 14 04-08 14 14 14 18 14 14 08  ................
83e944de  10 08 00 24 14 18 14 14-0c 10 14 10 18 04 14 0c  ...$............
83e944ee  18 18 14 14 18 0c 18 24-24 08 18 14 08 04 04 14  .......$$.......
83e944fe  04 10 08 0c 04 14 18 08-08 08 0c 0c 08 10 14 08  ................
83e9450e  08 0c 08 0c 0c 04 08 08-08 08 08 08 0c 0c 24 00  ..............$.

14转化为10进制为20,一个参数4个字节,所以函数NtOpenKeyTransactedEx接受5个参数。

调用系统服务表(驱动程序):

typedef struct _KSYSTEM_SERVICE_TABLE
{

   PULONG ServiceTableBase;         //函数地址表基地址
   PULONG ServicrCounterTableBase;  //SSDT函数被调用的次数
   ULONG  NumberOfService;          //函数的个数
   PULONG ParamTableBase;           //函数参数表基地址

} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;


typedef struct _KSERVICE_TABLE_DESCRIPTOR
{

	KSYSTEM_SERVICE_TABLE ntoskrnl;   //Ntoskrl.exe 的函数
	KSYSTEM_SERVICE_TABLE win32k;     //Win32K.sys 的函数
	KSYSTEM_SERVICE_TABLE notUsed1;          
	KSYSTEM_SERVICE_TABLE notUsed1;          

} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;


//KeServiceDescriptorTable是ntoskrnl.exe所导出的全局变量 声明一下就可以直接使用

extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

KeServiceDescriptorTableShadow

结构:

kd> dd KeServiceDescriptorTableShadow
83f7fa00  83e93d9c 00000000 00000191 83e943e4 //函数地址表、  、多少个函数、 参数(系统服务表 Ntoskrl.exe)
83f7fa10  93ea6000 00000000 00000339 93ea702c //函数地址表、  、多少个函数、 参数(系统服务表 Win32K.sys)
83f7fa20  00000000 00000000 83f7fa24 00000340
83f7fa30  00000340 855e6508 00000007 00000000
83f7fa40  855e6440 855e7f78 855e6378 855e7040
83f7fa50  00000000 855e7eb0 00000000 00000000
83f7fa60  83e8d809 83e9aeed 83ea93a5 00000003
83f7fa70  85535000 85536000 00000120 ffffffff

kd> dd 93ea6000  //没有使用Win32K.sys里的函数,所以没有挂数据
93ea6000  ???????? ???????? ???????? ????????
93ea6010  ???????? ???????? ???????? ????????
93ea6020  ???????? ???????? ???????? ????????
93ea6030  ???????? ???????? ???????? ????????
93ea6040  ???????? ???????? ???????? ????????
93ea6050  ???????? ???????? ???????? ????????
93ea6060  ???????? ???????? ???????? ????????
93ea6070  ???????? ???????? ???????? ????????

执行一个有窗口的程序后:

kd> !process 0 0 
**** NT ACTIVE PROCESS DUMP ****

PROCESS 85843030  SessionId: 1  Cid: 0284    Peb: 7ffd7000  ParentCid: 0504
DirBase: 3f2b5440  ObjectTable: 8dfbc4c8  HandleCount:  57.
Image: InStallDriver.exe

附加进程:

kd> .process 85843030  
Implicit process is now 85843030
WARNING: .cache forcedecodeuser is not enabled

再次查看 KeServiceDescriptorTableShadow的 Win32K.sys:

kd> dd 93ea6000 
93ea6000  93e33d37 93e4bc23 93ca71ac 93e42c5d
93ea6010  93e4d369 93e34554 93e345e8 93d5dad1
93ea6020  93e4cb94 93d11965 93d11882 93e4eead
93ea6030  93e4d085 93e4bc97 93d528cb 93e4cfd8
93ea6040  93e4fc51 93e4bb9e 93d84a88 93e4d10f
93ea6050  93e4f645 93d12069 93db88bf 93ddc7bc
93ea6060  93e5063d 93e45659 93d7358b 93e4d075
93ea6070  93dc76c3 93e4f508 93e4f8d2 93d4cf2e

KeServiceDescriptorTableShadow提供了Win32K.sys的,但是并不是每一个进程都会挂物理页,只有当使用了Win32K.sys里的函数后才会挂上内存。

Hook NtTerminateProcess实现禁止关闭进程

Hook NtTerminateProcess实现禁止关闭进程

总结

debug:

!vtop + CR3 + 线性地址 = 物理地址