Bootstrap

R0-R3 现场保护(_KTrap_Frame/_KPCR/_ETHREAD)—— 分析内核函数KiSystemService

简介

在进程由用户态进入内核态的过程中,发生了 ESP/SS/EIP/CS 的切换。因此,在进程权限切换的工程中,必然要进行寄存器的现场保护。

这里,要使用到3个内核结构体:_KTrap_Frame/_KPCR/_ETHREAD

_KTrap_Frame

每个线程在内核中都有一个 _KTrap_Frame 结构体,用于操作系统对线程的管理,该结构体时操作系统进行维护的。


_KTrap_Frame 的结构如下:

kd> dt _KTrap_Frame	
nt!_KTRAP_FRAME
   //调试信息
   +0x000 DbgEbp           : Uint4B	
   +0x004 DbgEip           : Uint4B
   +0x008 DbgArgMark       : Uint4B
   +0x00c DbgArgPointer    : Uint4B	//用于存放3环的参数指针
   +0x010 TempSegCs        : Uint4B
   +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
   +0x064 ErrCode          : Uint4B	// 中断错误码, 由CPU决定是否填充
       								// 如果CPU填充, 则不需要手动填充; 否则, 需手动填充
   /*
	   中断时, 依次会向0环堆栈中压入5个参数
	   保存3环被中断处的 EIP、CS、fs
	   若发生权限切换, 则要保存旧堆栈的ESP、SS
   */
   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B	
   +0x078 HardwareSegSs    : Uint4B
   // 虚拟8086模式下使用, 变换需要保存段寄存器
   +0x07c V86Es            : Uint4B		//进入0环, esp将会指向0x07c
   +0x080 V86Ds            : Uint4B
   +0x084 V86Fs            : Uint4B
   +0x088 V86Gs            : Uint4B

_KPCR

KPCR ,即 CPU 控制区( Processor Control Region ),在内存中存储 CPU 的控制信息。CPU 有几个核心数,就有几个 _KPCR


_KPCR 的结构体如下:

kd> dt _KPCR
nt!_KPCR
   +0x000 NtTib            : _NT_TIB	// _NT_TIB结构体
   /*
   		kd> dt _NT_TIB
        nt!_NT_TIB
           +0x000 ExceptionList    : 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	//结构体指针 指向自己
   */
   +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 DebugActive      : 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		// _KPRCB结构体
       
   // -------------------------------------------------
       
