DPL
DPL存储在段描述符中,规定访问该段的权限级别(Descriptor Privilege Level)

CPL
CPL是当前进程的权限级别(Current Privilege Level),是当前正在指向的代码段所在段的成绩,也就是CS段的DPL
RPL
RPL说明的是进程对段访问的请求权限(Request Privilege Level)

为了更好的加深印象,我们来尝试操作这几个位
对数据段的影响
首先还是得到现在GDT表,然后把index为4的段描述符放到index为9的地方,并且改变其DPL为0环,00cff3000000ffff改为00cf93000000ffff
0: kd> eq 807d4c68 0000000 00000000
WriteVirtual: 807d4c68 not properly sign extended
WriteVirtual: 807d4c70 not properly sign extended
0: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20  00000000`00000000 00cf9b00`0000ffff
807d4c30  00cf9300`0000ffff 00cffb00`0000ffff
807d4c40  00cff300`0000ffff 80008b7c`f75020ab
807d4c50  8040937c`c0003748 0040f300`00004000
807d4c60  0000f200`0400ffff 00000000`00000000
807d4c70  00000000`00000000 8000897d`1b300068
807d4c80  00000000`00000000 00000000`00000000
807d4c90  800092b9`900003ff 00000000`00000000
这是修改后的样子
0: kd> eq 807d4c68 00cf9300`0000ffff
WriteVirtual: 807d4c68 not properly sign extended
0: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20  00000000`00000000 00cf9b00`0000ffff
807d4c30  00cf9300`0000ffff 00cffb00`0000ffff
807d4c40  00cff300`0000ffff 80008b7c`f75020ab
807d4c50  8040937c`c0003748 0040f300`00004000
807d4c60  0000f200`0400ffff 00cf9300`0000ffff
807d4c70  00000000`00000000 8000897d`1b300068
807d4c80  00000000`00000000 00000000`00000000
807d4c90  800092b9`900003ff 00000000`00000000
这时候我们打开某个程序,用寄存器将ds的值换为48(0100 1000),也就是RPL为0环

再继续向下执行,没有任何影响

同理,如果我们将ds的值改为4b(0100 1011),也就是RPL为R3

也是能够正常执行的

所以,综上所述,我们得出结论在普通数据段下,RPL没有效果,是可以让我们随便改的
对堆栈段的影响
我们继续进行实验,这次要修改的是ss寄存器,之前我们已经将DPL改为了R0。所以我们在这里可以把ss改为R3,也就是4b,多余的过程就不截图了

这时候我们继续向下执行,这时候就又进入了错误分发,也就是报错

这时候我们将index号为9的段描述符DPL改为R3
1: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20  00000000`00000000 00cf9b00`0000ffff
807d4c30  00cf9300`0000ffff 00cffb00`0000ffff
807d4c40  00cff300`0000ffff 80008b7c`f75020ab
807d4c50  8040937c`c0003748 0040f300`00004000
807d4c60  0000f200`0400ffff 00cf9300`0000ffff
807d4c70  00000000`00000000 8000897d`1b300068
807d4c80  00000000`00000000 00000000`00000000
807d4c90  800092b9`900003ff 00000000`00000000
1: kd> eq 807d4c68 00cff300`0000ffff
WriteVirtual: 807d4c68 not properly sign extended
1: kd> dq 807d4c20
ReadVirtual: 807d4c20 not properly sign extended
807d4c20  00000000`00000000 00cf9b00`0000ffff
807d4c30  00cf9300`0000ffff 00cffb00`0000ffff
807d4c40  00cff300`0000ffff 80008b7c`f75020ab
807d4c50  8040937c`c0003748 0040f300`00004000
807d4c60  0000f200`0400ffff 00cff300`0000ffff//在这里
807d4c70  00000000`00000000 8000897d`1b300068
807d4c80  00000000`00000000 00000000`00000000
807d4c90  800092b9`900003ff 00000000`00000000
这时候重新启动,还是一样将ss修改为4b,这时候就可以正常执行了

所以,综上所述,对于ss堆栈段来说,需要DPL和RPL保持一致,再由CS和SS必须保持一致的原则我们可以知道 对于堆栈来说,只有DPL== RPL==CPL,那么代码才能正常执行
对于代码段的影响
先说在前面,由于编译器的影响,将我的jmp far segement:offset 语句错误的翻译成了jmp dword ptr [offset],导致我光是排错就思考了2小时。这个大坑点后面的人一定不要再踩上去
上网查阅资料,果然,jmp far 这种被认为是16位时期的指令,不过我也是第一次知道原来万能的编译器也会乱翻译(笑
正确的我的能够运行的代码如下
#include "stdafx.h"
#include<Windows.h>
void __declspec(naked) test(){
	__asm{
		ret;
	}
}
int _tmain(int argc,_TCHAR* argv[]){
	printf("%x\r\n",test());
	char bufcode[6] = {0,0,0,0,0x48,0};
	*(int *)&bufcode[0] = (int)test;
	printf("bufcode: %02X %02X %02X %02X %02X %02X\n",
		(ungigned char)bufcode[0],
		(ungigned char)bufcode[1]
		(ungigned char)bufcode[2]
		(ungigned char)bufcode[3]
		(ungigned char)bufcode[4]
		(ungigned char)bufcode[5]);
		__asm{
			jmp fword ptr bufcode;//
		}
}
赘述不多说,运行到跳转的这一步,此时cs的值是1b

然后继续向下运行,此时CS被改了

但是随着我们继续运行,CS又被改了回来

综上所述,CPL == DPL,和RPL无关,CPU会有处理机制自动帮助我们纠错



















