概述
双机调试配置参看我的另一篇文章[原创]内核学习-双机调试环境搭建-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com,基于xp sp3系统
系统调用的学习
分析ReadProcessMemory了解系统调用
一:分析ReadProcessMemory
ida打开kernel32.dll(ReadProcessMemory函数在这个dll里)
参数压栈,call NTReadVirtualMemory,跳转至loc_7C802204
loc_7C802204调用了sub_7C8093FD
sub_7C8093FD内部调用了另一个函数RtlNtStatusToDosError
这个函数的作用是设置错误号
从sub_7C8093FD出来后,将eax清零,跳转到loc_7C8021F9
返回
当调用ReadProcessMemory失败时,返回结果为0,若NtReadVirtualMemory返回结果大于等于0,返回结果为1
ReadProcessMemory函数在kernel32.dll中只是调用了NtReadVirtualMemory,然后设置了返回值
二:分析NtReadVirtualMemory
在ntdll.dll中,Ntdll.dll
:大多数API都会通过这个DLL进入内核(0环)
.text:7C92D9E0 mov eax, 0BAh 系统调用号,对应操作系统内核中某个函数的编号
.text:7C92D9E5 mov edx, 7FFE0300h 函数地址,该函数决定了我们用什么方式进0环
.text:7C92D9EA call dword ptr [edx]
.text:7C92D9EC retn 14h
真正读取进程内存的函数在0环实现,我们所用的函数只是系统提供给我们的函数接口
三:进入0环的两种方式
基本概念:
_KUSER_SHARED_DATA结构体
nt!_KUSER_SHARED_DATA
+0x000 TickCountLow : 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] Uint2B
+0x238 MaxStackTraceDepth : Uint4B
+0x23c CryptoExponent : Uint4B
+0x240 TimeZoneId : Uint4B
+0x244 Reserved2 : [8] 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
+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
+0x2f0 TraceLogging : Uint4B
+0x2f8 TestRetInstruction : Uint8B
+0x300 SystemCall : ntdll.dll!KiFastSystemCall()/ ntdll.dll!KiIntSystemCall()
+0x304 SystemCallReturn : Uint4B
+0x308 SystemCallPad : [3] Uint8B
+0x320 TickCount : _KSYSTEM_TIME
+0x320 TickCountQuad : Uint8B
+0x330 Cookie : Uint4B
该数据结构是三环与零环的共享内存。
它们使用固定的地址值映射,_KUSER_SHARED_DATA结构区域在User层和Kernel层地址分别为:
User
:0x7ffe0000
Kernnel
:0xffdf0000
指向的是同一个物理页,但是在user层是只读,在kernel层是可读可写的。
此结构体由操作系统负责初始化,其偏移 0x300 处有一个 SystemCall 属性,是个函数指针。
sysenter/sysexit指令
sysenter 指令可用于特权级 3 的用户代码调用特权级 0 的系统内核代码,而 SYSEXIT 指令则用于特权级 0 的系统代码返回用户空间中。sysenter 指令可以在 3,2,1 这三个特权级别调用(Linux 中只用到了特权级 3),而 SYSEXIT 指令只能从特权级 0 调用。
描述:当操作系统初始化时,其会通过CPUID指令查询当前CPU是否支持快速调用,如果支持则这里填写通过快速调用进入零环,否则通过中断进入零环。
可以设置eax=1,执行cpuid指令,处理器的特征信息被放在ecx和edx寄存器中,其中edx包含了一个SEP位(第11位),该位指明了当前处理器知否支持sysenter/sysexit指令,SEP=1,说明当前CPU支持 sysenter / sysexit 指令。以此来自行查看前处理器是否支持sysenter/sysexit指令。
当CPU支持快读调用,SystemCall 指向 ntdll.dll!KiFastSystemCall()
当CPU不支持快速调用,SystemCall 指向 ntdll.dll!KiIntSystemCall()
R3------>R0
- CS的权限由3变为0,意味着需要新的CS
- SS与CS的权限永远一致,需要新的SS
- 权限发生切换的时候,堆栈也一定会切换,需要新的ESP
- 进0环后会修改EIP
(1)int 2e
分析KiIntSystemCall
所有的API进内核时,统一的中断号为0x2e
在执行KiIntSystemCall函数前,系统调用号已被写入EAX。
分析 INT 0x2E
在IDT表中找到0x2E号门描述符:2E 右移3位(或者乘8)得到 0x170,加上 r idtr
获取的IDT基址,可以计算出 2E号中断对应的描述符:8053ee000008e481
门描述符:8053ee00
0008e481
指向地址:8053e481
CS:门描述符的段选择子部分(0008)(系统代码段)
查看eip
kd> u 8053e481
TSS描述符是 80008b04`200020ab,所以TSS的地址就是 80042000
所以ESP = 8054acf0, SS= 0010
小结:
- 固定中断号为0x2E
- CS/EIP由门描述符提供,ESP/SS由TSS提供
- 进入0环后执行的内核函数:NT!KiSystemService
进0环后,原来的寄存器存在哪里?
进入0环后执行的内核函数NT!KiSystemService
(2)sysenter
mov edx,esp 三环栈顶值传给edx,此时eax中已经是系统调用号
sysenter指令 寄存器数据传递
sysenter 是从 MSR 寄存器里读取 CS,ESP,EIP(MSR寄存器里的值,则是系统启动时就已经填好)
相关的MSR寄存器的值
可以通过RDMSR/WRMST来进行读写(操作系统使用WRMST写该寄存器):
kd> rdmsr 174 //查看CS
kd> rdmsr 175 //查看ESP
kd> rdmsr 176 //查看EIP
查看eip所在地址的反汇编:
SS
= IA32_SYSENTER_CS + 8
四:小结
3环进0环的两种方式,分别是中断门和快速调用,CPU支持快速调用,那么_KUSER_SHARED_DATA 结构体的 SystemCall 属性指向的函数是 KiFastSystemCall,执行 KiFastSystemCall,使用快速调用的方式进0环;如果不支持,那么SystemCall 指向的函数是KiIntSystemCall,执行 KiIntSystemCall,使用中断门的方式进0环。
KiFastSystemCall:KiIntSystemCall:
两个函数的共同点:
1.更改4个寄存器:SS CS EIP ESP,进入0环。
两个函数的区别:
1.快速调用不需要访问内存,而中断门需要读TSS和IDT表
2.int 0x2e 和 sysenter 指令进0环后,分别调用了两个函数 KiSystemService 和 KiFastCallEntry。
五:填充_KTRAP_FRAME结构体
中断门
int 0x2e进0环后调用函数KiSystemService
分析KiSystemService
_Trap_Frame 和0环栈密切相关。用户定义中断进0环,涉及提权时,CPU会把5个寄存器的值压入0环堆栈。EIP CS SS EFLAG ESP
线程切换时会修改TSS表,确保每个线程执行时,TSS里的ESP,SS都对应当前线程。
基本概念:
_KTRAP_FRAME
nt!_KTRAP_FRAME
+0x000 DbgEbp : Uint4B
+0x004 DbgEip : Uint4B
+0x008 DbgArgMark : Uint4B
+0x00c DbgArgPointer : Uint4B
+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
+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
_KPCR
KPCR(Processor Control Region)是CPU控制区的意思,每个CPU都有一个KPCR结构。描述cpu状态
nt!_KPCR
+0x000 NtTib : _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
_NT_TIB
主要存储了SEH结构化异常链表和一个指向自己的指针。
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
_KPRCB
nt!_KPRCB
+0x000 MinorVersion : Uint2B
+0x002 MajorVersion : Uint2B
+0x004 CurrentThread : Ptr32 _KTHREAD
+0x008 NextThread : Ptr32 _KTHREAD
+0x00c IdleThread : Ptr32 _KTHREAD
+0x010 Number : Char
+0x011 Reserved : Char
+0x012 BuildType : Uint2B
+0x014 SetMember : Uint4B
+0x018 CpuType : Char
+0x019 CpuID : Char
+0x01a CpuStep : Uint2B
+0x01c ProcessorState : _KPROCESSOR_STATE
+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
+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
存储的是线程相关的信息
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
+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
_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
+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
KiSystemService 函数如何初始化 _KTRAP_FRAME
中断门进0环后,新的ESP指向偏移 0x068(Eip)处!!!
通过中断门的方式进入内核的时候,SS CS EIP ESP EFLAG的值已经存在 _KTRAP_FRAME中了。
.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)+Cp
.text:00407631 ; ZwAccessCheck(x,x,x,x,x,x,x,x)+Cp ...
.text:00407631
.text:00407631 var_104 = dword ptr -104h
.text:00407631 var_100 = dword ptr -100h
.text:00407631 var_D0 = dword ptr -0D0h
.text:00407631 var_CC = dword ptr -0CCh
.text:00407631 var_C8 = dword ptr -0C8h
.text:00407631 var_B0 = dword ptr -0B0h
.text:00407631 var_AC = dword ptr -0ACh
.text:00407631 var_A8 = dword ptr -0A8h
.text:00407631 var_A3 = byte ptr -0A3h
.text:00407631 var_73 = byte ptr -73h
.text:00407631 arg_0 = dword ptr 4
.text:00407631 arg_64 = dword ptr 68h
.text:00407631 arg_69 = byte ptr 6Dh
.text:00407631
.text:00407631 push 0 ; _KTRAP_FRAME 0x064 ErrCode 错误码置为0;
.text:00407633 push ebp ; 保存3环寄存器的值
.text:00407634 push ebx
.text:00407635 push esi
.text:00407636 push edi
.text:00407637 push fs
.text:00407639 mov ebx, 30h ;30h段选择子 0011 0000:索引为6,GDT表,运行级别为0环
.text:0040763E mov fs, bx ; 设置 fs 为 0x30
.text:0040763E ; 根据段选择子查GDT表得到对应的段描述符 ffc093df`f0000001
.text:0040763E ; fs.base = ffdff000,指向当前CPU的KPCR结构
.text:00407640 assume fs:nothing
.text:00407640 push dword ptr ds:0FFDFF000h ; 保存旧的 ExceptionList,然后把新的清成-1,_KPCR+0X00->_NT_TIB->ExecotionList
.text:00407646 mov dword ptr ds:0FFDFF000h, 0FFFFFFFFh
.text:00407650 mov esi, ds:0FFDFF124h ; esi 指向 CurrentThread(0FFDFF124h:_KPCR+0x124=_KPCR+0x120+0x004->_KPRCB+0X004->CurrentThread)
.text:00407656 push dword ptr [esi+140h] ; 保存 CurrentThread.PreviousMode
.text:00407656 ; PreviousMode = 0 表示从0环调用过来
.text:00407656 ; PreviousMode != 0 表示从3环调用过来
.text:0040765C sub esp, 48h ; esp 指向 _KTRAP_FRAME
.text:0040765F mov ebx, [esp+68h+arg_0];arg_0:4,[esp+6c]->Segcs(三环原来的cs的值)
.text:00407663 and ebx, 1 ;0环最低位为0,3环最低位为1
.text:00407666 mov [esi+140h], bl ; 旧CS 与 1 的结果存入 PreviousMode
.text:0040766C mov ebp, esp ; ebp 指向 _KTRAP_FRAME
.text:0040766E mov ebx, [esi+134h] ;_ETHREAD+0x00+0x134->_KTHERAD+0x134-> TrapFrame
.text:00407674 mov [ebp+3Ch], ebx ; [ebp+3Ch]:_KTRAP_FRAME.Edx , ebx是指向原来的TrapFrame
.text:00407677 mov [esi+134h], ebp ;_ETHREAD+0x00+0x134->_KTHERAD+0x134-> TrapFrame 指向当前 _KTRAP_FRAME
.text:0040767D cld ; df = 0
.text:0040767E mov ebx, [ebp+60h] ;[ebp+60h]:_KTRAP_FRAME.EBP(3环ebp) ,ebp 指向 _KTRAP_FRAME
.text:00407681 mov edi, [ebp+68h] ;[ebp+68h]:_KTRAP_FRAME.EIP(3环eip)
.text:00407684 mov [ebp+0Ch], edx ; _KTRAP_FRAME.DbgArgPointer = edx
.text:00407684 ; 这一步是保存3环API参数指针
.text:00407687 mov dword ptr [ebp+8], 0BADB0D00h; _KTRAP_FRAME.DbgArgMark
.text:0040768E mov [ebp+0], ebx ; _KTRAP_FRAME.DbgEbp = _KTRAP_FRAME.Ebp
.text:00407691 mov [ebp+4], edi ; _KTRAP_FRAME.DbgEip = _KTRAP_FRAME.Eip
.text:00407694 test byte ptr [esi+2Ch], 0FFh;_ETHREAD+0x00+0x2c->_KTHERAD+0x2c->DebugActive ,
.text:00407698 jnz Dr_kss_a ; 测试 CurrentThread.DebugActive
.text:0040769E ; 如果处于调试状态(结果不为-1),跳转,跳转后的代码主要是保存调试相关的寄存器(DR0-DR7)到 _KTRAP_FRAME.DR0-_KTRAP_FRAME.DR7
.text:0040769E
.text:0040769E loc_4664EF: ; CODE XREF: Dr_kss_a+10j
.text:0040769E ; Dr_kss_a+7Cj
.text:0040769E sti ; 关闭中断
.text:0040769F jmp loc_407781
.text:0040769F _KiSystemService endp
解析:00407631 --00407637:设置_KTRAP_FRAME结构体的下图中的成员
00407639 :fs.base = ffdff000,指向当前CPU的KPCR结构
在3环fs指向TEB结构,进入0环,fs指向KPCR结构体(通过段描述符),
00407650:esi 指向CurrentThread(当前cpu所执行线程的_ETHREAD)
00407656 : push dword ptr [esi+140h]:_ETHREAD+0x00+0x140->_KTHERAD+0x140-> PreviousMode(原来的先前模式)
00407640 压栈 ExceptionList->ExceptionList
00407656 压栈 PreviousMode->PreviousPreviousMode
0040765C:sub esp, 48h ;提升48h后 esp指向 _KTRAP_FRAME
00407698 jnz Dr_kss_a;保存调试相关的寄存器(DR0-DR7)到 _KTRAP_FRAME.DR0-_KTRAP_FRAME.DR7
.text:0040752C Dr_kss_a proc near ; CODE XREF: _KiSystemService+67↓j
.text:0040752C test dword ptr [ebp+70h], 20000h
.text:00407533 jnz short loc_407542
.text:00407535 test dword ptr [ebp+6Ch], 1
.text:0040753C jz loc_40769E
.text:00407542
.text:00407542 loc_407542: ; CODE XREF: Dr_kss_a+7↑j
.text:00407542 mov ebx, dr0
.text:00407545 mov ecx, dr1
.text:00407548 mov edi, dr2
.text:0040754B mov [ebp+18h], ebx
.text:0040754E mov [ebp+1Ch], ecx
.text:00407551 mov [ebp+20h], edi
.text:00407554 mov ebx, dr3
.text:00407557 mov ecx, dr6
.text:0040755A mov edi, dr7
.text:0040755D mov [ebp+24h], ebx
.text:00407560 mov [ebp+28h], ecx
.text:00407563 xor ebx, ebx
.text:00407565 mov [ebp+2Ch], edi
.text:00407568 mov dr7, ebx
.text:0040756B mov edi, large fs:20h
.text:00407572 mov ebx, [edi+2F8h]
.text:00407578 mov ecx, [edi+2FCh]
.text:0040757E mov dr0, ebx
.text:00407581 mov dr1, ecx
.text:00407584 mov ebx, [edi+300h]
.text:0040758A mov ecx, [edi+304h]
.text:00407590 mov dr2, ebx
.text:00407593 mov dr3, ecx
.text:00407596 mov ebx, [edi+308h]
.text:0040759C mov ecx, [edi+30Ch]
.text:004075A2 mov dr6, ebx
.text:004075A5 mov dr7, ecx
.text:004075A8 jmp loc_40769E
.text:004075A8 Dr_kss_a endp
.text:004075A8
.text:004075A8 ; ---------------------------------------------------------------------------
.text:004075AD align 10h
.text:004075B0
.text:004075B0 ; =============== S U B R O U T I N E =======================================
0040769F jmp loc_407781;可以发现跳转到了_KiFastCallEntry函数内部(不同的方式保存寄存器,但是最后执行的代码是一样的),因为_KiIntSystemCall与KiFastSystemCall对于寄存器的处理不同,所以需要使用_KiFastCallEntry,KiSystemService两个函数填充_KTRAP_FRAME结构体。
.text:004076F0 ; =============== S U B R O U T I N E =======================================
.text:004076F0
.text:004076F0
.text:004076F0 _KiFastCallEntry proc near ; DATA XREF: _KiTrap01+6F↓o
.text:004076F0 ; KiLoadFastSyscallMachineSpecificRegisters(x)+24↓o
.text:004076F0
.text:004076F0 var_B = byte ptr -0Bh
.text:004076F0
.text:004076F0 ; FUNCTION CHUNK AT .text:004076C8 SIZE 00000023 BYTES
.text:004076F0 ; FUNCTION CHUNK AT .text:00407990 SIZE 00000014 BYTES
.text:004076F0
.text:004076F0 mov ecx, 23h
.text:004076F5 push 30h
.text:004076F7 pop fs
.text:004076F9 mov ds, ecx
.text:004076FB mov es, ecx
.text:004076FD mov ecx, ds:0FFDFF040h
.text:00407703 mov esp, [ecx+4]
.text:00407706 push 23h
.text:00407708 push edx
.text:00407709 pushf
.text:0040770A
.text:0040770A loc_40770A: ; CODE XREF: _KiFastCallEntry2+22↑j
.text:0040770A push 2
.text:0040770C add edx, 8
.text:0040770F popf
.text:00407710 or [esp+0Ch+var_B], 2
.text:00407715 push 1Bh
.text:00407717 push dword ptr ds:0FFDF0304h
.text:0040771D push 0
.text:0040771F push ebp
.text:00407720 push ebx
.text:00407721 push esi
.text:00407722 push edi
.text:00407723 mov ebx, ds:0FFDFF01Ch
.text:00407729 push 3Bh
.text:0040772B mov esi, [ebx+124h]
.text:00407731 push dword ptr [ebx]
.text:00407733 mov dword ptr [ebx], 0FFFFFFFFh
.text:00407739 mov ebp, [esi+18h]
.text:0040773C push 1
.text:0040773E sub esp, 48h
.text:00407741 sub ebp, 29Ch
.text:00407747 mov byte ptr [esi+140h], 1
.text:0040774E cmp ebp, esp
.text:00407750 jnz loc_4076C8
.text:00407756 and dword ptr [ebp+2Ch], 0
.text:0040775A test byte ptr [esi+2Ch], 0FFh
.text:0040775E mov [esi+134h], ebp
.text:00407764 jnz Dr_FastCallDrSave
.text:0040776A
.text:0040776A loc_40776A: ; CODE XREF: Dr_FastCallDrSave+10↑j
.text:0040776A ; Dr_FastCallDrSave+7C↑j
.text:0040776A mov ebx, [ebp+60h]
.text:0040776D mov edi, [ebp+68h]
.text:00407770 mov [ebp+0Ch], edx
.text:00407773 mov dword ptr [ebp+8], 0BADB0D00h
.text:0040777A mov [ebp+0], ebx
.text:0040777D mov [ebp+4], edi
.text:00407780 sti
.text:00407781
.text:00407781 loc_407781: ; CODE XREF: _KiBBTUnexpectedRange+18↑j
.text:00407781 ; _KiSystemService+6E↑j
.text:00407781 mov edi, eax
.text:00407783 shr edi, 8
.text:00407786 and edi, 30h
.text:00407789 mov ecx, edi
.text:0040778B add edi, [esi+0E0h]
.text:00407791 mov ebx, eax
.text:00407793 and eax, 0FFFh
.text:00407798 cmp eax, [edi+8]
.text:0040779B jnb _KiBBTUnexpectedRange
.text:004077A1 cmp ecx, 10h
.text:004077A4 jnz short loc_4077C0
.text:004077A6 mov ecx, ds:0FFDFF018h
.text:004077AC xor ebx, ebx
.text:004077AE
.text:004077AE loc_4077AE: ; DATA XREF: _KiTrap0E+110↓o
.text:004077AE or ebx, [ecx+0F70h]
.text:004077B4 jz short loc_4077C0
.text:004077B6 push edx
.text:004077B7 push eax
.text:004077B8 call ds:_KeGdiFlushUserBatch
.text:004077BE pop eax
.text:004077BF pop edx
.text:004077C0
.text:004077C0 loc_4077C0: ; CODE XREF: _KiFastCallEntry+B4↑j
.text:004077C0 ; _KiFastCallEntry+C4↑j
.text:004077C0 inc dword ptr ds:0FFDFF638h
.text:004077C6 mov esi, edx
.text:004077C8 mov ebx, [edi+0Ch]
.text:004077CB xor ecx, ecx
.text:004077CD mov cl, [eax+ebx]
.text:004077D0 mov edi, [edi]
.text:004077D2 mov ebx, [edi+eax*4]
.text:004077D5 sub esp, ecx
.text:004077D7 shr ecx, 2
.text:004077DA mov edi, esp
.text:004077DC cmp esi, ds:_MmUserProbeAddress
.text:004077E2 jnb loc_407990
.text:004077E8
.text:004077E8 loc_4077E8: ; CODE XREF: _KiFastCallEntry+2A4↓j
.text:004077E8 ; DATA XREF: _KiTrap0E+106↓o
.text:004077E8 rep movsd
.text:004077EA call ebx
.text:004077EC
.text:004077EC loc_4077EC: ; CODE XREF: _KiFastCallEntry+2AF↓j
.text:004077EC ; DATA XREF: _KiTrap0E+126↓o ...
.text:004077EC mov esp, ebp
.text:004077EE
.text:004077EE loc_4077EE: ; CODE XREF: _KiBBTUnexpectedRange+38↑j
.text:004077EE ; _KiBBTUnexpectedRange+43↑j
.text:004077EE mov ecx, ds:0FFDFF124h
.text:004077F4 mov edx, [ebp+3Ch]
.text:004077F7 mov [ecx+134h], edx
.text:004077F7 _KiFastCallEntry endp
.text:004077F7
.text:004077FD
.text:004077FD ; =============== S U B R O U T I N E =======================================
sysente
sysenter 指令进0环后调用KiFastCallEntry
KiFastCallEntry函数如何初始化_KTRAP_FRAME
.text:00466540 _KiFastCallEntry: ; DATA XREF: KiLoadFastSyscallMachineSpecificRegisters(x)+24o
.text:00466540 ; _KiTrap01+72o
.text:00466540 mov ecx, 23h ;让ecx存储023h(三环描述符)
.text:00466545 push 30h
.text:00466547 pop fs ; fs = 0x30, ffc093df`f0000001, 0环数据段
.text:00466549 mov ds, ecx ; ds = 0x23, 00cff300`0000ffff, 3环数据段
.text:0046654B mov es, ecx ; es = 0x23(es辅助ds)
.text:0046654D mov ecx, ds:0FFDFF040h;将TSS地址存储在ecx中 fs:[40h]
.text:00466553 mov esp, [ecx+4] ; esp = _KPCR.TSS.Esp0,切换到0环堆栈
.text:00466556 push 23h ; _KTRAP_FRAME.HardwareSegSs = 0x23,保存旧ss
.text:00466558 push edx ; _KTRAP_FRAME.HardwareEsp = edx, edx是3环栈顶,参数指针
.text:00466559 pushf ; _KTRAP_FRAME.EFlags = EFlags,保存3环eflag寄存器
.text:0046655A
.text:0046655A loc_46655A: ; CODE XREF: _KiSystemService+96j
.text:0046655A push 2 ;将0环eflag寄存器存储在栈中
.text:0046655C add edx, 8 ; edx 指向3环API参数
.text:0046655F popf ; EFlags = 0x02,即清空0环所有标志位
.text:0046655F ; 此时 esp 指向 EFlags
.text:00466560 or [esp+0A4h+var_A3], 2 ; _KTRAP_FRAME.EFlags 即3环 EFlags 的 IF = 1
.text:00466565 push 1Bh ; _KTRAP_FRAME.SegCs = 0x1B, 3环代码段
.text:00466567 push dword ptr ds:0FFDF0304h ; _KTRAP_FRAME.Eip = _KUSER_SHARED_DATA.SystemCallReturn
.text:0046656D push 0 ; _KTRAP_FRAME.ErrCode = 0
.text:0046656F push ebp ; _KTRAP_FRAME.Ebp = ebp
.text:00466570 push ebx ; _KTRAP_FRAME.Ebx = ebx
.text:00466571 push esi ; _KTRAP_FRAME.Esi = esi
.text:00466572 push edi ; _KTRAP_FRAME.Edi = edi
.text:00466573 mov ebx, ds:0FFDFF01Ch ; ebx = _KPCR.SelfPcr,即 ebx 指向 _KPCR
.text:00466579 push 3Bh ; _KTRAP_FRAME.SegFs = 0x3B
.text:0046657B mov esi, [ebx+124h] ; esi = _KPCR._KPRCB.CurrentThread
.text:00466581 push dword ptr [ebx] ; _KTRAP_FRAME.ExceptionList = _KPCR.NtTib.ExceptionList
.text:00466583 mov dword ptr [ebx], 0FFFFFFFFh ; _KPCR.NtTib.ExceptionList = -1
.text:00466589 mov ebp, [esi+18h] ; ebp = _KPCR._KPRCB.CurrentThread.InitialStack
.text:0046658C push 1 ; _KTRAP_FRAME.PreviousPreviousMode = 1,表示从3环来
.text:0046658E sub esp, 48h ; esp 指向 _KTRAP_FRAME
.text:00466591 sub ebp, 29Ch
.text:00466597 mov byte ptr [esi+140h], 1 ; CurrentThread.PreviousMode = 1,表示从3环调用来
.text:0046659E cmp ebp, esp
.text:004665A0 jnz short loc_46653C ; 如果 ebp != esp,跳转到异常处理
.text:004665A0 ; 正常情况下,esp,ebp 均指向 _KTRAP_FRAME
.text:004665A2 and dword ptr [ebp+2Ch], 0 ; _KTRAP_FRAME.Dr7 = 0
.text:004665A6 test byte ptr [esi+2Ch], 0FFh
.text:004665AA mov [esi+134h], ebp ; CurrentThread.TrapFrame = ebp,即指向当前 _KTRAP_FRAME
.text:004665B0 jnz Dr_FastCallDrSave ; 如果DebugActive == 1(被调试),那么跳转到 Dr_FastCallDrSave
.text:004665B0 ; Dr_FastCallDrSave 的功能是保存调试寄存器
.text:004665B6
.text:004665B6 loc_4665B6: ; CODE XREF: Dr_FastCallDrSave+10j
.text:004665B6 ; Dr_FastCallDrSave+7Cj
.text:004665B6 mov ebx, [ebp+60h]
.text:004665B9 mov edi, [ebp+68h]
.text:004665BC mov [ebp+0Ch], edx ; _KTRAP_FRAME.DbgArgPointer = edx, 保存3环参数指针
.text:004665BF mov dword ptr [ebp+8], 0BADB0D00h
.text:004665C6 mov [ebp+0], ebx ; _KTRAP_FRAME.DbgEbp = _KTRAP_FRAME.Ebp
.text:004665C9 mov [ebp+4], edi ; _KTRAP_FRAME.DbgEip = _KTRAP_FRAME.Eip
.text:004665CC sti
小结:
原来的寄存器存储到了 _Trap_Frame 结构体里,3环API参数指针通过EDX传给0环
最后
以上就是贪玩紫菜为你收集整理的内核学习-系统调用上系统调用的学习的全部内容,希望文章能够帮你解决内核学习-系统调用上系统调用的学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复