码迷,mamicode.com
首页 > Windows程序 > 详细

[转载] x86 winxp 下的 segmentation 实例

时间:2015-02-02 17:52:21      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

使用 bochs 可以很容易很直观地观察调试系统。下面选取一个 xp 启动的实际片断,如下:

 

<bochs:7> sreg
cs:s=0x001b, dl=0x0000ffff, dh=0x00cffa00, valid=1
ds:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
ss:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
ss:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
fs:s=0x003b, dl=0xe000ffff, dl=0x7f40f3fd, valid=7
gs:s=0x0000, dl=0x00000000, dl=0x00000000, valid=0
ldtr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
tr:s=0x0028, dl=0x200020ab, dh=800008b04, valid=1
gdtr:base=0x8003f000, limit=0x3ff
idtr:base=0x8003f400, limit=0x7ff




1、GDTR.base 是 0x8003f000, GDTR.limit 是 0x3ff
2、IDTR.base 是 0x8003f400, IDTR.limit 是 0x7ff
3、LDTR.selector  为 0x0000

这里没有建立 LDT,它的 selector 是 0x0000,也就是 NULL descriptor。



5.6.1、  观察 cs register

观察 cs 的信息:
1、cs 使用的 selector 正是前面提到的 0x1b
2、接下来的 dl=0x0000ffff, dh=0x00cffa00 其实就是 descriptor 信息。

来看一看 cs 的 descriptor 的什么:

<bochs:8> x/2 0x8003f000+3*8
0x8003f018 <bogus+    0>:  0x0000ffff   0x00cffa00



cs 使用的 selector 是 0x1b,因此:selector.RPL = 3  使用的权限 3   selector.TI = 0,使用 GDT,selector.SI = 3

descriptor 的地址在:gdtr.base + 3 * 8 = 0X8003f018。

它的值按 64 位显示是:0x00cffa00_0000ffff。


那么,descriptor 的信息:
1、 base = 0x00000000,这是 32 位值。
2、 limit = 0xffffff,这是一个 20 位的值。
3、 DPL = 11b,也就是 3 级。
4、 S 位是 1,它是一个非系统的 descriptor,也就是属于 segment descriptor。
5、 type 是 1010b,显示它是一个 execute/readable  non-conforming 类型的 code segment descriptor。
6、 limit 的粒度位 G 位是 1,显示它是 4K 粒度的。
7、 最后缺省位 D 位是 1, 表明目标 code segment 的 32 位代码。

对这个 descriptor 描述的信息,归纳一下为:segment 是 32 位的代码段,基地址是 0x00000000,访问权限是 3 级,limit 是 0xFFFFF * 0x1000 + 0xFFF = 4G。
物理上这个 descriptor 被加载到 cs register 里。




5.6.2、 观察 ds register

我们看看 ds 加载的 descriptor 的又是怎样的。
ds 使用的 selector 是 0x23:TI = 0,SI = 4 以及 RPL = 3。

获取 descirptor :

<bochs:9> x/2 0x8003f000+4*8
0x8003f020 <bogus+    0>:  0x0000ffff   0x00cff300



这个 descriptor 的值是:0x00cff300_0000ffff  (64 位值)


1、 base = 0x00000000,这是 32 位值。
2、 limit = 0xffffff,这是一个 20 位的值。
3、 DPL = 11b,也就是 3 级。
4、 S 位是 1,它是一个非系统的 descriptor,也就是属于 segment descriptor。
5、 type 是 0011b,显示它是一个具有 R/W 权限的 data segment descriptor。
6、 limit 的粒度位 G 位是 1,显示它是 4K 粒度的。
7、 最后缺省位 D 位是 1, 同 code segment descriptor 意义一致

---------------------------

这个 descriptor 与上面 cs 的 descriptor 不同之处仅是 type 不同。这个 descriptor 是个 data segment descriptor。



5.6.3、 平坦的内存模式

现在的操作系统绝大部分使用平坦的内存模式,这种模式下,所有 segment 的基址是 0x00000000,但是 windows 使用了 FS 来定义非零基址的段。 FS 描述的段的基地址是:0x7f3de000,使用 FS 来管理一些系统信息。
使用了平坦模式,导致可以使用 ds 读取 cs 的数据,或者可以执行 cs 以外的如:ds 或 ss 的代码。在 segmentation 这个阶段里 processor 无法阻止 stack 里的代码可以执行这一情况。直至在 paging 保护措施上才得到解决。

既然使用了平坦模式,逻辑地址与线性地址是一致的。导致现代操作系统已经弱化逻辑地址这个概念,虚拟地址一般就指线性地址

因此:对于两条指令
mov eax, dword ptr cs:[0x8012100]
      mov eax, dword ptr ds:[0x8012100]
      -------------------------------------
      结果是完全一致的。当然这是有提前的。提前是:cs 装的这个 code segment 是可读的。



但是,对于这两条指令,情况就不同了:

mov dword ptr cs:[0x8012100],eax
      mov dword ptr ds:[0x8012100],eax
     -------------------------------------
     第 1 条是会出错的。这里 cs 装的 code segment 是不可写的。

[转载] x86 winxp 下的 segmentation 实例

标签:

原文地址:http://www.cnblogs.com/Acg-Check/p/4268105.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!