<2017年12月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

保护模式1-段寄存器-基本属性

段寄存器是什么?
Segment Register 也可以称作 Selector Register
当我们用汇编读写某个地址时
MOV DWORD PTR DS:[0X00401000],EAX

我们读写的地址其实是DS.BASE+0x00401000

0x00401000被称为读写的有效地址
DS.BASE+0x00401000被称为线性地址,这里做了解即可

段寄存器有自己结构

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

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

其中不可见部分暂不理会,可见部分可以通过OD随便打开一个程序查看
其中红色部分就是段选择子Select

段寄存器  Select  Attribute  Base      Limit
ES      002B    可读/可写   0         0xFFFFFFFF
CS      0023    可读/可执行  0         0xFFFFFFFF
SS      002B    可读/可写   0         0xFFFFFFFF
DS      002B    可读/可写     0            0xFFFFFFFF
FS      0053     可读/可写  0x7FFDE000   0xFFF
GS - - - -

为了验证段寄存器的属性:

Selector:

MOV AX,ES

这里的段选择子为16位,只能使用16位AX寄存器,不能使用32位EAX寄存器

EAX 0000002B
ECX 00FF0000
...

通过读取段寄存器,我们发现只能读取16位,这可见部分就是段选择子

Attribute:

int var = 0;
__asm
{
MOV AX,SS //SS可读,可写 CS可读,可执行
MOV DS,AX
MOV DWORD PTR DS:[var],EAX
}

执行上面代码发现并没有什么用,因为DS修饰的段指向了SS,SS段寄存器可读可写
如果把SS换成CS,就会发现访问错误,因为CS可读可执行,但是并不可写

Base:

int var = 0;
__asm
{
MOV AX,FS //不能换成DS
MOV GS,AX
MOV EAX,GS:[0]
MOV DWORD PTR DS:[VAR],EAX
//MOV DWORD PTR DS:[0X7FFDF000]
}

如果访问地址0会报内存访问错误0xC0000005错误这是常识,但是由于FS段寄存器的Base为0X7FFDF000
线性地址=FS.Base+有效地址 ---------------------- FS.0X7FFDF000+0x00000000
等于说直接访问了0X7FFDF000这个位置,虽然我们代码里写的是0
如果换成其他Base为0的寄存器就会发现内存访问错误

Limint:

int var = 0;
__asm
{
MOV AX,FS //不能换成DS
MOV GS,AX
MOV EAX,GS:[0x1000]
MOV EAX,DWORD PTR DS:[0X7FFDF000+0x1000]
MOV DWORD PTR DS:[var],EAX
}

0x0X7FFDF000+0x1000
FS段寄存器的段限长为FFF,但是我们读取的是0x1000位置的数据,这就能证明段的Limint真实存在

posted @ 2019-01-01 21:41  史D芬周  阅读(714)  评论(0编辑  收藏  举报