kd> dt _KPRCB
nt!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD	//当前CPU所执行线程的_ETHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD	//下一个_ETHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD	//当所以线程都执行完了CPU就可以执行这个
   +0x010 Number           : Char	//CPU编号
   +0x011 Reserved         : Char
   +0x012 BuildType        : Uint2B
   +0x014 SetMember        : Uint4B
   +0x018 CpuType          : Char
   +0x019 CpuID            : Char
   +0x01a CpuStep          : Uint2B	//CPU子版本号
   +0x01c ProcessorState   : _KPROCESSOR_STATE	//CPU状态
   +0x33c KernelReserved   : [16] Uint4B
   +0x37c HalReserved      : [16] Uint4B
   +0x3bc PrcbPad0         : [92] UChar
   +0x418 LockQueue        : [16] _KSPIN_LOCK_QUEUE
   +0x498 PrcbPad1         : [8] UChar
   +0x4a0 NpxThread        : Ptr32 _KTHREAD	//Npx浮点处理器  最后一次用过浮点的线程
   +0x4a4 InterruptCount   : Uint4B	//中断计数 统计信息 没什么实际意义 自己调试用的
   +0x4a8 KernelTime       : Uint4B	//统计信息
   +0x4ac UserTime         : Uint4B	//统计信息
   +0x4b0 DpcTime          : Uint4B	//统计信息
   +0x4b4 DebugDpcTime     : Uint4B	//统计信息
   +0x4b8 InterruptTime    : Uint4B	//统计信息
   +0x4bc AdjustDpcThreshold : Uint4B
   +0x4c0 PageColor        : Uint4B
   +0x4c4 SkipTick         : Uint4B
   +0x4c8 MultiThreadSetBusy : UChar
   +0x4c9 Spare2           : [3] UChar
   +0x4cc ParentNode       : Ptr32 _KNODE
   +0x4d0 MultiThreadProcessorSet : Uint4B
   +0x4d4 MultiThreadSetMaster : Ptr32 _KPRCB
   +0x4d8 ThreadStartCount : [2] Uint4B
   +0x4e0 CcFastReadNoWait : Uint4B
   +0x4e4 CcFastReadWait   : Uint4B
   +0x4e8 CcFastReadNotPossible : Uint4B
   +0x4ec CcCopyReadNoWait : Uint4B
   +0x4f0 CcCopyReadWait   : Uint4B
   +0x4f4 CcCopyReadNoWaitMiss : Uint4B
   +0x4f8 KeAlignmentFixupCount : Uint4B
   +0x4fc KeContextSwitches : Uint4B
   +0x500 KeDcacheFlushCount : Uint4B
   +0x504 KeExceptionDispatchCount : Uint4B
   +0x508 KeFirstLevelTbFills : Uint4B
   +0x50c KeFloatingEmulationCount : Uint4B
   +0x510 KeIcacheFlushCount : Uint4B
   +0x514 KeSecondLevelTbFills : Uint4B
   +0x518 KeSystemCalls    : Uint4B
   +0x51c SpareCounter0    : [1] Uint4B
   +0x520 PPLookasideList  : [16] _PP_LOOKASIDE_LIST
   +0x5a0 PPNPagedLookasideList : [32] _PP_LOOKASIDE_LIST
   +0x6a0 PPPagedLookasideList : [32] _PP_LOOKASIDE_LIST
   +0x7a0 PacketBarrier    : Uint4B
   +0x7a4 ReverseStall     : Uint4B
   +0x7a8 IpiFrame         : Ptr32 Void
   +0x7ac PrcbPad2         : [52] UChar
   +0x7e0 CurrentPacket    : [3] Ptr32 Void
   +0x7ec TargetSet        : Uint4B
   +0x7f0 WorkerRoutine    : Ptr32     void 
   +0x7f4 IpiFrozen        : Uint4B
   +0x7f8 PrcbPad3         : [40] UChar
   +0x820 RequestSummary   : Uint4B
   +0x824 SignalDone       : Ptr32 _KPRCB
   +0x828 PrcbPad4         : [56] UChar
   +0x860 DpcListHead      : _LIST_ENTRY
   +0x868 DpcStack         : Ptr32 Void
   +0x86c DpcCount         : Uint4B
   +0x870 DpcQueueDepth    : Uint4B
   +0x874 DpcRoutineActive : Uint4B
   +0x878 DpcInterruptRequested : Uint4B
   +0x87c DpcLastCount     : Uint4B
   +0x880 DpcRequestRate   : Uint4B
   +0x884 MaximumDpcQueueDepth : Uint4B
   +0x888 MinimumDpcRate   : Uint4B
   +0x88c QuantumEnd       : Uint4B
   +0x890 PrcbPad5         : [16] UChar
   +0x8a0 DpcLock          : Uint4B
   +0x8a4 PrcbPad6         : [28] UChar
   +0x8c0 CallDpc          : _KDPC
   +0x8e0 ChainedInterruptList : Ptr32 Void
   +0x8e4 LookasideIrpFloat : Int4B
   +0x8e8 SpareFields0     : [6] Uint4B
   +0x900 VendorString     : [13] UChar
   +0x90d InitialApicId    : UChar
   +0x90e LogicalProcessorsPerPhysicalProcessor : UChar	//每个物理处理器有几个逻辑处理器
   +0x910 MHz              : Uint4B	//频率 
   +0x914 FeatureBits      : Uint4B
   +0x918 UpdateSignature  : _LARGE_INTEGER
   +0x920 NpxSaveArea      : _FX_SAVE_AREA
   +0xb30 PowerState       : _PROCESSOR_POWER_STATE

_ETHREAD

_ETHREAD 结构体是线程相关的结构体。


_ETHREAD 的构体如下:

