• 2.[保护模式]段寄存器


    1.段寄存器结构

    段寄存器一共96位,但是可见部分只有16位

    Struct SegMent
    {
        WORD Selector;     //16位段选择子
        WORD Attributes; //16位属性
        DWORD Base;     //32位基址
        DWORD Limit;    //32位段限长
    }
    
    

    其中红色部分就是段选择子(就是做段权限检测的)Selector比如:2B拆分如下 0010 1011 -》0010 1 0 11

    00101查找GDT表里面的位置索引5

    0     查GDT表,如果为1则查LDT表(LDT能有多张表)
    11 所处的请求级别RPL ,3是三环 0 是0环


    HEX=转成16进制
    那么索引公式是:GDT表首地址(通过 r gdtr获取)+HEX[索引值(5)*8(字节宽度)]

    2.段寄存器的读写:

      读段寄存器:

        比如:MOV AX,ES  只能读16位的可见部分

        读写LDTR 的指令为:SLDT/LLDT

        读写TR的指令为:STR/LTR

      写段寄存器:

        比如:MOV DS,AX 写的时候是写96位

     

    除了CS 都是可读可写属性。

     

    3.既然只有16位可见位那怎么判读另外的80位是存在的呢?接下来我们进行探查

     一、探测Attribute

        attr =0cf3   第一位没有用使用所以补0 

    #include "stdafx.h"
    //两个可读可写段寄存器互换没影响
    int var = 0;
    int main()
    {
        
        __asm
        {
            mov ax,ss   //将SS的值读出来
            mov ds,ax    //将AX写入,此时ds已经是SS了
            mov dword ptr ds:[var],eax  //实际上已经是ss:[var]
        return 0;
    }  

      //以下代码报错证明Attribute属性起作用了!

    #include "stdafx.h"
    
    int var = 0;
    int main()
    {
        
        __asm
        {
            mov ax,cs   //将CS的值读出来  ,但是CS是可读可执行,并不可写
            mov ds,ax    //将AX写入,此时就会报错
            mov dword ptr ds:[var],eax  //两个不同属性的并不能转换
        return 0;
    }

     2.探测BASE:

     1 #include "stdafx.h"
     2 
     3 int var = 0;
     4 int main()
     5 {
     6     __asm
     7     {
     8         mov ax,fs     
     9         mov gs,ax      //此处如果换成ds则会出现编译不过的问题
    10         mov eax,gs:[0]  //对0地址进行读的操作(如果是0地址不能读也不能写,此时gs已经是fs)
    11         //相当于
    12         //mov edx,dword ptr ds:[0x7FFDF000]
    13         mov dword ptr ds:[var],eax
    14     }
    15     
    16 }

      3.探测Limit

    limt:(fffff+1)*4k -1 =ffffffff

    4k = 4096

    fffff是从0开始所以应该+1

    #include "stdafx.h"
    //报错,fs访问越界,证明Limit真实存在
    int var = 0;
    int main()
    {
        __asm
        {
            mov ax,fs     
            mov gs,ax      //此处如果换成ds则会出现编译不过的问题
            mov eax,gs:[1000]  //fs的limit是FFF 但是读0x1000则越界了
            //访问的地址相当于下面的 但是DS的Limit是0xFFFFFFFF
            //mov eax,dword ptr ds:[0x7FFDF000+0x1000]
            mov dword ptr ds:[var],eax
        }
        
    }

    4.段寄存器有96位,那剩下的80位从哪来的?

    数据是从GDT表里面来的,在线程和进程没有切换的情况下:读取后会把它弄进一个缓冲区,只会读取GDT表一次

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

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

    查出多少数据;

    在WinDbg中 使用 r gdtr  命令来查找gdtr寄存器里的地址,r 则是查看寄存器的意思;

    使用 r gdtl 指令则是查看这张表有多大!

    使用dd 查看表内容

    1: kd> r gdtr
    gdtr=fffff8800470b4c0
    1: kd> r gdtl
    gdtl=007f
    1: kd> dd fffff8800470b4c0
    fffff880`0470b4c0 00000000 00000000 00000000 00000000
    fffff880`0470b4d0 00000000 00209b00 0000ffff 00cf9300
    fffff880`0470b4e0 0000ffff 00cffb00 0000ffff 00cff300
    fffff880`0470b4f0 00000000 0020fb00 00000000 00000000
    fffff880`0470b500 4ec00067 04008b70 fffff880 00000000
    fffff880`0470b510 e0007c00 ff40f3f9 00000000 00000000
    fffff880`0470b520 0000ffff 00cf9a00 00000000 00000000
    fffff880`0470b530 00000000 00000000 00000000 00000000

     
       

    GDT表内存储的元素称之为:“段描述符”

    每个段描述符占8个字节

    段描述符结构(必背):

    看一个段首先看P为是否可用,然后看S位 -TYPE 看看描述的是个什么东西,其次看D/B  ,再看G位

    dq指令 则是查看8字节;

    如果想要查看更多 则可以使用 dq 地址  L数量

    nt!RtlpBreakWithStatusInstruction:
    fffff800`03ec7fb0 cc int 3
    1: kd> r gdtr
    gdtr=fffff8800470b4c0
    1: kd> r gdtl
    gdtl=007f
    1: kd> dd fffff8800470b4c0
    fffff880`0470b4c0 00000000 00000000 00000000 00000000
    fffff880`0470b4d0 00000000 00209b00 0000ffff 00cf9300
    fffff880`0470b4e0 0000ffff 00cffb00 0000ffff 00cff300
    fffff880`0470b4f0 00000000 0020fb00 00000000 00000000
    fffff880`0470b500 4ec00067 04008b70 fffff880 00000000
    fffff880`0470b510 e0007c00 ff40f3f9 00000000 00000000
    fffff880`0470b520 0000ffff 00cf9a00 00000000 00000000
    fffff880`0470b530 00000000 00000000 00000000 00000000
    1: kd> dq fffff8800470b4c0
    fffff880`0470b4c0 00000000`00000000 00000000`00000000
    fffff880`0470b4d0 00209b00`00000000 00cf9300`0000ffff
    fffff880`0470b4e0 00cffb00`0000ffff 00cff300`0000ffff
    fffff880`0470b4f0 0020fb00`00000000 00000000`00000000
    fffff880`0470b500 04008b70`4ec00067 00000000`fffff880
    fffff880`0470b510 ff40f3f9`e0007c00 00000000`00000000
    fffff880`0470b520 00cf9a00`0000ffff 00000000`00000000
    fffff880`0470b530 00000000`00000000 00000000`00000000
    1: kd> dq fffff8800470b4c0 L50
    fffff880`0470b4c0 00000000`00000000 00000000`00000000
    fffff880`0470b4d0 00209b00`00000000 00cf9300`0000ffff
    fffff880`0470b4e0 00cffb00`0000ffff 00cff300`0000ffff
    fffff880`0470b4f0 0020fb00`00000000 00000000`00000000
    fffff880`0470b500 04008b70`4ec00067 00000000`fffff880
    fffff880`0470b510 ff40f3f9`e0007c00 00000000`00000000
    fffff880`0470b520 00cf9a00`0000ffff 00000000`00000000
    fffff880`0470b530 00000000`00000000 00000000`00000000
    fffff880`0470b540 03ec8e00`0010cf00 00000000`fffff800
    fffff880`0470b550 03ec8e00`0010d000 00000000`fffff800
    fffff880`0470b560 03ec8e03`0010d1c0 00000000`fffff800
    fffff880`0470b570 03ecee00`0010d540 00000000`fffff800
    fffff880`0470b580 03ecee00`0010d640 00000000`fffff800
    fffff880`0470b590 03ec8e00`0010d740 00000000`fffff800
    fffff880`0470b5a0 03ec8e00`0010d840 00000000`fffff800
    fffff880`0470b5b0 03ec8e00`0010da80 00000000`fffff800
    fffff880`0470b5c0 03ec8e01`0010db40 00000000`fffff800
    fffff880`0470b5d0 03ec8e00`0010dc00 00000000`fffff800
    fffff880`0470b5e0 03ec8e00`0010dcc0 00000000`fffff800
    fffff880`0470b5f0 03ec8e00`0010dd80 00000000`fffff800
    fffff880`0470b600 03ec8e00`0010dec0 00000000`fffff800
    fffff880`0470b610 03ec8e00`0010e000 00000000`fffff800
    fffff880`0470b620 03ec8e00`0010e140 00000000`fffff800
    fffff880`0470b630 04008e00`001090f0 00000000`fffff800
    fffff880`0470b640 03ec8e00`0010e500 00000000`fffff800
    fffff880`0470b650 03ec8e00`0010e680 00000000`fffff800
    fffff880`0470b660 03ec8e02`0010e780 00000000`fffff800
    fffff880`0470b670 03ec8e00`0010eb00 00000000`fffff800
    fffff880`0470b680 04008e00`00109140 00000000`fffff800
    fffff880`0470b690 04008e00`00109150 00000000`fffff800
    fffff880`0470b6a0 04008e00`00109160 00000000`fffff800
    fffff880`0470b6b0 04008e00`00109170 00000000`fffff800
    fffff880`0470b6c0 04008e00`00109180 00000000`fffff800
    fffff880`0470b6d0 04008e00`00109190 00000000`fffff800
    fffff880`0470b6e0 04008e00`001091a0 00000000`fffff800
    fffff880`0470b6f0 04008e00`001091b0 00000000`fffff800
    fffff880`0470b700 04008e00`001091c0 00000000`fffff800
    fffff880`0470b710 04008e00`001091d0 00000000`fffff800
    fffff880`0470b720 04008e00`001091e0 00000000`fffff800
    fffff880`0470b730 03f18e00`0010af10 00000000`fffff800

     
       

    段选择子:

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

    如: 1B (001B)00一般省略 拆分后为 0000 0000 0001 1011

    0000 0000 0001 1 (这里拼接起来为3则查找GDT表第3相)   0(TI)11(RPL)

    加载段描述符至段寄存器:

     这里的RPL<=DPL不准确,数值上应该是RPL>=DPL

    2019-07-21

    三环读取GDT表首地址

    unsigned char buf[6]={0};
    _asm
    {
      sgdt buf;  
    }
    printf("%x,%x",*((unsingned int*)&(buf[2])),
    *((unsingned short*)&(buf[0])));
    )

     每次执行代码都要经过CS段!CPL

  • 相关阅读:
    CSS画出三角形(利用Border)
    Javascript中style,currentStyle和getComputedStyle的区别以及获取css操作方法
    用canvas实现验证码的绘制
    tinymce富文本编辑器升级问题
    同步和异步
    this
    发送短信——案例
    SpringMvc框架【多测师】
    通过百度文字识别的API来实现把图片内容写入到txt文件当中【多测师】
    史上最全软件测试工程师常见的面试题总结(七)【多测师】
  • 原文地址:https://www.cnblogs.com/hanhandaren/p/11163622.html
Copyright © 2020-2023  润新知