电子商务网站建设与管理总结,wordpress 插件报错,wordpress破解key,wordpress好看的中文主题windows xp#xff0c;ReactOS系统快速系统调用的实现
windows xp#xff0c;ReactOS系统快速系统调用的实现 文章目录 **windows xp#xff0c;ReactOS系统快速系统调用的实现**快速系统调用进入R0我们看MSR寄存器中的内容到底是啥子快速系统调用返回PspLookupKernelUserE…windows xpReactOS系统快速系统调用的实现
windows xpReactOS系统快速系统调用的实现 文章目录 **windows xpReactOS系统快速系统调用的实现**快速系统调用进入R0我们看MSR寄存器中的内容到底是啥子快速系统调用返回PspLookupKernelUserEntryPoints(VOID) 快速系统调用
从奔腾2开始就增设了两条指令和三个寄存器来支持“快速系统调用”sysenter,sysexit指令,MSR寄存器这样就实现比较轻便和搞笑的系统调用 在快速系统调用时用户空间的“int 0x2e自陷指令大体上为一条sysenter指令锁替代但是sysenter指令不同于int 指令或者call指令。sysexit指令也不同于iretret指令这两条指令并不涉及 到堆栈的操作。而是依赖一组MSR寄存器。
进入R0
当执行sysenter指令时CPU进入R0并且 1把寄存器SYSTEMER_CS_MSR的内容复制到段寄存器CS中。 2把寄存器SYSTEMER_EIP_MSR的内容复制到段寄存器EIP中。 3把(寄存器SYSTEMER_CS_MSR的内容8)复制到段寄存器SS中。 4把寄存器SYSTEMER_ESP_MSR的内容复制到段寄存器ESP中。
这样只要预先设置好三个MSR寄存器的内容cpu在指向sysenter指令病会进入R0并预定的地址开始执行程序 同时开始使用系统空间的堆栈而不像通过自陷指令进入系统空间那样要执行那么多的操作效率提高了。
但是此时CPU不想在执行子限制了时那样自动把用户空间的堆栈指针保存在系统空间堆栈上甚至也不讲返回地址压入堆栈所有如果需要就要有对象的程序来完成操作。尽管如此快速系统调用的效率还是要搞很多因为至少不需要从中断向量表获取程序入口的位置了。
我们看MSR寄存器中的内容到底是啥子
ULONG_PTR
NTAPI
KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
{/* Set CS and ESP */Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);Ke386Wrmsr(0x175, (ULONG)KeGetCurrentPrcb()-DpcStack, 0);/* Set LSTAR */Ke386Wrmsr(0x176, (ULONG)KiFastCallEntry, 0);return 0;
}其中
#define KGDT_R0_CODE 0x8
c
这里可以看出他是一个常量这里调用了三次Ke386Wrmsr()
#define Ke386Wrmsr(msr,val1,val2) __asm__ __volatile__(wrmsr : /* no outputs */ : c (msr), a (val1), d (val2))实际上就是特权指令wrmsr的封装 第一个参数时目标MSR寄存器的编号。显然这三个端口粉笔为0x174,0x175,x0176 MSR寄存器时64位的但这三个寄存器时都是32位的所以第三个参数都为0 第一次调用把cs设置位8 第二次用KeGetCurrentPrcb函数获取。 第三次调用指向快速调用的入口地址。这里通过KiFastCallEntry函数获取
快速系统调用返回
与KiFastSystemCall()一样这是有ntdll.dll导出的一个函数。内核在初始化通过PspLookupKernelUserEntryPoints(VOID)获取ntdll.dll中这两个函数的入口并将其保存在一个数据结构SharedUserData中之所以说Shared,是因为其所在的物理页面在系统空间和用户空间都有映射因此从内核和用户空间都能访问这个数据结构只是所有的虚拟地址不同
PspLookupKernelUserEntryPoints(VOID) NTSTATUS
NTAPI
PspLookupKernelUserEntryPoints(VOID)
{NTSTATUS Status;/* Get user-mode APC trampoline */Status PspLookupSystemDllEntryPoint(KiUserApcDispatcher,KeUserApcDispatcher);if (!NT_SUCCESS(Status)) return Status;/* Get user-mode exception dispatcher */Status PspLookupSystemDllEntryPoint(KiUserExceptionDispatcher,KeUserExceptionDispatcher);if (!NT_SUCCESS(Status)) return Status;/* Get user-mode callback dispatcher */Status PspLookupSystemDllEntryPoint(KiUserCallbackDispatcher,KeUserCallbackDispatcher);if (!NT_SUCCESS(Status)) return Status;/* Get user-mode exception raise trampoline */Status PspLookupSystemDllEntryPoint(KiRaiseUserExceptionDispatcher,KeRaiseUserExceptionDispatcher);if (!NT_SUCCESS(Status)) return Status;/* Check if this is a machine that supports SYSENTER */if (KeFeatureBits KF_FAST_SYSCALL){/* Get user-mode sysenter stub */Status PspLookupSystemDllEntryPoint(KiFastSystemCall,(PVOID)SharedUserData-SystemCall);if (!NT_SUCCESS(Status)) return Status;/* Get user-mode sysenter return stub */Status PspLookupSystemDllEntryPoint(KiFastSystemCallRet,(PVOID)SharedUserData-SystemCallReturn);}else{/* Get the user-mode interrupt stub */Status PspLookupSystemDllEntryPoint(KiIntSystemCall,(PVOID)SharedUserData-SystemCall);}/* Set the test instruction */if (!NT_SUCCESS(Status)) SharedUserData-TestRetInstruction 0xC3;/* Return the status */return Status;
}
这样需要从快速系统调用返回时只需要从这个数据结构获取目标地址就行了。至于堆栈指针则显然是保存在寄存器edx中。 当CPU执行sysexit指令时则返回用户态。并且 1把CS设置成SYSENTER_CS_MSR的内容16这实际上是KGDT_R3_CODE注意CS中的RPL位段自动设置为3三环 2把寄存器EDX的内容复制到EIP. 3,把SS设置成SYSTENTER_CS_MSR的内容24这实际上是KGDT_R3_DATA注意SS中的RPL位段自动设置为3 4把寄存器ECX的内容复制到ESP
九十四只需要ECX持有用户空间的堆栈指针并把SharedUserData-SystemCallReturn之于EDX在执行sysexit就可以了。 可见。sysenter,sysexit的组合再加上三个MSR寄存器的作用实现了一种十分简便的快速系统调用和返回机制相比之下int,iret的组合显得太复杂了。