kd> dt _ETHREAD
nt!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   /*
   	kd> dt _KTHREAD
    nt!_KTHREAD
       +0x000 Header           : _DISPATCHER_HEADER
       +0x010 MutantListHead   : _LIST_ENTRY
       +0x018 InitialStack     : Ptr32 Void
       +0x01c StackLimit       : Ptr32 Void
       +0x020 Teb              : Ptr32 Void
       +0x024 TlsArray         : Ptr32 Void
       +0x028 KernelStack      : Ptr32 Void
       +0x02c DebugActive      : UChar	//是否处于调试状态
       +0x02d State            : UChar
       +0x02e Alerted          : [2] UChar
       +0x030 Iopl             : UChar
       +0x031 NpxState         : UChar
       +0x032 Saturation       : Char
       +0x033 Priority         : Char
       +0x034 ApcState         : _KAPC_STATE
       +0x04c ContextSwitches  : Uint4B
       +0x050 IdleSwapBlock    : UChar
       +0x051 Spare0           : [3] UChar
       +0x054 WaitStatus       : Int4B
       +0x058 WaitIrql         : UChar
       +0x059 WaitMode         : Char
       +0x05a WaitNext         : UChar
       +0x05b WaitReason       : UChar
       +0x05c WaitBlockList    : Ptr32 _KWAIT_BLOCK
       +0x060 WaitListEntry    : _LIST_ENTRY
       +0x060 SwapListEntry    : _SINGLE_LIST_ENTRY
       +0x068 WaitTime         : Uint4B
       +0x06c BasePriority     : Char
       +0x06d DecrementCount   : UChar
       +0x06e PriorityDecrement : Char
       +0x06f Quantum          : Char
       +0x070 WaitBlock        : [4] _KWAIT_BLOCK
       +0x0d0 LegoData         : Ptr32 Void
       +0x0d4 KernelApcDisable : Uint4B
       +0x0d8 UserAffinity     : Uint4B
       +0x0dc SystemAffinityActive : UChar
       +0x0dd PowerState       : UChar
       +0x0de NpxIrql          : UChar
       +0x0df InitialNode      : UChar
       +0x0e0 ServiceTable     : Ptr32 Void
       +0x0e4 Queue            : Ptr32 _KQUEUE
       +0x0e8 ApcQueueLock     : Uint4B
       +0x0f0 Timer            : _KTIMER
       +0x118 QueueListEntry   : _LIST_ENTRY
       +0x120 SoftAffinity     : Uint4B
       +0x124 Affinity         : Uint4B
       +0x128 Preempted        : UChar
       +0x129 ProcessReadyQueue : UChar
       +0x12a KernelStackResident : UChar
       +0x12b NextProcessor    : UChar
       +0x12c CallbackStack    : Ptr32 Void
       +0x130 Win32Thread      : Ptr32 Void
       +0x134 TrapFrame        : Ptr32 _KTRAP_FRAME
       +0x138 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
       +0x140 PreviousMode     : Char	//先前模式,记录先前是0环,还是3环
       +0x141 EnableStackSwap  : UChar
       +0x142 LargeStack       : UChar
       +0x143 ResourceIndex    : UChar
       +0x144 KernelTime       : Uint4B
       +0x148 UserTime         : Uint4B
       +0x14c SavedApcState    : _KAPC_STATE
       +0x164 Alertable        : UChar
       +0x165 ApcStateIndex    : UChar
       +0x166 ApcQueueable     : UChar
       +0x167 AutoAlignment    : UChar
       +0x168 StackBase        : Ptr32 Void
       +0x16c SuspendApc       : _KAPC
       +0x19c SuspendSemaphore : _KSEMAPHORE
       +0x1b0 ThreadListEntry  : _LIST_ENTRY
       +0x1b8 FreezeCount      : Char
       +0x1b9 SuspendCount     : Char
       +0x1ba IdealProcessor   : UChar
       +0x1bb DisableBoost     : UChar
   */
   +0x1c0 CreateTime       : _LARGE_INTEGER
   +0x1c0 NestedFaultCount : Pos 0, 2 Bits
   +0x1c0 ApcNeeded        : Pos 2, 1 Bit
   +0x1c8 ExitTime         : _LARGE_INTEGER
   +0x1c8 LpcReplyChain    : _LIST_ENTRY
   +0x1c8 KeyedWaitChain   : _LIST_ENTRY
   +0x1d0 ExitStatus       : Int4B
   +0x1d0 OfsChain         : Ptr32 Void
   +0x1d4 PostBlockList    : _LIST_ENTRY
   +0x1dc TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x1dc ReaperLink       : Ptr32 _ETHREAD
   +0x1dc KeyedWaitValue   : Ptr32 Void
   +0x1e0 ActiveTimerListLock : Uint4B
   +0x1e4 ActiveTimerListHead : _LIST_ENTRY
   +0x1ec Cid              : _CLIENT_ID
   +0x1f4 LpcReplySemaphore : _KSEMAPHORE
   +0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
   +0x208 LpcReplyMessage  : Ptr32 Void
   +0x208 LpcWaitingOnPort : Ptr32 Void
   +0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
   +0x210 IrpList          : _LIST_ENTRY
   +0x218 TopLevelIrp      : Uint4B
   +0x21c DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x220 ThreadsProcess   : Ptr32 _EPROCESS
   +0x224 StartAddress     : Ptr32 Void
   +0x228 Win32StartAddress : Ptr32 Void
   +0x228 LpcReceivedMessageId : Uint4B
   +0x22c ThreadListEntry  : _LIST_ENTRY
   +0x234 RundownProtect   : _EX_RUNDOWN_REF
   +0x238 ThreadLock       : _EX_PUSH_LOCK
   +0x23c LpcReplyMessageId : Uint4B
   +0x240 ReadClusterSize  : Uint4B
   +0x244 GrantedAccess    : Uint4B
   +0x248 CrossThreadFlags : Uint4B
   +0x248 Terminated       : Pos 0, 1 Bit
   +0x248 DeadThread       : Pos 1, 1 Bit
   +0x248 HideFromDebugger : Pos 2, 1 Bit
   +0x248 ActiveImpersonationInfo : Pos 3, 1 Bit
   +0x248 SystemThread     : Pos 4, 1 Bit
   +0x248 HardErrorsAreDisabled : Pos 5, 1 Bit
   +0x248 BreakOnTermination : Pos 6, 1 Bit
   +0x248 SkipCreationMsg  : Pos 7, 1 Bit
   +0x248 SkipTerminationMsg : Pos 8, 1 Bit
   +0x24c SameThreadPassiveFlags : Uint4B
   +0x24c ActiveExWorker   : Pos 0, 1 Bit
   +0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit
   +0x24c MemoryMaker      : Pos 2, 1 Bit
   +0x250 SameThreadApcFlags : Uint4B
   +0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit
   +0x250 LpcExitThreadCalled : Pos 1, 1 Bit
   +0x250 AddressSpaceOwner : Pos 2, 1 Bit
   +0x254 ForwardClusterOnly : UChar
   +0x255 DisablePageFaultClustering : UChar

