要点回顾
- 如:MOV DS, AX
- AX中是一个16位的数,又称为段选择子,段选择子中包含了一个索引,可以通过该索引找到段描述符。
- 并不是说段描述符指向谁,就一定会将这个段描述符加载到当前的段寄存器中。
- 它在加载之前,会有一系列的检查,比如有没有权限,允不允许把段描述符加载到段寄存器中。
- 如果想要了解检查的细节,还要了解一些其他概念。
CPU分级
- 为什么要分级?
- 因为对CPU来说,有些特权指令是只有在0环(Ring 0)才可以使用的。
- Windows系统只使用了CPU中的两个环,R0和R3。
如何查看/判断程序处于几环?需要看CPL。
CPL
CPL(Current Privilege Level):当前进程特权级别,CS和SS中储存的段选择子后2位。
举例说明
如随便拖入一个程序到OD中:
- 可以看到,CS段寄存器中储存的段选择子是0023,拆分为2进制:0000 0000 0010 0011。
- 后2位是11,转换为十进制是3。那么说明这个程序是3环的程序。
DPL
DPL(Descriptor Privilege Level):描述符特权级别。
DPL储存在段描述符中,规定了访问该段所需要的特权级别是什么。
通俗的理解:
如果你想访问我,那么你应该要具备什么特权。
举例说明
- MOV DS, AX:将AX指向的段描述符加载至DS段寄存器。
- 如果AX指向的段DPL(描述符特权级别) = 0,但当前程序的CPL(当前进程特权级别) = 3,这行指令(MOV DS, AX)是不会成功的,因为段权限检查无法通过。
因为Windows中只使用了0环和3环。所以在Windows中,DPL只会是00或者11,在前文提到过,还记得吗?
详见:https://blog.csdn.net/qq_18120361/article/details/114753605
RPL
RPL(Request Privilege Level):请求特权级别。
- RPL是针对段选择子而言的,每个段的段选择子都有自己的RPL。
- RPL就是一个数值,意味着你可以随便写,RPL可以随意指定。
- 但DPL不同,每个段描述符只有唯一的DPL。
举例说明
MOV AX, 0008 | MOV AX, 000B | 设置段选择子 |
MOV DS, AX | MOV DS, AX | 加载段描述符 |
- 以上两行代码指向的是同一个段描述符,但是RPL是不一样的。
- 0008:0000 0000 0000 1000
- 000B:0000 0000 0000 1011
数据段的段权限检查
参考如下代码:
如当前程序处于0环,也就是说CPL = 0。
MOV AX, 000B //0000 0000 0000 1011,RPL = 3
MOV DS, AX //AX指向的段描述符的DPL = 0
数据段的权限检查:
- CPL <= DPL 且 RPL <= DPL (数值上的比较)
- 只有CPL与RPL都要小于等于DPL的时候,上面的两行指令才能加载成功,否则会失败。
注意:
代码段和系统段描述符检查方式是不同的。
总结
CPL(Current Privilege Level):当前进程特权级别。(CS和SS中储存的段选择子后2位。)
DPL(Descriptor Privilege Level):描述符特权级别。(如果想访问,应该具备什么样的权限。)
RPL(Request Privilege Level):请求特权级别。(使用什么样的权限去访问。)
已经有CPL了为什么还要有RPL?
例如写代码时,可以使用 "读写" 的权限去打开一个文件,但是为了避免出错,有些时候使用 "只读" 的权限去打开一个文件。