sysenter指令做了那些事情
在 Ring3 的代码调用了 sysenter 指令之后,CPU 会做出如下的操作:
1. 将 SYSENTER_CS_MSR 的值装载到 cs 寄存器 174
2. 将 SYSENTER_EIP_MSR 的值装载到 eip 寄存器 176
3. 将 SYSENTER_CS_MSR 的值加 8(Ring0 的堆栈段描述符)装载到 ss 寄存器。
4. 将 SYSENTER_ESP_MSR 的值装载到 esp 寄存器 175
5. 将特权级切换到 Ring0
6. 如果 EFLAGS 寄存器的 VM 标志被置位,则清除该标志
7. 开始执行指定的 Ring0 代码
在 Ring0 代码执行完毕,调用 SYSEXIT 指令退回 Ring3 时,CPU 会做出如下操作:
1. 将 SYSENTER_CS_MSR 的值加 16(Ring3 的代码段描述符)装载到 cs 寄存器
2. 将寄存器 edx 的值装载到 eip 寄存器
3. 将 SYSENTER_CS_MSR 的值加 24(Ring3 的堆栈段描述符)装载到 ss 寄存器
4. 将寄存器 ecx 的值装载到 esp 寄存器
5. 将特权级切换到 Ring3
6. 继续执行 Ring3 的代码
dt _KTRAP_FRAME
相当于三环的CONTEXT「Context(上下文)」
函数从3环到0环时的保存现场
操作系统维护了一个结构 _KTRAP_FRAME ,在该结构里保存了一个线程3环的寄存器的值。每一个线程有一个该结构体
Trap Frame是指中断、自陷、异常进入内核后,在堆栈上形成的一种数据结构。用来存储三环的寄存器。
typedef struct _KTRAP_FRAME //Trap现场帧
{
// ------------------这些是KiSystemService保存的---------------------------
ULONG DbgEbp;
ULONG DbgEip;
ULONG DbgArgMark;
ULONG DbgArgPointer;
ULONG TempSegCs;
ULONG TempEsp;
ULONG Dr0; //调试寄存器
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
ULONG SegGs;
ULONG SegEs;
ULONG SegDs;
ULONG Edx;//xy 这个位置不是用来保存edx的,而是用来保存上个Trap帧,因为Trap帧是可以嵌套的
ULONG Ecx; //中断和异常引起的自陷要保存eax,系统调用则不需保存ecx
ULONG Eax;//中断和异常引起的自陷要保存eax,系统调用则不需保存eax
ULONG PreviousPreviousMode;
struct _EXCEPTION_REGISTRATION_RECORD FAR *ExceptionList;//上次seh链表的开头地址
ULONG SegFs;
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Ebp;
//----------------------------------------------------------------------------------------
ULONG ErrCode;//发生的不是中断,而是异常时,cpu还会自动在栈中压入对应的具体异常码在这儿
//-----------下面5个寄存器是由int 2e内部本身保存的或KiFastCallEntry模拟保存的现场---------
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG HardwareEsp;
ULONG HardwareSegSs;
//---------------以下用于用于保存V86模式的4个寄存器也是cpu自动压入的-------------------
ULONG V86Es;
ULONG V86Ds;
ULONG V86Fs;
ULONG V86Gs;
} KTRAP_FRAME, *PKTRAP_FRAME;
KPCR
1)KPCR结构体 CPU临时记录线程信息的一个结构体
2)KPCR中存储了CPU本身要用的一些重要数据:GDT,IDT以及一些线程相关的信息
3)KPCR CPU快速查找线程信息用的,自己在上面做不了什么事情。
FS寄存器的作用
FS寄存器在三环时,记录的是TEB结构的地址。
在0环时,记录的是KPCR的地址。
kd> dt _kpcr
nt!_KPCR
+0x000 NtTib : _NT_TIB
+0x01c SelfPcr :