分析内核函数KiSystemService

分析内核主程序 ntoskenl.exe 如下:

在这里插入图片描述


进入操作系统的 IDT 表,如下:

在这里插入图片描述


汇编代码分析如下:

.text:00407631 ; =============== S U B R O U T I N E =======================================
.text:00407631
.text:00407631
.text:00407631 _KiSystemService proc near              ; CODE XREF: ZwAcceptConnectPort(x,x,x,x,x,x)+C↑p
.text:00407631                                         ; ZwAccessCheck(x,x,x,x,x,x,x,x)+C↑p ...
.text:00407631
.text:00407631 arg_0           = dword ptr  4
.text:00407631
.text:00407631                 push    0
.text:00407633                 push    ebp             ; push 0, 错误码占位
.text:00407634                 push    ebx             ; 保存0环寄存器现场
.text:00407635                 push    esi
.text:00407636                 push    edi
.text:00407637                 push    fs
.text:00407639                 mov     ebx, 30h
.text:0040763E                 mov     fs, ebx   ; 更新0环fs, 此时fs段寄存器的段描述符为 ffc093df`f0000001
.text:0040763E                                         ; 指向地址ffdff000, 指向当前CPU的_KPCR结构体
.text:00407640                 push    dword ptr ds:0FFDFF000h ; 保存旧的ExceptionList
.text:00407646                 mov     dword ptr ds:0FFDFF000h, 0FFFFFFFFh ; 更新ExceptionList
.text:00407650                 mov     esi, ds:0FFDFF124h ; 当前CPU所执行线程的_ETHREAD指针
.text:00407656                 push    dword ptr [esi+140h] ; PreviousMode, 记录先前的权限级别
.text:0040765C                 sub     esp, 48h        ; 将ESP指向DbgEbp
.text:0040765F                 mov     ebx, [esp+68h+4h] ; EBX指向SegCs
.text:00407663                 and     ebx, 1          ; 判断原CS的权限级别
.text:00407666                 mov     [esi+140h], bl  ; 新的先前模式
.text:0040766C                 mov     ebp, esp        ; 更新EBP
.text:0040766E                 mov     ebx, [esi+134h] ; 获取新线程的TrapFrame
.text:00407674                 mov     [ebp+3Ch], ebx  ; 临时存储旧的TrapFrame
.text:00407677                 mov     [esi+134h], ebp ; 更新_Trap_Frame
.text:0040767D                 cld
.text:0040767E                 mov     ebx, [ebp+60h]  ; 3环EBP
.text:00407681                 mov     edi, [ebp+68h]  ; 3环EIP
.text:00407684                 mov     [ebp+0Ch], edx  ; 3环参数指针
.text:00407687                 mov     dword ptr [ebp+8], 0BADB0D00h
.text:0040768E                 mov     [ebp+0], ebx
.text:00407691                 mov     [ebp+4], edi
.text:00407694                 test    byte ptr [esi+2Ch], 0FFh ; DeBugActive,标识当前线程是否处于调试状态
.text:00407694                                         ; 如果处于调试状态,跳转
.text:00407698                 jnz     Dr_kss_a
.text:0040769E
.text:0040769E loc_40769E:                             ; CODE XREF: Dr_kss_a+10↑j
.text:0040769E                                         ; Dr_kss_a+7C↑j
.text:0040769E                 sti                     ; 关闭中断
.text:0040769F                 jmp     loc_407781      ; 取出3环传递的系统号
.text:0040769F _KiSystemService endp
;