x64内核实验2-段机制的变化

news2024/12/23 11:22:23

x64内核实验2-段机制的变化

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寄存器的值

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

下面我们分析几个段描述符看一下

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命令加上段的偏移就可以显示目标段描述符的详细信息
如下可以看到我们分析的是对的

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
系统段的变化

我们这边只介绍调用门和中断门,任务门在白皮书里明确说明x64下不提供此能力,陷阱门没找到对应章节暂不处理

1.调用门

首先看一下调用门在x64下的描述符结构和32位下的对比
在这里插入图片描述

这是32位下的
在这里插入图片描述

可以看到描述符扩充到了128位低32位跟32位环境下是一模一样的只是不在提供有参的形式了(这也是对32位环境兼容的一种做法)高64位的低32字节用作offset,图中高64位的type暂时没看到有什么用
下面我们做一些实验来熟悉调用门
实验:

  1. windbg创建自己的调用门,并在应用层调用

首先描述出我们要添加的调用门的属性
selector 0013
offset 00007ff8 85420960
p=1
dpl=11
s=0
type=1100
根据属性构造出调用门(注意windbg的eq是一次写入64位而我们分两次写要小心大小端序的问题)
8542ec0000130960 0000000000007ff8

在这里插入图片描述

我们的selector是 0x63

2.TSS段描述符

tss段是变化比较大的一个系统段描述符,下面是白皮书里的段描述结构图,他变化的点不在于这个段描述符的结构变化而是TSS所描述的内存块中存储的内容发生了比较大的变化,也就是TSS这个数据结构变化是比较大的
在这里插入图片描述

我们来对比这看一下
这是我们比较熟悉的32位环境下的tss结构,然后我们在看一下64位下的变化
在这里插入图片描述

这是64位下的tss结构,可以发现里面不在存储各种各样的寄存器了而是存储的ISTX
这个IST是中断栈表,每一个都存储了64位的esp地址相当于32位下的esp0 esp1 esp2等位置,其中IST0就是esp0,IST3就是esp3,这种变化的原因我想可能有两个,一个是在64位下不再提供任务切换的能力,第二个就是tss这个结构本身在32位操作系统中也就只使用了esp0,所以在64位下干脆就不存储其他的寄存器只提供存储各种各样的esp的能力,在线程切换时候就可以直接替换对应的ist0或者ist3就可以切换当前的栈
大家可能觉得疑惑我们只有0123四种权限级别为啥提供了一大堆的ist都干到ist7了,这是因为64位的中断门也发生了变化中断门会使用这个ist位,等下我们看到中断门的时候再详细描述,现在我们只要记住tss中存储了一大堆的esp基址分别对应了一个和一个的ist变化就可以了
在这里插入图片描述

3.中断门

首先我们还是看一下白皮书里对64位中断门的描述
在这里插入图片描述

下面是我在网上找的32位下中断门描述符的图
在这里插入图片描述

可以看到64位和32位下中断门的变化跟调用门差不多属性位置都没有变然后高64位中多存储了32位的偏移地址,不过注意看一下在64位下多出了一个属性字段IST,我们回想一下刚刚的tss中是不是有一大堆istX,那个就是给这里用的,当我们通过中断进入0环的时候会根据中断门的ist位来切换当前的堆栈
我们来看一下我环境上的idt表
在这里插入图片描述

我图中圈出来的就是ist位,它代表了调用这个中断门切换esp时候所使用的tss中对应的ist编号
如下,部分中断就会用一些比较特殊的栈
在这里插入图片描述

大家可以自己调用一下中断来看一下栈的变化能够更好的理解中断门在64位环境下的变化

SAMP和SEMP

SMAP(Supervisor Mode Access Prevention,管理模式访问保护)和SMEP(Supervisor Mode Execution Prevention,管理模式执行保护)的作用分别是禁止内核CPU访问用户空间的数据和执行用户空间的代码,并不会因为你权限高就能访问/执行低权限的资源,你的就是你的,我的就是我的

这里两个检查的控制位分别是cr4的第20位和第21位
当这两位为1的时候意味着0环不可以访问和执行三环地址,运行时就会进行检查

现在我们可以做一些实验了
实验1:
通过驱动在0环读取idt表和idt表并解析出信息打印出来,大家可以试一下不开smap和开启smap的时候我们的代码运行时有什么区别

实验代码:

#include <wdm.h>
//#include <ntifs.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include <intrin.h>
#pragma pack(1)
struct Attribute
{
	UINT64 offset1 : 16;
	UINT64 p : 1;
	UINT64 dpl : 2;
	UINT64 s : 1;
	UINT64 type : 4;
	UINT64 unuse : 6;
	UINT64 ist : 2;
	UINT64 selector : 16;
	UINT64 offset2 : 16;
};
typedef struct _IDT_ENTRY64 {
	
	union hightStruct
	{
		UINT64 lower;
		struct Attribute attribute;
	};
	UINT64 hight;
}IDT_ENTRY64, * PIDT_ENTRY64;

