[转载] x86 winxp 下的 segmentation 实例

使用 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 是不可写的。

时间: 2024-10-29 02:42:13

[转载] x86 winxp 下的 segmentation 实例的相关文章

[转载]x86 vista 下的 paging

看一个实际的例子: kd> u nt!InitBootProcessor+0x3df: 81b3a6de fec8            dec     al 81b3a6e0 f6d8            neg     al 81b3a6e2 bfe0df8f81      mov     edi,offset nt!ExpBootEnvironmentInformation (818fdfe0) 81b3a6e7 1bc0            sbb     eax,eax 81b3a

一个多线程下的单实例实现故障

最近在asp.net项目中碰到的一个问题. 一个编码器模块使用单实例实现,结果碰到了编码ID重复的异常. public class IdGenerator { private static IdGenerator single; public static IdGenerator Single { get { if (null == single) { single = new IdGenerator(); } return single; } } protected IdGenerator()

纯css+js下拉菜单实例代码

纯css+js下拉菜单实例代码 分享一个css+js下拉菜单代码,js+css实现的简单下拉菜单,兼容性不错. 例子:<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <

Linux下shell编程实例

1. 判断一文件是不是块或字符设备文件,如果是将其拷贝到 /dev 目录下 read -p "input a file:" filename if [ -b $filename -o -c $filename ] then cp $filename /dev/ fi 2.编写一个脚本,进行简单的减法运算,要求提示输入变量 #!/bin/bash read -p "input a number:" num1 read -p "input another nu

(8)Linux(客户端)和Windows(服务端)下socket通信实例

Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows   Client端 #include <stdio.h> #include <Windows.h> #pragma comment(lib, "ws2_32.lib") #define Port 5000 #define IP_ADDRESS "192.168.1.30"     //服务器地址

Windows下MySQL多实例运行

关键字:Windows下MySQL多实例运行 阅读前注意事项: 1.有的版本的data目录不直接放在mysql安装目录下,有可能在:C:\ProgramData\MySQL\MySQL Server 5.1\data(不管路径在哪里 指定正确的路径即可) 2.操作步骤:复制MySQL安装目录-->修改my.ini中的端口2处.安装目录和数据目录---->命令安装MySQL windows服务--->修改注册表---->启动新实例的window服务---->正常使用 正文篇: 

[转载]window系统下TCP参数优化

注:此文转载自红黑联盟,最近服务器遇到周期性down掉的问题,拖了两三周请教了前辈之后才知道无关应用和数据库的事情,是tcp设置的问题.从网上找个这篇文章,解释的很不错.有兴趣请至红黑联盟翻阅原文. TCP连接的状态与关闭方式及其对Server与Client的影响 http://www.2cto.com/net/201304/206071.html 通常会采用修改注册表的方式改进Windows的系统参数.下面将为大家介绍Windows系统下的TCP参数优化方式,适用于Windows 2003.W

X86平台下用汇编写&quot;HelloWorld&quot;

首先需要安装一个汇编器,我用的是Nasm,这个汇编器在Linux下安装还是很简单的. Nasm下载地址http://www.nasm.us/pub/nasm/releasebuilds/ 在下载之后对其进行解压,然后进入到其目录下,会发现有configure文件,接下来相信对于熟悉Linux的同学就知道该怎么办了. 输入./configure然会待其执行完成后,会发现在目录下生成了一个Makefile文件,这是输入make命令,就可以完成对Nasm的编译了 然后进入root,输入make ins

转载:Ubuntu下deb包的安装方法

转载:Ubuntu下deb包的安装方法,http://blog.csdn.net/kevinhg/article/details/5934462 deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb dpkg 是Debian Package的简写,是为Debian 专门开发的套件管理系统,方便软件的安装.更新及移除.所有源自Debian的Linux发行版都使用dpkg,例如Ubuntu.Knoppix 等.以下是一些