上篇我们说了段寄存器有96位,且有四个属性,那我们怎么证明这些属性的存在?一个办法是我们去看Intel架构手册,但是本篇我们用程序和常规知识来探测其存在。
下面就以Win8作为测试环境,编译器使用VS2013来进行测试,注意测试环境不一样,下表的值有可能不一样,如何获取你自己的系统对应的这些值呢?一种办法当然是你度娘了,另一种方式就是OD或者VS咯(注:别问我OD是啥,看这种博客的OD不知道那就别看了!)
段寄存器 | Selector | Attribute | Base | Limit |
ES | 0x002B | 可读、可写 | 0 | 0xFFFFFFFF |
CS | 0x0023 | 可读、可执行 | 0 | 0xFFFFFFFF |
SS | 0x002B | 可读、可写 | 0 | 0xFFFFFFFF |
DS | 0x002B | 可读、可写 | 0 | 0xFFFFFFFF |
FS | 0x0053 | 可读、可写 | 0X7F0EE000 | 0xFFF |
GS | 0x002B | 可读、可写 | 0 | 0xFFFFFFFF |
表中粗体倾斜部分环境不同有可能不一样,如下图OD截图就能轻易知道这些值的来源了;
由上表我们知道ES SS DS GS段中可读、可写,下面我们就来看看下面的代码:
/*
*Attribute.c
*/
int var = 0;
int main()
{
_asm{
//下面两句我们把需要验证的段寄存器写入ds(data segment)中
mov ax, cs //这句中我们依次将cs 换成 ss ds es gs, 并分别编译运行一次看效果
mov ds, ax
//然后我们向变量中写入eax的值
mov dword ptr ds:[var], eax
}
return 0;
}
由上面的代码执行结果我们可以知道,cs修饰的段不能写入,运行程序时报错,其他段中程序没有报错,从这个实验我们看出Attribute属性起作用了;
接下来我们探测仪下Base属性的存在,由于这个实验我们需要用一个段寄存器,Win8中GS被使用了,所以我们接下来环境切换到虚拟机里面的xp系统+VC6.0进行实验。同样我们将上面表中的各属性贴图出来:
从上图我们看到GS在xp中没有使用,这里我们用如下代码来证明:
int main()
{
_asm{
mov ax, fs
mov gs, ax
//我们都知道0地址不能读也不能写
//但是我们这样的代码在VC6.0中顺利执行这说明Base是存在的
//存在着相当于向7FFDF000读取数据,所以Base存在的
mov eax, gs:[0]
}
return 0;
}
接下来我们探测一下Limit属性,代码如下:
int main()
{
_asm{
mov ax, fs
mov gs, ax
//我们前面已经探测了Base的存在
//如果不存在Limit
//则下面这行代码是可以执行的
//但是当执行时却报错,所以Limit是存在的
//mov eax, gs:[0]
//接下来我们将上一行代码注释
//并用西面等价代码替换
//发现同样的地址用下面的语句是可以读的,进一步说明Limit存在
mov eax,dword ptr ds:[0x7FFDF000 + 0x1000]
}
return 0;
}
通过本篇我们验证出了段寄存器的三个隐藏属性确实存在,不是虚无的概念。