• 二.Windows内核保护机制--段保护


    一.段的作用:

      在x86-16体系中,为了解决16位寄存器对20位地址线的寻址问题,引入了分段式内存管理。而段的沿用,一方面是为了保持向下的拓展性,另一方面,也增加了可寻址的范围,增加了CPU的性能. 随着CPU性能的大幅度提升,生产商的研发重点,也开始着重于计算机的稳定性,和数据的安全性,因此,在会影响到计算机稳定性和重要数据的地方,就要给用户加上限制,限制用户的行为主要是,数据的读,写和执行,在限制用户的同时,又不能影响操作系统对数据和代码的使用,因此,引入了层(R0,R1,R2,R3)的概念,其中R1层和R2层,并未使用,R0就是我们一般常说的内核层,R3为应用层,也就是用户层,不同的层有不同的权限级别(R0>R1>R2>R3),为了限制人们随意进出R0层,胡乱删改重要内核数据,引起操作系统的崩溃,加入了段机制对人们进行了限制.

    二.段寄存器:

    代码段寄存器CS(Code Segment)

    存放当前正在运行的程序代码所在段的段基址,表示当前使用的指令代码可以从该段寄存器指定的存储器段中取得,相应的偏移量则由IP提供。

    数据段寄存器DS(Data Segment)

    指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基址。

    堆栈段寄存器SS(Stack Segment)

    指出当前堆栈的底部地址,即存放堆栈段的段基址。

    附加段寄存器ES(Extra Segment)

    指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。
     
    FS寄存器在内核层和应用层的表现不太一样,R3层是3B,R0层是30.
     
    GS寄存器 也是一个附加寄存器
     
     

     三.段寄存器的作用

      是用来存放段选择子(Selector),而段选择子在CPU实际应用当中,主要起到两个作用:  

      1.用于在GDT表中,查找到相对应的段描述符,确认属性.  

      2.表明RPL(请求特权级别)的值,CS作为代码寄存器,其段寄存器中的值,与其他段寄存器不同,称为:CPL.

     例如:

    DS:002B

    先将002B拆分为2进制:

    0000 0000 0010 1  0  11  (对照上图)

    RPL:3  即R3权限

    TI: 0指示从全局描述符表GDT中读取描述符;TI:1指示从局部描述符表LDT中读取描述符(windows操作系统自身并没有使用LDT表,因此TI位,在windows里一直为0,除非你自己要用LDT表,否则TI位没什么用...)

    索引号:5  下图中,所对应的是第6个描述符,(GDT表索引是从0开始的,每个描述符为8个字节,32位)

    四.段描述符:

    搜索 gdt 表:

      GDT表全程 Global Descriptor Table,段描述符表。

      其存储在 gdtr 寄存器中,我们在Windbg中使用 "r gdtr" 即可获取该地址。

      然后我们采用 dq address (一个段选择子四字,八字节) 来显示 gdt 表,如果知道索引想直接查看其地址,可以使用 dq address + (index * 8) 的公式来进行搜索。

    在取得段描述符之后,我们对段描述符进行拆分,来获取他的具体属性:

      WORD Attribute;  高位8:15  和 20:23 的属性(下面详细讲解各标志位的作用)

      DWORD Base;    段基地址:: Base31:24   +  Base23:16  +  Base15:00 除了FS寄存器外,Base一般为:0x00000000

      DWORD Limit;     段地址最大范围:Seg Limit19:16  +  Seg Limit15:00  最大值为0X000FFFFF,需要通过G位所表示的单位,进行换算.

      各标志位的作用:

      G位:   G=0表示界限粒度(单位)为1字节,Limit最大值为0x000FFFFF(1MB)

         G=1表示界限粒度(单位)为4K字节,Limit最大值为0x000FFFFF个4KB(4GB)

         注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。

      D/B位:下面将会更详细的讲解

      L位:    用来设置是否为64位代码段.

      AVL位:是软件可利用位80386对该位的使用未做规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。此为被linux和windows操作系统忽略。

     

      P位:0 - 无效段 、 1 - 有效段。(查看该段是否有效,最直接的就是查看该位)

      DPL位: 段特权级别(0到3,但是因为Windows并没有对R1和R2层进行使用,因此DPL的值,不是00就是11,也就是R0或者R3)

         S位:0 - 系统段、1 - 代码段或数据段。

      TYPE位:如果S位==1,则TYPE位进一步详解其代码段或数据段的有关属性(可读可写可执行等等)。

            如下图,一个直观判断到底是代码段还是数据段的方法:TYPE <= 7 数据段 ; TYPE >= 8 代码段。

            数据段:E标志位=1,向下拓展,E标志位=0向上拓展.

          向上拓展与向下拓展:

          向上拓展,可以访问的段范围是:Base到Base+Limit 之间. 现在操作系统都采用向上拓展

          向下拓展,可以访问的段范围是:小于Base 或 大于Base+Limit

          

          代码段:C标志位=1,一致代码段,C标志位=0,非一致代码段.

          一致代码段与非一致代码段:

          一致代码段,可以让三环的权限访问零环的代码,现在操作系统都采用非一致代码段

          难道这就意味着如果将段描述符改为一致代码段,那么三环可以访问零环吗?当然不可以,因为现在操作系统采用段页机制,即使过了段保护,也会存在页保护让你禁止访问。

            

      

    如果S位==0,那么此时为系统段,将会引出:调用门,中断门,陷阱门,任务门,TSS表和IDT表等概念.

     任务门(task gate) 
        当中断信号发生时,必须取代当前进程的那个进程的TSS选择符存放在任务门中。
    中断门(interruptgate) 
        包含段选择符和中断或异常处理程序的段内偏移量.当控制权转移到一个适当的段时,处理器 清IF标志,从而关闭将来会发生的可屏蔽中断.
    陷阱门(Trap gate)
        与中断门相似,只是控制权传递到一个适当的段时处理器不修改IF标志.

    D/B位

      该位对于数据段和代码段有着不同的含义,但大体都是与位数大小有关。比如,如果我们使用32位操作系统,一次操作32位,又如何切换到对16位的操作,根本上就是使用这个位。

      1)代码段CS:在32位操作系统下,如果DB == 1,则采用32位寻址方式,如果操DB==0,则采用16位寻址方式.

       好比汇编代码加上了0x66前缀:

       机器码 :50   对应的汇编代码  push eax

       机器码 :66 50    对应的汇编代码  push ax

        

      2)数据段:该段作用与不同的数据段其含义不同。

       (1) 当特殊情况下,会把数据段ds的段描述符加载到ss段,这种情况下SS的短描述符属性,实际上是DS的,属于数据段描述符,只是放在了ss段中.

          mov ax,ds

          mov ss,ax

          此时,当使用 PUSH POP CALL RETN,类似这种能够改变堆栈指针esp值的代码:

          SS段:  DB == 1 ,被修改的是 esp

              DB == 0 ,被修改的是  sp

       3) 当DS数据段处于,向下拓展的时候:     (其实没啥用,因为Windows,根本都是向上拓展,向下拓展的方式根本就没用过...所以...)

          DB=1,段上限为4GB

          DB=0,段上限为64KB  

     段权限检查:

      

       1)三个概念:

        (1)RPL(Request Privilege Level) 请求特权级别,段选择子的后两位。

        (2)DPL(Descriptor Privilege Level) 段描述特权级别,13位与14位。

        (3)CPL(Current Privilege Level)当前特权级别,当前工作在CSSS段的RPL,我们称之为CPL

      2)权限检查:

        简单解释下上面的概念就很好理解,像 mov ,eax,3bh ; mov ds,eax 。 这种就会进行有关段权限检查,如果不通过赋值会失败。

        首先,CPL表示当前工作的环境(0环或3环),如果CPL为3环,其段选择子后两位不可能为0(不用访问,请求都请求不了)。

        而即使你生成请求,其还会和段描述符中的DPL校验,如果校验不通过,你依然无法生成。

  • 相关阅读:
    PL/SQL注册码
    分页sql
    js获取url值
    C语言中的bool类型 stdbool.h
    语音朗读小程序
    50. Pow(x, n)
    二维数组旋转
    用一位数组代替二维数组作为形参使用
    单链表排序——交换数据成员
    C++重载输入流、输出流运算符
  • 原文地址:https://www.cnblogs.com/jszyx/p/12405111.html
Copyright © 2020-2023  润新知