typedef struct _IDTR
{
	UINT16 limit;
	UINT64 base;
}IDTR, *PIDTR;
#pragma pack()




VOID Unload(PDRIVER_OBJECT pDriver) {
	KdPrint(("unload\r\n"));

}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
	NTSTATUS status = STATUS_SUCCESS;


	pDriver->DriverUnload = Unload;
	KdPrint(("start\r\n"));
	//关闭smap和smep
	UINT64 cr4 = __readcr4();
	cr4 &= 0xffffffffffcfffff;
	__writecr4(cr4);
	IDTR idtr = { 0 };
	PIDT_ENTRY64 idtEntryArr = NULL;
	__sidt(&idtr);
	KdPrint(("idt base:0x%llx, limit:0x%x\r\n",idtr.base ,idtr.limit));
	if (idtr.base == NULL && idtr.limit <= 0) {
		return STATUS_UNSUCCESSFUL;
	}
	idtEntryArr = (PIDT_ENTRY64)idtr.base;
	DbgBreakPoint();
	SIZE_T i = 0;
	while (i < (idtr.limit / 16))
	{
		UINT64 hight = idtEntryArr->hight << 32;
		UINT64 lower_1 = (idtEntryArr->lower & 0xffff000000000000) >> 32;
		UINT64 lower_2 = (idtEntryArr->lower & 0x000000000000ffff);
		UINT64 offset = hight + lower_1 + lower_2;
		UINT16 selector = (idtEntryArr->lower & 0x00000000ffff0000) >> 16;
		
		KdPrint(("中断门 index=%llu---offset=0x%llx---selector=0x%x---p=%d---dpl=%d---type=%d---ist=%d\r\n", 
			i, offset, (UINT32)selector, (UINT32)idtEntryArr->attribute.p,
			(UINT32)idtEntryArr->attribute.dpl, (UINT32)idtEntryArr->attribute.type,
			(UINT32)idtEntryArr->attribute.ist));
		i++;
		idtEntryArr++;
	}
	KdPrint(("end\r\n"));
	return status;
}

T32)idtEntryArr->attribute.p,
(UINT32)idtEntryArr->attribute.dpl, (UINT32)idtEntryArr->attribute.type,
(UINT32)idtEntryArr->attribute.ist));
i++;
idtEntryArr++;
}
KdPrint((“end\r\n”));
return status;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

U盘里文件损坏无法打开怎么恢复?

U盘&#xff0c;全称为USB闪存盘&#xff0c;是一种体积小巧、传输数据速度快的便携式存储设备。由于其出色的便捷性和高效性&#xff0c;U盘在各个工作领域和日常生活中得到了广泛应用&#xff0c;赢得了消费者的普遍好评。然而&#xff0c;使用U盘的过程中也可能会面临数据损…

Zabbix配置监控文件系统可用空间小于30GB自动告警

一、创建监控项 二、配置监控项 #输入名称–>键值点击选择 #找到磁盘容量点击 注&#xff1a; 1、vfs 该键值用于检测磁盘剩余空间&#xff0c;zabbix 内置了非常多的键值可以选着使用 2、单位B不需要修改&#xff0c;后期图表中单位和G拼接起来就是GB 3、更新时间 10S…

Qt扫盲-QSqlTableModel理论总结

QSqlTableModel理论总结 一、概述二、使用1. 与 view 视图绑定2. 做中间层&#xff0c;不显示 三、常用函数 一、概述 QSqlTableModel是用于从单个表读写数据库记录的高级接口。它构建在较低级的QSqlQuery之上&#xff0c;可用于向QTableView 等视图类提供数据。这个主要是对单…

基于三平面映射的地形纹理化【Triplanar Mapping】

你可能遇到过这样的地形&#xff1a;悬崖陡峭的一侧的纹理拉伸得如此之大&#xff0c;以至于看起来不切实际。 也许你有一个程序化生成的世界&#xff0c;你无法对其进行 UV 展开和纹理处理。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 三平面映射&#xff08;Trip…

【C++】String -- 详解

⚪C语言中的字符串 C 语言中&#xff0c;字符串是以 \0 结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C 标准库中提供了一些 str 系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合 OOP 的思想&#xff0c;而且底层空间需要用户自己…

Java实现整数互转罗马数字基本算法

目录 一、罗马数字的起源&#xff1f; 二、算法代码 &#xff08;1&#xff09;整数转罗马数字算法代码 &#xff08;2&#xff09;罗马数字转整数算法代码 三、测试结果 &#xff08;1&#xff09;整数转罗马数字测试结果 &#xff08;2&#xff09;罗马数字转整数测试…

GD32F103 硬件 IIC

1. 硬件IIC 1. 硬件IIC的框图 如果MCU做为主机SCL就做为输出&#xff0c;做从机SCL就做为输入。 主机&#xff1a; 当MCU作为主机发送数据流程从数据缓冲寄存器里拿到移位寄存器。在从移位寄存器一位一位发送。 当MCU作为主机接收数据流程先放到移位寄存器。在从移位寄存…

微信小程序软件著作权申请成功!

软件著作权登记是对自己开发的软件享有著作权的一种保障&#xff0c;也是对自己开发能力的一种认证&#xff0c;在个人找工作或者公司拿项目资质审查时都可能发挥作用。我成功开发了一款微信小程序后&#xff0c;便了解了许多相关资料&#xff0c;花钱请代理代办速度快、省事&a…

Visopsys 0.92 发布

Visopsys 是一个 PC 机的操作系统&#xff0c;系统小型、快速而且开源。有着丰富的图形界面、抢先式多任务机制以及支持虚拟内存。Visopsys 视图兼容很多操作系统&#xff0c;但并不是他们的克隆版本。Visopsys 0.92 现已发布&#xff0c;此维护版本引入了多任务处理程序、文件…

C++标准模板(STL)- 类型支持 (定宽整数类型)(int8_t,int_fast8_t,int_least8_t,intmax_t,intptr_t)

定宽整数类型 类型 定义于头文件 <cstdint> int8_tint16_tint32_tint64_t (可选) 分别为宽度恰为 8、16、32 和 64 位的有符号整数类型 无填充位并对负值使用补码 &#xff08;仅若实现支持该类型才提供&#xff09; (typedef) int_fast8_tint_fast16_tint_fast32_tint…

进程调度算法之先来先服务(FCFS),短作业优先(SJF)以及高响应比优先(HRRN)

1.先来先服务&#xff08;FCFS&#xff09; first come first service 1.算法思想 主要从“公平”的角度考虑(类似于我们生活中排队买东西的例子) 2.算法规则 按照作业/进程到达的先后顺序进行服务。 3.用于作业/进程调度 用于作业调度时&#xff0c;考虑的是哪个作业先…

Spring 原理

它是一个全面的、企业应用开发一站式的解决方案&#xff0c;贯穿表现层、业务层、持久层。但是 Spring仍然可以和其他的框架无缝整合。 1 Spring 特点 轻量级控制反转面向切面容器框架集合 2 Spring 核心组件 3 Spring 常用模块 4 Spring 主要包 5 Spring 常用注解 bean…

【HTTP】URL结构、HTTP请求和响应的报文格式、HTTP请求的方法、常见的状态码、GET和POST有什么区别、Cookie、Session等重点知识汇总

目录 URL格式 HTTP请求和响应报文的字段&#xff1f; HTTP请求方法 常见的状态码 GET 和 POST 的区别 Cookie 和 Session URL格式 &#xff1f;&#xff1a;是用来分割URL的主体部分&#xff08;通常是路径&#xff09;和查询字符串&#xff08;query string&#xff09;…

MyBatisPlus(九)模糊查询

说明 模糊查询&#xff0c;对应SQL语句中的 like 语句&#xff0c;模糊匹配“要查询的内容”。 like /*** 查询用户列表&#xff0c; 查询条件&#xff1a;姓名包含 "J"*/Testvoid like() {String name "J";LambdaQueryWrapper<User> wrapper ne…

十天学完基础数据结构-第六天(树(Tree))

树的基本概念 树是一种层次性的数据结构&#xff0c;它由节点组成&#xff0c;这些节点按照层次关系相互连接。树具有以下基本概念&#xff1a; 根节点&#xff1a;树的顶部节点&#xff0c;没有父节点。 子节点&#xff1a;树中每个节点可以有零个或多个子节点。 叶节点&am…

力扣第102题 广度优先搜索 二叉数 c++

题目 102. 二叉树的层序遍历 中等 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20…

八大排序算法汇总(C语言实现)

本专栏内容为&#xff1a;八大排序汇总 通过本专栏的深入学习&#xff0c;你可以了解并掌握八大排序以及相关的排序算法。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;八大排序汇总 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库…

【1++的刷题系列】之双指针

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的刷题系列】 文章目录 一&#xff0c;什么是双指针二&#xff0c;相关例题例一例二例三例四例五 一&#xff0c;什么是双指针 常见的双指针有两种形式&#xff1a;一种是对撞指针&#xff08…

tinymce富文本编辑器【tip】

项目场景&#xff1a; tinymce富文本编辑器在iview的modal框中显示的问题 问题描述 最近在使用tinymceiviewvue写项目&#xff0c;在富文本编辑器配合弹框一起使用时&#xff0c;总是存在问题&#xff1a;弹框弹出的时候&#xff0c;富文本编辑器不能点击&#xff0c;鼠标的光…

【软考】PV 操作

#国庆发生的那些事儿# 临界资源: 诸进程间需要互斥方式对其进行共享的资源&#xff0c;如打印机、磁带机等临界区: 每个进程中访问临界资源的那段代码称为临界区信号量: 是一种特殊的变量。 信号量的值与相应资源的使用情况有关: ①: 当信号量的值大于0时&#xff0c;表示当…