段寄存器测试


寄存器测试

内存地址转换过程

虚拟地址 –>段选择子+偏移地址–>分段管理机制–>线性地址–>分页管理机制–>物理地址

地址映射转换过程

不同段寄存器对应不同作用

ES —> 对串进行操作 [ESI] [EDI] STOSD MOVSD

CS —> EIP EBP

DS —> 通用

FS —> 异常

GS —> 保留

系统段 —> LDTR TR

段寄存器有96位,但在3环仅可使用16位选择子

struct Segment{
    WORD selector;//3环用户态只能看到选择子
    WORD attributes;//系统
    DWORD base;//系统
    DWORD limit;//系统
}

获取不同寄段存器的选择子

mov ax, es #0x23
mov cx, cs #0x1b
mov dx, ss #0x23
mov ax, ds #0x23
mov cs, fs #0x3b
mov dx, gs #0x00
ldtr #0x0
tr   #0x28
sldt ax #读取ldtr
lldt    #写ldtr,只有0环可操作
str cx  #读取tr
ltr     #写tr,只有0环可操作

修改段寄存器

int var;
int main(){
    _asm{
        mov ax, ss;
        mov ds, ax;
        mov var, eax;
    }
}

在32位系统中,由于ss和ds的值相同,所以可以运行,若将ss改成cs,则会发生0xc0000005内存冲突

int var;
int main(){
    _asm{
        mov ax, cs;
        mov ds, ax;
        mov var, eax; //此步内存冲突
    }
}

因为ds对应数据段,可读可写,而cs对应EIP,EIP对应代码段,代码段可读不可写,所以eax无法给var赋值

如下代码,当段寄存器不为0,偏移为0时,可以访问该地址。若将fs改成ds(ds一般为0),gs:[0] = 0x0,访问报错

int var;
int main(){
    _asm{
        mov ax, fs;
        mov gs, ax;
        mov eax, gs:[0];
        mov var, eax;
    }
}

fs的基址为0x7ffdf000,界限为0xfff,超过0xfff会报错

int var;
int main(){
    _asm{
        mov ax, fs;
        mov gs, ax;
        mov eax, gs:[0xffd]; //ffd ffe fff 1000 
        //eax有4个字节,而fs的界限为0xfff,0xffd+4=0x1000超出了0xfff界限,所以报错
        mov var, eax;
    }
}
struct GDTR{ //一个CPU只有一份
    WORD LIMIT;
    DOWRD BASE;
} 

通用寄存器给段寄存器赋值16位扩展96位

段寄存器赋值规则

mov ax, 0x2b
mov ds, ax

以上代码为例

1、判断ax是否在GDTR限制中

0 < (ax >> 3) < GDTR.limit

2、TI

TI = 0时,表示选择GDT,TI = 1 选择LDT,由于Windows没有LDT,所以TI一定为0

3、GDT中判断

选择子结构

RPL 选择子的权限 ax & 0b11

CPL cs的权限 cs & 0b11

DPL 描述符的权限 描述符 & 0x60000000000

判断各个寄存器和描述符权限

max(CPL, RPL) <= DPL

在保护模式下 3环CS的低两位和SS的低两位一定相同

FS ES DS GS 权限上一定大于等于CS的低两位
在数值上一定要小于等于CS的低两位

判断P

P = 1时,描述符对地址转换有效,反之则无效。为了让GDTR这8字节有效,P必须为1

判断DT

DT = 1 表示为存储段描述符

判断TYPE

判断type是否符合当前段寄存器的属性

Type.c==0,非一致代码段,则要求CPL==DPL;一致代码段,则要求CPL>=DPL

s==1 && Type.11 == 1则代表请求代码段;

image-20220409174548096

调用门,type == 1100B(12)
中断门,type == 1110B(14),IDT表中的中断处理函数就是这种门描述符
陷阱门,type == 1111B(15),IDT表中的陷阱处理函数就是这种门描述符
任务门,type == 0101B(5),用于任务切换

windbg> eq 地址 值 //修改内存


文章作者: Kevin。
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Kevin。 !
评论
 上一篇
存储段描述符表 存储段描述符表
存储段描述符表GDT和GDTRGDTGDT(Global Descriptor Table)全局描述符表,一个处理器仅有一个GDT,主要用于内存转换,所有程序的内存访问都需要用到GDT中的有关内存区域即x86内存分段的信息。描述符每一项都为
2022-04-09
下一篇 
初步了解保护模式 初步了解保护模式
保护模式实模式与保护模式的区别实模式实模式出现于早期8088 CPU时期。当时由于CPU的性能有限,一共只有20位地址线,地址空间只有2^20B = 1MB,以及8个16位的通用寄存器,以及4个16位的段寄存器 ES、SS、CS、DS。为了
2022-04-06
  目录