今天,我们来讲一下内核安全!
本文章仅提供学习,切勿将其用于不法手段!
目前,在渗透测试领域,主要分为了两个发展方向,分别为Web攻防领域和PWN(二进制安全)攻防领域。在PWN的二进制领域,免杀技术,一直是后渗透利用阶段的重要安全技术之一。
想要免杀,需要了解的安全技术知识包括软件加壳、代码混淆(例如,使用花指令)、隐匿技术(例如,Rootkit技术)、动态加密等内容。
接上一篇文章,我们来继续讲述下 Rootkit技术 的相关基础知识点内容!
在《 渗透测试之内核安全系列课程:Rootkit技术初探 》之前的文章中,我们讲述了 GDT 全局描述符表、LDT 局部描述符表、GDTR 全局描述符表 寄存器、LDTR 局部描述符表 寄存器 、一致性代码、非一致性代码、实模式、保护模式、线性地址 等非常重要的基础知识点内容!
这些内容,是学习 Rootkit 技术 的基础 !
今天,我们来重点讲解下 线性地址 到 物理地址 的 转换 !
注意,本章中的 比特位排序,是从 数字 1 开始计算的,第N位 对应的 比特位索引 为 第N位 - 1 。
注意,本章中的 字节排序,是从 数字 1 开始计算的,第N个字节 对应的 字节索引 为 第N个字节 - 1 。
说起,线性地址 到 物理地址 的 转换,我们不得不提起几个非常重要的 控制寄存器 !
CR0 寄存器、CR1 寄存器、CR2 寄存器、CR3 寄存器 。
其中,CR1 寄存器 ,并没有被实际使用,所以 暂时 忽略 !
这里,重点只讲 CR0 控制寄存器 、CR2 页故障线性地址寄存器、 CR3 页目录基址寄存器 !
CR0 控制寄存器,最重要的两个比特位,分别是第1位和第32位,刚好是 CR0寄存器的内容值的" 头 " 和 " 尾 " !
CR0控制寄存器的第1位 PE ,控制着 保护模式 的开启 与 关闭 !当 PE 位 是 1 时,保护模式 处于 开启状态 ,当 PE 位 是 0 时,保护模式 处于 关闭状态,此时 计算机 运行于 实模式 !
CR0控制寄存器的第32位 PG ,控制着 内存分页机制 的开启 与 关闭 !当 PG 位 是 1 时,内存分页机制 处于 开启状态 ,当 PG 位 是 0 时,内存分页机制 处于 关闭状态,此时 计算机 运行于 实模式 !
如果需要 启用 内存分页机制,那么 第 1 位 PE 位 和 第 32 位 PG 位 的值,均要为 1 !
在禁用 CPU 的 内存分页机制 时,线性内存地址 等同于 物理内存地址!
现在,让我们来科普一下 布尔值 和 布尔运算 存在 的 意义!
这主要是为了让您更加深刻地理解,0 和 1 所代表的 布尔运算 意义 !
在我之前发布的一些文章中,我提到了 布尔值 的 运算 !
非真即假,非假即真!不是真的?那么就一定是假的!不是假的?那么就一定是真的!
布尔值,只会存在 两个值,True 真,或者 False 假 !
在 计算机领域 的 二进制 世界 中,数字 1 ,通常代表 True 真 !
在 计算机领域 的 二进制 世界 中,数字 0 ,通常代表 False 假 !
在 计算机领域 的 二进制 世界 中,数字 1 ,通常代表 条件成立 !
在 计算机领域 的 二进制 世界 中,数字 0 ,通常代表 条件不成立 !
在 计算机领域 的 二进制 世界 中,数字 1 ,通常代表 开启 !
在 计算机领域 的 二进制 世界 中,数字 0 ,通常代表 关闭 !
这些知识,都属于 计算机领域 中 技术知识 学习方面 的 小技巧 !
CR2 页故障线性地址寄存器,主要用于 在页异常情况发生时,报告相应的出错信息。
当发生页异常时(例如,指定的内存页,并不存在!这时,会触发 缺页中断 )CPU 会把引起 缺页中断 的 线性地址 保存在 CR2 页故障线性地址寄存器 之中!
操作系统中的页异常处理程序(其实就是 缺页中断 所对应的 中断服务程序)可以通过检查 CR2 页故障线性地址寄存器 的 内容值 的方式,去筛查出 缺页中断 这个异常 是 由 虚拟地址空间(线性地址空间)中的哪一个页面不存在而引起的(CR2 页故障线性地址寄存器,主要用于定位错误,以及通过分页交换文件去辅助载入内存分页)!
我们需要知道,针对 缺页中断 ,从 硬盘 中 载入 对应的 页表资源 或 页资源,是由 缺页中断 对应的 中断服务程序 去完成的 !CR2 页故障线性地址寄存器,在 从 硬盘空间 向 内存空间 载入 指定页表资源 或 指定页资源 时,起到了非常重要的作用 !
CR3 页目录基址寄存器,主要用于 PDT 页目录表 或 PDPT 页目录指针表 的 物理寻址 !
CR3 页目录基址寄存器,存储了 PDT 页目录表 或 PDPT 页目录指针表 的 物理内存地址 !
在启用了 PAE 物理地址扩展的基础上,CR3 页目录基址寄存器 的 高 27 位,被用于 进行 PDPT 页目录指针表 的 物理地址寻址 !
上面提到了 CR3 寄存器,它主要用于存储 页目录 在 内存空间 中的 物理地址 !
我们需要知道,开启分页机制之前(例如,开启启动,在正式载入系统内核之前,此时,CPU 还工作于 实模式 之下 ),CPU 进行的 寻址操作 ,还是基于 物理内存地址 的 !只有在开启了 保护模式( 通过将 CR0 寄存器 的 第 1 个 比特位 PE位 的内容值置为 1 来实现 )和 内存分页机制 ( 通过将 CR0 寄存器 的 第 32 个 比特位 PG位 的内容值置为 1 来实现 )之后,CPU 进行的 寻址操作 ,才会基于 线性内存地址 去进行 !在 开启 保护模式 和 内存分页机制 时,务必要 将 CR3 寄存器 指向 页目录表 的 基址(页目录表在内存空间中的起始地址)(物理内存地址) !
我们必须清晰地认知,虚拟地址空间 是被 操作系统 虚拟出来的!虚拟地址空间,只是 操作系统 进行 内存管理 的 一种技术实现方式!虚拟地址空间 和 物理地址空间 之间 存在 映射关系,每一个进程,都拥有自己的虚拟地址空间!当进程切换,CR3 页目录基址 寄存器 中的内容值,也会发生变化!这意味着,CR3 页目录基址寄存器 将指向 新的物理内存地址!这代表着,虚拟地址空间,会随着进程切换行为,同时被切换掉!进程切换,虚拟地址空间,也会同步切换!
为什么 CR3寄存器 承担着 切换虚拟地址空间 的义务呢?
CR3寄存器,是页目录基址寄存器,它存储了页目录空间在内存空间中的物理内存地址!
CR3寄存器,是页目录基址寄存器,它指向了 内存空间 中的 页目录空间 !
CR3 寄存器,指定了页目录表 或 页目录指针表 在内存空间中的物理地址!记住,是物理地址!是物理地址!是物理地址!重要的事情,要说三遍 !!!!
CR3 寄存器,就相当于 大树的根系 ,它 存储着 页目录 的 内存物理地址!
与 CR3 寄存器 相关的 汇编指令,使用的是 内存物理地址!
CR3 寄存器,就像 树状 数据结构 中的 根节点 !
在 CPU 的 分页机制 中,存在着 页目录、页表、页 这样的 技术设计概念 !
我们已经说过了,CR3 寄存器,存储着 页目录 的 内存物理地址!
页目录、页表、页 这样的 技术架构设计 ,共同实现了 内存分页机制 的 树状 数据结构 !
页目录,相当于 大树的主干 !
页表,相当于 大树主干 上的 分叉 !
页,相当于 大树主干 的 分叉上 生长的 叶子 !
透彻理解,树状 数据结构,是 理解 CPU 分页机制 技术实现 方面 的 重要基础!
页目录中,存在很多的子项,每个子项 均 指向了 页表 在 内存空间 中的 物理地址 !
页表中,存在很多的子项,每个子项 均 指向了 页 在 内存空间 中的 物理地址 !
CPU 在 技术上实现 的 内存分页机制 ,除了 页目录、页表、页 这样的 技术架构设计 之外,线性地址 这种技术概念的出现,也是 实现 CPU 内存分页机制 的 重要基础!
线性地址、页目录、页表、页 等 技术架构设计 ,共同实现了 CPU 内存分页机制 !
线性地址、页目录、页表、页 等 技术架构设计 ,使 CPU 内存分页机制 的 技术实现 成为了可能 !
线性地址,有 32 位 和 64 位 之分!
32位 的 线性地址 ,用于 32位操作系统 下的 内存寻址 (最大寻址范围:4GB)!
64位 的 线性地址 ,用于 64位操作系统 下的 内存寻址 (最大寻址范围:64GB)!
本篇文章中,重点还是在 32位 操作系统 环境下 进行相关内容讲解!
在 32位 环境下,很多概念,都是向 4 对齐的 !
在 64位 环境下,很多概念,都是向 8 对齐的 !
无论是 32 位 的 操作系统环境,还是 64位 的 操作系统环境,都是以向 2 的整数倍 对齐的!
内存边界,一定会是 2 的 整数倍 !
在上面的内容中,我们简单的提到了 线性地址、页目录、页表、页 的 架构设计 !
现在,我们来重点讲一下 线性地址、页目录、页表、页 的方面的 技术实现 !
在 80386 以上规格的处理器环境中,32位操作系统环境下,内存分页 中的 页大小 是 4KB !
在 80386 以上规格的处理器环境中,64位操作系统环境下,内存分页 中的 页大小 是 8KB !
在内存空间中,bit 比特位 是 最基础的 内存空间存储单元 !
基础知识科普:8 BIT (比特位)= 1B(byte 字节);1024 B = 1 KB ;1024 KB = 1 MB ; 1024MB = 1 GB;1024GB = 1TB 。
在 32位环境下,以 Windows 系列 的 操作系统 举例 !
线性地址 从 0 开始,到 2 GB 结束 的 范围内的内存空间,是 用户态进程 的 内存使用空间 !
线性地址 从 2G 开始,到 4 GB 结束 的 范围内的内存空间,是 内核态进程 的 内存使用空间 !
在 Windows 系列 的 操作系统环境 中 ,地址内存分段模式,是 基于平坦模式 的 !
在 Linux 系列 的 操作系统环境 中 ,地址内存分段模式,是 基于平坦模式 的 !
在 平坦模式 下 ,操作系统 能够 访问 一个连续的、不分段的 地址空间 !所有的段(包括 代码段、数据段、栈段 等)都 被映射到同一个内存地址空间中!所有的段的段基址 都是 0 ,在32位环境下,段限长为 4GB,在64位环境下,段限长为64GB 。
记住了吗?Windows 和 Linux 的 内存分段模式,都是 基于平坦模式 的 !
32位 线性地址 的 第 23~32位,是 页目录表项 中的 子项偏移量 !
32位 线性地址 的 第 23~32位 的 内容值 ,加上 CR3寄存器 中的 页目录基地址(页目录在内存空间中的起始物理地址),即得到了 页目录表项 的 物理内存地址 !
32位 线性地址 的 第 13~22位 的 内容值 ,加上 页目录表项 中 存储的 子项偏移量,即得到了 内存分页 的 物理内存地址 !
32位 线性地址 的 第 1~12位 的 内容值 ,加上 内存分页 的 页基址(内存页的起始物理地址),即得到了 线性内存地址 对应的 物理内存地址 !
虚拟地址空间 ( 采用 线性地址 方式 进行 虚拟内存寻址 )与 物理地址空间 ( 采用 物理地址 方式 进行 物理内存寻址)之间,存在映射关系!一个进程,就会拥有一个虚拟地址空间!但是!物理地址空间,只会存在一个!这是 N 对 1 的 映射关系 !多个虚拟地址空间,通过进程切换(进程切换时,虚拟地址空间也会随之被切换!切换原理 :更改 CR3 寄存器 的 内容值!CR3 寄存器 存储了 指向 页目录表 的 物理地址 !物理地址被替换了,意味着 CR3寄存器 已经 指向了 不同的页目录表 !每个进程,都会拥有一个属于自己的页目录表!页目录表,是属于虚拟地址空间的!而每个进程,都会拥有一个虚拟地址空间!相应的,每个进程,都会存在一个页目录表),共享 同一个 物理地址空间 !
虚拟地址空间,是按 页 进行管理的!
物理地址空间,也是按 页 进行管理的!
虚拟地址空间 中的 页面大小 和 物理地址空间 中的 页面大小 相同!
在 Intel 系列的 芯片中,存在专门的电路,负责将虚拟地址(线性地址)转译为内存物理地址!
还记得 内存管理单元 (MMU)吗 (下面的内容,会有相应的介绍)?
虚拟地址空间,通过 树状 数据结构 对 虚拟地址空间 进行 创建 和 管理 !
在 虚拟地址空间 中,线性内存空间 是 连续的 !通过 树状 数据结构,的确可以实现 对于任意线性地址空间的操作访问 !
首先,根据 32位 线性地址 的 第 23~32位 的 内容值,结合 CR3寄存器 中的 页目录基地址 得到 页目录中对应子项(指定的页表) 的 物理内存地址(指定页表的内存空间基地址)!然后,根据
32位 线性地址 的 第 13~22位 的 内容值,结合 已获取的 指定页表的内存空间基地址 得到 页表中对应子项(指定的页) 的 物理内存地址(指定页的内存空间基地址)!最后,根据 32位 线性地址 的 第 1~12位 的 内容值,结合 已获取的 指定页的内存空间基地址 得到 线性地址 对应的 物理地址 !
在 虚拟地址空间 中,有些 虚拟页面(内存页面),并不存在对应的 物理页面,我们管这种情况,叫做 "页面缺失" !当这种情况发生时,会触发 页面缺失 中断,由 页面缺失 中断 对应的 处理程序(这种处理程序,通常是一种 中断服务例程 !不了解 中断服务 的童鞋儿,可以去看一下 王爽 老师 写的 《零基础入门汇编语言》 这本书 ),去将以虚拟内存形式存储于硬盘中的页面数据,从硬盘空间中取回!或许,这就是 虚拟内存 这个技术实现 的价值和存在意义!我们可以把这种行为,称为 " 数据交换 " !
什么是 虚拟内存 ?
我们需要知道,在 Windows 系列 的 操作系统环境 中, 虚拟内存 在技术实现本质上 就是 物理内存 + 分页文件 !
我们必须知道,分页文件,是被存储在 硬盘 上的 !
这里的 分页文件,指的就是 分页交换文件 !
在《Windows核心编程》一书的 第13个章节( 物理存储器和页交换文件 )内容中,重点讲解了 分页交换文件 和 物理存储器 之间 进行 数据交换的过程 这种非常重要的基础知识内容 !
在下一章内容中,我们将重点地去讲解 分页交换文件 和 物理存储器 之间 是 如何 进行 数据交换 的!下一章节中,我们将重点讲解 分页交换文件 和 物理存储器 之间 的 数据交换 过程 !
在不同的操作系统环境中,对于 虚拟内存 的技术实现,会略有不同 !
在下一章内容中,我们会主要 参考 Windows 系列 的 操作系统 进行相应的 内容讲解 !
还记得下面的这句话吗?
在 Intel 系列的 芯片中,存在专门的电路,负责将虚拟地址(线性地址)转译为内存物理地址!
是的!说到 线性地址 的 寻址,我们不得不重点提一下,CPU 的 内存管理单元 (MMU)!
CPU 的内存管理单元 (MMU)是什么东西呢 ?
内存管理单元 (MMU),的英文翻译为 " Memory Management Unit " !
内存管理单元 (MMU),也被称为 " 分页内存管理单元 ",英文翻译为 " paged memory management unit ",被简写为 " PMMU " !
内存管理单元 (MMU),是一种被用于处理 中央处理器( CPU )的 内存访问请求 的 计算机硬件 !
内存管理单元 (MMU)的功能,包括 虚拟地址(线性地址)到 物理地址(内存物理地址)的转换( 也就是,我们常说的,虚拟内存管理,或称为 虚拟地址空间 管理 !这里,涉及到了 虚拟地址空间 的相关概念 )!
内存管理单元 (MMU)的功能,包括 内存保护( 内存分页 的 执行保护,这里涉及到了 内存分页 的 访问权限 )!
内存管理单元 (MMU)的功能,包括 中央处理器高速缓存的控制( 这里主要指,对 CPU 中的 高速缓存部件 进行管控 )!
内存管理单元 (MMU)的功能,包括 在相对简单的计算机体系结构中,负责进行总线的仲裁(总线仲裁(bus arbitration),计算机 中多个 设备 或 模块 可能会同时去 申请 对于 总线 的 使用权 ,为 避免 产生总线 冲突 ,需由 总线仲裁机构 ,也就是 内存管理单元 MMU 去进行 合理控制 和 适当管理 那些 需要占用总线的申请者(计算机中的 设备 或 模块 等),当多个申请者同时提出总线使用请求时,需要以一定的优先算法去决策哪个申请者能够优先获得对于总线的使用权)!
内存管理单元 (MMU)的功能,包括 负责进行存储体切换( bank switching,在非常简单的计算机体系结构(例如,只有 8位 的 计算机设备)中 去执行 存储体切换 操作 !目前这块,笔者本人,也需要更加深入的理解,也许以后,会涉及到对这方面的更详细讲解 )。
大家一定要记住,内存管理单元 (MMU)这个硬件,是位于 中央处理器(CPU)之中的 !
CPU 的 内存管理单元 (MMU)的用途和价值,是什么呢 ?
CPU 可以直接通过 MMU,去找出 实际要访问 的 指定内存空间 的 物理内存地址 !
在保护模式下,MMU 内存管理单元 实现 的是 虚拟地址(线性地址)到 物理内存地址 的 转换过程 !
大家需要记住,虚拟地址(线性地址)到 物理内存地址 的 转换,是由 MMU 内存管理单元 去自动完成的!
(未完待续)
请关注下一篇,渗透测试之内核安全系列课程:Rootkit技术初探(四)