-
-
[原创]2.滴水中级班(内核驱动)——段寄存器的属性探测
-
发表于: 2025-9-18 00:16 390
-

这里需要记住的就是LDTR和TR是不能通过MOV指令读写的。

xp系统里的值如上图所示,如果系统不一样,那么这些段寄存器的值可能会不一样,也就是红色部分的值是有可能会发生变化的。这个GS的段寄存器,Windows没有使用,所以这里用下换线-表示。Attribute属性里,除了CS段寄存器以外,其他的都是可读可写的;再来看一下Base,除了FS段寄存器以外,其他Base全部都是0;最后再看一下Limit,除了FS段寄存器,其他的段寄存器的界限都是8个F。
有了这些基础以后,可以来挨个探测其存在。


我们先来探测其属性是否存在以及是否起作用。如上图所示,我们把SS段寄存器的内容放到ax这个16位通用寄存器中,接着把ax寄存器的值赋值给ds段寄存器中,然后把eax的值赋值给ds:[var]中,这里的ds由于拿到的值是ss,所以这里也就是相当于ss:[var],ss是可读可写的,所以这里编译运行没有任何问题。

但是如上图所示,如果这里是cs就不行了,因为我们知道cs是可读可执行但是不可写的。这里给大家解释一下什么叫可读可写可执行,(注意:mov 源操作数,目标操作数),可读:你当前的段寄存器是可以放到mov的后一个位置也就是源操作数的位置,可写指的是当前段修饰的地址可以放到mov的前一个位置也就是目标操作数的位置,可执行指的是你当前的段修饰的地址可以赋值给EIP。我们编译运行发现会报错,所以Attribute属性是存在的。
接着来探测一下Base属性。



Base属性是除了FS段寄存器以外,其他的段寄存器的值全是0,我们来探测一下Base属性。这里gs存储的值是fs存储的值,注意这里不能用DS,否则会编译不过去。有点编程基础的人都知道,这个0也就是[0]地址是不能读也不能写的,但是这里编译执行没有报错,是因为实际上我们并没有读0这个地址,结合上一节课说的,我们对任何一个地址的读和写的操作,都相当于当前段的Base加上这个地址,而现在当前段的地址是FS,所以说真正读的地址是FS.Base+0而不是真正对这个0进行读取,也即这里真正读取的地址是0x7FFDE000,那么通过这个探测,我们也是知道了Base属性是确实存在的。
接下来来看Limit属性是否存在。



继续解释这个代码,在这里面,依旧是将FS段寄存器的值读出来放到GS段寄存器里,这里GS段寄存器就相当于FS段寄存器,那么我们要读的地址就是FS.Base+0x1000,我们这里编译运行结果报错,原因就是在于这里的Limit是0xFFF,换句话说0x1000比0xFFF大,所以越界了,因此不能读取这个地址(在 mov eax,gs:[0x1000]位置报错)。而如果我们把这一行注释掉,把下面的那一行取消注释,那么就不会报错了,原因就是Limit在起作用——DS段寄存器的BASE+0x1000没有超过Limit的界限,所以这里可以读、不会报错。
通过刚才的几个例子,我们可以看到段寄存器的这些性质不是虚无的概念,而都是真实存在的,只是我们看不到而已。

刚才在演示程序的时候可以看到写段寄存器的时候一直用的都是AX这样的十六位通用寄存器,那么请思考上述的问题。答案: