win10 x64内核 IA-32e 笔记
0x0 前言
21年11月份学习了32位的内核,但是准备腾讯比赛发现,是给的64位驱动,所以学习64位。
0x1 x86到x64的改变
IA-32e 模式:内核64位,用户64或32位
强制平坦段,不支持任务切换
Legacy 模式:内核32位,用户32位
支持非平坦段,任务切换,虚拟8086,实模式等
IA-32e:代码段,数据段仍使用64位描述符,强制平坦(FS, GS 除外)
TSS段描述符扩展到128位
TSS段不用来任务切换,主要保存一堆rsp备用指针
中断门描述符扩展到128位
IA32_EFER_MSR C0000080H
IA32_FS_BASE C0000100H
IA32_GS_BASE C0000101H
IA32_KERNEL_GS_BASE C0000102H
权限切换
系统调用:x64用户程序通过,syscall 进入内核
x86用户程序在 ring3 转入 x64 模式再进入内核
中断:只使用了一张idt表,内核可以根据栈上的保存cs判断先前模式
0x2 EFER_MSR
可以看见第8位是1 当前系统为64位。
IA-32e模式兼容 0x86 和 0x64 转换的时候不是cpu转换成32位,而是一直在IA-32e模式上。
0x3 GDT表
相比于32位,64位的gdt表描述符会特别少。弱化了段保护。
L 决定是否处于64位还是32位
64位cs的段描述符,可以看见没有对描述符做扩展。虚拟地址从32位改变为64位,但是没有扩展。现在的段描述符没有了基址界限(base address limiti)
基址64位现在就放不下,就引出了一个新概念强制平坦 所以现在代码段和数据段仍用了64位描述符
0x4 TSS段描述符改为128位
先找一个TSS段,然后查看基址发现什么也没有
现在应该找 高位的 fffff801+ 5420200 就能找到TSS段了
TSS段的内容也改变了
32位TSS段储存的都是一堆寄存器,现在储存的都是IST指针
0的位置空,直接偏移+4 就是RSP0 就是0环的RSP指针 如果一个3环要切换到0环,就会把寄存器放在这个RSP0里面
0x5 IDT表改变成128位
IDT表现在储存的都是中断门描述符
可以看到地址是 fffff801+4fa0+0500 学过32位内核的应该知道还是差不多的寻找方法
可以看一下改变成128位的idt,主要理解里面的IST 占了3位
有什么作用呢,我们可以看一下IST的位置 大多数都是设置为0,可以看一下上面的TSS表,就是对应其中的IST寄存器指针,等于多少的时候,就代表IST几指针寄存器(如04,对应IST4)对应不同的中断
可以看一下不同的中断对应的效果,比如2号中断,cpu强制校验,会给一个特殊的栈,8号中断DoubleFault就是蓝屏了 栈已经找不到,就会给一个栈。只要后面没有标记 Stack的就代表没有使用了IST栈指针。
现在idt表存储的都是中断门描述符,陷阱门和调用门,windows不用,任务门是已经不支持了
可以看一下 第三中断 就是int 3 (可以在自己电脑上拿ntoskrenl.exe 拉ida)
32位进入的时候要求内核的fs指向KPCR
在64位的时候就变成了不在内核fs指向KPCR,而是用gs寄存器指向KPCR,fs就留给32位用。
注意(强制平坦对 FS,GS是没有用的)
既然FS,GS没有扩展,那怎么办呢,提供了两个地址到这里寻找。
IA32_FS_BASE C0000100H
IA32_GS_BASE C0000101H
FS是读取不到的,因为这个上面说了是针对32位用户的,在内核无法读取
而且在用户态时,地址也会一直有改变
GS是有的,指向的就是KPCR
再看一下这个图,现在在64位内核里不直接写gs的值,(32位的时候都是 push 30h pop fs 这样写进) 现在是直接使用 swapgs指令 把当前的gs基址和gs_base切换
IA32_KERNEL_GS_BASE C0000102H 改变指向KPCR
存储了0环进系统之前的某一个TEB
0x6 总结
写笔记记录一下加深记忆,同时分享给大家。忘记了有笔记可以快速回顾。