-
-
[原创]x64内核实验2-段机制的变化
-
发表于:
2023-10-6 16:44
9832
-
ia-32e模式简介
x86下的段描述符结构图如下

在x86环境下段描述符主要分为3个部分的内容:base、limit、attribute,而到了64位环境下段的限制越来越少,主要体现在base和limit已经不再使用而是直接置空,也就是默认强制为平坦模式
ia-32e模式使用的是64位内核文件,legacy是兼容模式使用的还是32位内核文件,我们这里不关注兼容模式
ia-32e模式下是支持32位和64位的文件的,此模式下就是之前说的强制平坦模式并且取消掉了任务门切换的能力(可能是本来在32位的环境下各个操作系统的实现就没有使用任务切换所以cpu在64位下把这个能力删掉了)
ia-32e模式的启动流程跟32位下差不多也是进来是实模式然后在msr寄存器里设置一些位开启ia-32e模式模式
ia-32e模式下的系统调用跟32位下差不多是通过syscall进入0环
rdmsr 命令可以查看msr寄存器的值
1
2
3
4
5
6
7
8
9
10
11
12
13
|
0 : kd> rdmsr c0000080
msr[c0000080] = 00000000 ` 00000d01
0 : kd> .formats d01
Evaluate expression:
Hex : 00000000 ` 00000d01
Decimal: 3329
Decimal (unsigned) : 3329
Octal: 0000000000000000006401
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00001101 00000001
Chars: ........
Time: Thu Jan 1 08 : 55 : 29 1970
Float : low 4.66492e - 042 high 0
Double: 1.64474e - 320
|
可以看到我的模式是d01通过.formats查看具体描述可以看到我当前的二进制位第8位是1(第八位是第九个)说明处于IA-32e模式
这里我们先介绍这些后面慢慢遇到了在说
非系统段描述符的变化
首先看一下白皮书里对64位代码段描述符给出的图

可以看到大部分段描述符的长度依旧是64位,但是基址和界限已经不再存储了,而是默认平坦,留下的大部分内容和32位是一致的,因为图例给出的是代码段所以s位是1type的第一位也是1,要说的是L位现在描述的是32位还是64位段
有区别的地方在于只有s位=1的时候段描述符是64位,s=0的时候段描述符是128位,这是因为在64位环境下我们的数据段和代码段都是强制平坦模式无需关注base和limit而系统段不是这样在系统段里存了段选择子和offset而64位环境下offset也就有64位所以他必须扩到16个字节来存储offset
举例说明就是如果是1就是64位,如果L=1那么push Xax会被翻译为push rax反之则是push eax
下面我们分析几个段描述符看一下
1
2
3
4
5
6
7
8
9
10
11
|
0 : kd> r gdtr
gdtr = fffff80580a99fb0
0 : kd> dq fffff80580a99fb0
fffff805` 80a99fb0 00000000 ` 00000000 00000000 ` 00000000
fffff805` 80a99fc0 00209b00 ` 00000000 00409300 ` 00000000
fffff805` 80a99fd0 00cffb00 ` 0000ffff 00cff300 ` 0000ffff
fffff805` 80a99fe0 0020fb00 ` 00000000 00000000 ` 00000000
fffff805` 80a99ff0 80008ba9 ` 80000067 00000000 `fffff805
fffff805` 80a9a000 0040f300 ` 00003c00 00000000 ` 00000000
fffff805` 80a9a010 00000000 ` 00000000 00000000 ` 00000000
fffff805` 80a9a020 00000000 ` 00000000 00000000 ` 00000000
|
00209b00 00000000 g=0 d=0 l=1 avl=0 p=1 dpl=0 s=1 type=1011
说明是一个64位的代码段描述符 dpl=0
00409300 00000000 g=0 d=1 l=0 avl=0 p=1 dpl=0 s=1 type=0011
说明是一个64位数据段描述符 dpl=0
这里要说明一下这个l位只对代码段生效
00cffb00 0000ffff g=1 d=1 l=0 avl=0 p=1 dpl=3 s=1 type=1011
是一个3环32位代码段
00cff300 0000ffff g=1 d=1 l=0 avl=0 p=1 dpl=3 s=1 type=0011
是一个3环32位数据段
00000000 fffff805 80008ba9 80000067这就是一个系统tss段
他的base是fffff805 80a98000系统段我们后面再说
怎么去验证呢,在windbg中可以使用dg命令加上段的偏移就可以显示目标段描述符的详细信息
如下可以看到我们分析的是对的
1
2
3
4
5
6
7
8
9
10
|
0 : kd> dg 10
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0010 00000000 ` 00000000 00000000 ` 00000000 Code RE Ac 0 Nb By P Lo 0000029b
0 : kd> dg 3 * 8
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0018 00000000 ` 00000000 00000000 ` 00000000 Data RW Ac 0 Bg By P Nl 00000493
|
系统段的变化
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-10-6 16:52
被幺幺满地乱爬编辑
,原因: