关于 x86-64 分段模型中的限制和基地址的问题?

逆向工程 x86 风袋 x64 内核模式 分割
2021-06-28 04:52:14

我试图了解分段在 x86-64 下是如何工作的。据我所知,它主要是禁用的,但并非完全禁用。看起来 GS 和 FS 寄存器仍在使用它。

所以我正在使用 WinDbg 查看 Windows 7 x64 内核中段描述符的结构另外为了不立即使操作系统崩溃,我决定使用不使用分段的分段。说 SS 寄存器:

在此处输入图片说明

然后我决定在原始内存中修改它并通过lgdt指令重新加载它因此,我将其低 16 位更改为0x1234,因此(在内存中查看):

在此处输入图片说明

或者我是这么想的。当我运行dg命令时,它显示的限制为01234fff.

所以我有两个问题:

  1. fffWinDbg 报告的限制来自哪里(在第一个屏幕截图中以红色显示。)

  2. 段描述符中的 32 位基数如何包含整个 64 位平面寻址范围?

1个回答

Q1:在其手册“Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide, Part 1”中

Intel在“3.5.1 Segment Descriptor Tables”一章中写道:

“与段一样,将限制值添加到基地址以获得最后一个有效字节的地址。限制值为 0 导致恰好一个有效字节。因为段描述符总是 8 字节长,所以 GDT 限制应该总是比 8 的整数倍小 1(即 8N – 1)。”

这可以解释为什么 01234 的限制被填充为 fff,以满足该条件。

Q2:同手册,第 3.4.1 章“IA-32e 模式下的逻辑地址转换”:

“在64位模式下,段的偏移量和基地址是64位而不是32位。线性地址格式也是64位宽,受制于规范形式要求。每个代码段描述符提供一个L位. 该位允许代码段逐个代码段执行 64 位代码或遗留 32 位代码。”

尽管这回答了在 64 位模式下代码段中没有 32 位基地址的问题(如果我正确理解了他们的手册),但我无法在 p 上找到与图 3-8 对应的图片.3-10 使用 64 位基地址而不是 32 位基地址。可以从该图片中检索 L 位。然而,与其他位相比,它不是在 kd 中解码的。第一个(Privilege Level 0,最高)和最后一个(Privilege Level 3)代码段的 02xx Flags 值表示 L 位,并将这些代码段标记为 64 位段。

在 OP 的上截图中,Base 和 Limit 确实是 64 位,如果我做对了。但是,我不清楚到较低输出的映射。然而,我对 kd 的了解是有限的。

在此处输入图片说明

编辑

请求限制为 0x1234。该段被分页,如 G(粒度)位所示,并由 kd 解码。英特尔手册不是很清楚,IMO。如果进入手册“AMD64 架构程序员手册第 2 卷:系统编程”,它在第 81 页写道:

“将 G 位设置为 1 表示限制字段按 4 KB(4096 字节)缩放”,也在评论中提到。

这意味着以字节为单位的限制转换为 0x01234000。关于 0xfff 我假设系统的行为方式与在限制字段中输入 0 的方式相同。引用 AMD,第 81 页:“当 G=1 [即分页] 表明段限制为 4095 [=0xfff] 时,将限制设置为 0。如果系统以相同的方式处理此处提出的请求,这将导致0x01234fff 的限制值。

然而,另一个不确定性仍然存在。给出的解释假设 WinDbg 以字节而不是 4K 页显示限制。