要点回顾
struct SetMent
{
WORD Selector; // 16位Selector 可见部分
WORD Attributes; // 16位Attributes 表示当前段寄存器是可读还是可写
DWORD Base; // 32位Base 表示当前段寄存器是从哪里开始的
DWORD Limit; // 32位Limit 表示当前段寄存器整个的长度有多少
}
- 上篇文章中提到,段寄存器有96位。
- 可以通过MOV指令进行读写(LDTR和TR除外)。
但只能看到16位可见部分,也就是Selector。如何证明Attributes、Base以及Limit的存在?
段寄存器成员简介
注意:红色部分在不同的操作系统下可能会发生改变。
探测段寄存器属性
探测Attribute
int var = 0;
int main(int argc, char* argv[])
{
__asm
{
mov ax,ss // cs不行,cs是可读、可执行,但是不可写
mov ds,ax
mov dword ptr ds:[var],eax
}
return 0;
}
探测Base
int var = 0;
int main(int argc, char* argv[])
{
__asm
{
mov ax,fs
mov gs,ax //不要使用ds,否则编译不通过
mov eax,gs:[0] //fs.base+0
mov dwrod ptr ds:[var],eax
//mov edx,dword ptr ds:[0x7FFDE000]
}
return 0;
}
探测Limit
因为fs段寄存器的limit是0xFFF,使用0x1000去读会报错,而读ds段寄存器就不会报错,由此可证明出limit的存在。
int var = 0;
int main(int argc, char* argv[])
{
__asm
{
mov ax,fs
mov gs,ax //不要使用ds,否则编译不通过
mov eax,gs:[0x1000] //fs.base+0x1000
mov dword ptr ds:[var],eax
//mov edx,dword ptr ds:[0x7FFDE000+0x1000]
}
return 0;
}