当我在说跳转时,说的什么?
CPU有很多指令,不是所有的指令都能够随时用,比如
ltr指令就不是随便什么时候能用,在保护模式下,如果你不安规则来执行指令,CPU就会抛出异常,比如你在INTEL手册上就能看到如下文本
意思据是说,如果你当前的CPL不是RING0,那么就会抛出GP(0)异常!
所以要正确使用这个指令,你就需要将CPL跳转到RING0来。这就是跳转!
RING3到RING0(用户态到内核态)的特权转变过程
首先得要有一个RING3的代码段,并且该代码段正处于运行状态
1.定义RING3代码段
[SECTION .ring3]
ALIGN 32
[BITS 32]
LABEL_CODE_RING3:.
;此处省略RING3代码段要做的事情
.
;最后一句转移到ring0
2.必须为RING3代码段定义描述符
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len - 1, DA_C + DA_32 + DA_DPL3 ;DA_DPL3表明该代码段特权等级是RING3
3.为RING3代码段定义选择子
SelectorCodeRing3 equ LABEL_DESC_CODE_RING3 - LABEL_GDT + SA_RPL3 ;SA_RPL3表明该选择子的特权等级也是RING3
4.有了RING3的代码段,描述符,选择子,当然应该有RING0
[SECTION .ring0]
ALIGN 32
[BITS 32]
LABEL_CODE_RING0:.
;此处省略RING0代码段要做的事情
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen - 1, DA_C + DA_32 ; 非一致代码段 ,该段为RING0
SelectorCodeDest equ LABEL_DESC_CODE_DEST - LABEL_GDT ;RING0代码段对应的选择子
到此准备工作已经做好(各级堆栈也需要准备),要从RING3跳转到RING0,通过这一篇文章,可以通过调用门实现从低级到高级的跳转,接下来定义调用门,和调用门的选择子
调用门
LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 0, DA_386CGate + DA_DPL3;
选择子
SelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3
调用门定义时,需要用到RING0的选择子。并且调用门和调用门选择子的特权等级也都是RING3,加入调用门本身就定义为非RING3,那么在RING3代码中执行跳转时,就会报错。
现在来晚上RING3代码段最后一句,跳转到RING0
call SelectorCallGateTest:0 ;
准备一大堆,一句话就跳转了!RING3->RING0。从老幺一下权利跃升到老大!