简介
在进程由用户态进入内核态的过程中,发生了 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