zoukankan      html  css  js  c++  java
  • 保护模式_1_段寄存器_段描述符_段选择子

    1 段寄存器

    1-1 段寄存器的结构

    图示:

    结构体表示:

    struct SegMent
    {
    	WORD Selector;
    	WORD Attribute;
    	DWORD Base;
    	DWORD Limit;
    }
    

    1-2 段寄存器的属性探测

    可以通过MOV指令进行读写(LDTR和TR除外)

    段寄存器成员简介

    探测Attribute是否存在

    int var=0;
    int main()
    {
    	__asm
    	{
    		mov ax, ss  //cs不行 cs是可读 可执行 但不可写
    		mov ds, ax
    		mov dword ptr ds:[var], eax
    	}
    }
    

    探测Base是否存在

    int var=0;
    int main()
    {
    	__asm
    	{
    		mov ax, fs
    		mov gs, ax
    		mov eax, gs:[0]  //不要用DS否则编译不过去  //fs.base+0是真正访问的
    		//相当于
    		//mov edx, dword ptr ds:[0x7FFDE000]  //这个地址是可以访问的
    		mov dword ptr ds:[var], eax
    
    	}
    }
    

    探测Limit是否存在

    int var=0;
    int main()
    {
    	__asm
    	{
    		mov ax, fs
    		mov gs, ax
    		mov eax, gs:[0x1000]   //0x7FFDF000+0x1000,1000超过了0xFFF
    		//访问的地址相当于下面的 但DS的Limit是0xFFFFFFFF
    		mov edx, dword ptr ds:[0x7FFDF000+0x1000]
    		mov dword ptr ds:[var], eax
    	}
    }
    

    1-3 段描述符与段选择子

    段寄存器的值是通过段描述符填充的。

    1-3-1 GDT(全局描述符表) LDT(局部描述符表)

    当我们执行类似MOV DS, AX指令时,CPU会查表,根据AX的值来决定查找GDT还是LDT,查找表的什么位置,查出多少数据

    1-3-2 段选择子

    段选择子是一个16位的段描述符,该描述符指向了定义该段的段描述符.

    1-3-3 加载段描述符至段寄存器

    除了MOV指令,我们还可以使用LES、LSS、LDS、LFS、LGS指令修改寄存器.

    CS不能通过上述的指令进行修改,CS为代码段,CS的改变会导致EIP的改变,要改CS,必须要保证CS与EIP一起改,后面会讲

    char buffer[6];
    __asm
    {
    	les ecx, fword ptr ds:[buffer]  //高2字节给es,低四字节给ecx
    }
    

    注意:RPL<=DPL(在数值上)

    1-4 段描述符属性_P位_G位_S位_TYPE域

    1-4-1 P位

    P = 1 段描述符有效
    P = 0 段描述符无效

    1-4-2 段描述符与段寄存器的对应关系

    1-4-3 G位

    重点在于Limit结构。
    当G = 0 时,Limit是0x000XXXXX
    当G = 1 时,Limit是0xFFFXXXXX -- 这里存疑

    1-4-4 S位

    小结:先判断P位,再判断S位是0/1(确定是数据段/代码段或者是系统段的)
    DPL只能出现两种情况,或0或1

    1-4-5 TYPE域

    S = 1 代码段或数据段的描述符

    S = 0 系统段的描述符

    ** 数据段说明: **
    A 访问位,表示该位最后一次被操作系统清理后,该段是否被访问过,每当处理器将该段选择符置入某个段寄存器时,就将该位置1.
    W 是否可写
    E 扩展方向
    ** 代码段说明:**
    A 访问位
    R 可读位
    C 一致位 { C = 1 一致代码段; C = 0 非一致代码段}

    1-4-6 DB位

    情况一:对CS段的影响
    D = 1采用32位寻址方式
    D = 0采用16位寻址方式
    前缀67 改变寻址方式

    情况二:对SS段的影响
    D = 1 隐式堆栈访问指令(如:PUSH POP CALL)使用32位堆栈指令寄存器ESP
    D = 0 隐式堆栈访问指令(如:PUSH POP CALL)使用16位堆栈指令寄存器SP

    情况三:向下扩展的数据段
    D = 1 段上线为4GB
    D = 0 段上线为64KB

    1-5 段权限检查

    1-5-1 CPU分级

    1-5-2 如何查看程序处于第几环?

    CS寄存器的段选择子(共16bit)的后两个bit,表示的是CPL(Current Privilege Level):CPU当前特权等级
    CS和SS中存储的段选择子后2个bit

    1-5-3 DPL(Descriptor Privilege Level) 描述符特权等级

    DPL存储在段描述符中,规定了访问该段所需要的特权级别是什么
    举例说明:
    如果AX指向的段DPL = 0 但当前程序的CPL = 3 这行指令是不会成功的

    1-5-4 RPL(Request Privilege Level) 请求特权等级

    举例说明:
    mov ax, 0008 与 mov ax, 000B //段选择子
    mov ds, ax //将段描述指向的是同一个段描述符,但RPL是不一样的

    1-5-5 数据段的权限检查

    参考如下代码:
    比如当前程序处于0环, 也就是说CPL=0
    mov ax, 000B //1011 RPL=3
    mov ds, ax //ax指向的段描述符的DPL=0

    数据段的权限检查:
    CPL <= DPL 并且 RPL <= DPL(数值上的比较)

    注意:
    代码段和系统段描述符中的检查方式并不一样,具体参见后面内容...

    1-5-6 总结:

    CPL CPU当前的权限级别
    DPL 如果你想访问我,你应该具备什么样的权限
    RPL 用什么权限去访问一个段

    为啥要有RPL?
    我们本可以用“读、写”的权限去打开一个文件,但为了避免出错,有些时候我们使用“只读”的权限去打开。

  • 相关阅读:
    mac 终端命令kill掉某个指定端口
    python web开发之flask框架学习(1) 创建flask项目
    ios json转model的简单现实
    SnapKit swift实现高度自适应的新浪微博布局
    IOS swift实现密码的显示与隐藏切换
    IOS UIWebView与js的简单交互swift3版
    android 手写万能adapter适配器
    简单几步实现 IOS UITextField输入长度的控制
    IOS Swift UITableViewcontroller实现点击空白处隐藏键盘
    xcode 版本控制推送代码到远程git仓库的步骤
  • 原文地址:https://www.cnblogs.com/flatcc/p/11613649.html
Copyright © 2011-2022 走看看