今天,我们来讲一下内核安全!
本文章仅提供学习,切勿将其用于不法手段!
目前,在渗透测试领域,主要分为了两个发展方向,分别为Web攻防领域和PWN(二进制安全)攻防领域。在PWN的二进制领域,免杀技术,一直是后渗透利用阶段的重要安全技术之一。
想要免杀,需要了解的安全技术知识包括软件加壳、代码混淆(例如,使用花指令)、隐匿技术(例如,Rootkit技术)、动态加密等内容。
接上一篇文章,我们来继续讲述下 Rootkit技术 的相关基础知识点内容!
我们讲到了 GDT 全局描述符表、LDT 局部描述符表、段选择器、段描述符、实模式、保护模式等相关的知识点内容。
学习 Rootkit 技术,这些必要的知识,是学习 Rootkit技术 的 前置知识基础!
大家可以把这些知识,理解为 是 学习 Rootkit 技术 的 前置任务。
上一篇文章中,我们重点讲述了 段选择器 和 段描述符,现在我们来讲一下,线性地址,是如何被合成的!接下来,如果时间宽裕,我们还可以继续讲一下,线性地址,是如何转换成物理地址的!
想要了解线性地址的合成,我们就必须要知道两个非常重要的寄存器!
它们是,GDTR 全局描述符表 寄存器,还有 LDTR 局部描述符表 寄存器 。
细心的童鞋儿,会发现,GDTR 和 LDTR 寄存器,在命名规则上,除了首字母不同,其它都是相同的!那么 首字母的不同,说明着什么呢? GDTR 寄存器 的 命名中, G 是 Global 全局的意思!
LDTR 寄存器 的命名中,L 是 Local 本地的意思!
我们通过命名规则,即可看出。GDTR 和 LDTR 寄存器 在 用途上的不同 !
GDTR 寄存器 用于 指向 全局描述符表的 线性地址!
是的! GDTR 寄存器中存储的,就是 线性地址 !!!!
重要的事情,说三遍! GDTR 寄存器中存储的内存地址,是线性地址!GDTR 寄存器中存储的内存地址,是线性地址!GDTR 寄存器中存储的内存地址,是线性地址!
LDTR 寄存器 用于 指向 局部描述符表 !我们需要知道, LDTR 寄存器中,存储的 并不是内存地址! LDTR 寄存器 中 存储 的是 指向 GDT全局描述符表 中 对应 LDT 局部描述符表 的 段描述符 的 GDT全局描述符表 子项 索引值 信息 !!!
LDTR 寄存器 中存储的 索引信息(通常是一个数字),指向 存储了局部描述符表对应内存空间信息的 GDT全局描述符表子项。 GDT全局描述符表 中存储了多个不同的 LDT 局部描述符表( LDT 段 ) 所对应的不同内存空间信息(所谓的内存空间信息,指的就是 段基址、段限长、段属性 这些信息)!在 GDT 全局描述符表中,LDT 局部描述符表,也被当作一个普通的 " 段 " 来对待!在 GDT 全局描述符表中, LDT 局部描述符表 被当作 LDT 段进行使用!含有 LDT 段 的 段基址、段限长、段属性 信息 的 段描述符,在 GDT 全局描述符表中,被当成普通的 段描述符 进行使用!
随着进程的切换,我们只要改变 LDTR 局部描述符表 寄存器 的 内容值,那么 就可以十分方便地切换到当前进程所对应的LDT 局部描述符表!
LDTR 局部描述表 寄存器 指向 全局描述符表子项 的这种设计,非常有利于进程的快速切换,以及各任务之间的数据隔离!不同的进程,不同的数据,存储在不同的物理内存之上,尽管不同进程的线性地址,可能是不同的,也可能是相同的!尽管不同进程需要使用到的物理地址,可能是不同的,也可能是相同的!但是!如果遇到两个进程,真的需要使用同一块物理内存空间的情况,那么我们也完全可以选择(事实上,操作系统内核,也是这么去实现的),将当前物理内存的数据先以虚拟内存的方式转存到硬盘之上!之后,再将腾出的物理内存空间 留给 新的进程 使用!了解操作系统的实现原理,对于我们去进行 Rootkit 行为,是非常有利的!想要进行 Rootkit ,你必须足够了解 操作系统内核 , 你必须能够熟练进行 操作系统 的 内核级别编程 !
我们需要充分地认知到,每个进程,或者说,每个任务,都会存在一个独立的,独属于自己的 LDT 局部描述符表(也称为 " 本地描述符表 " )空间。每个独立的进程,都有自己独立的代码段、数据段、栈段 等内存空间!私有的 LDT 局部描述符表中,存储着 对应 自身进程 的 代码段、数据段、栈段的内存空间信息(段基址、段限长、段属性) 的 私有段描述符!
通过读取 段选择子 的 第3个比特位 (对应的 比特位索引 为 2 )T1 的内容值,我们可以知道,当前段的 段描述符,是需要到 GDT 全局描述符表 中去寻找,还是到 LDT 局部描述符表 中去寻找!
如果 段选择子 的 第3个比特位 (对应的 比特位索引 为 2 )T1 的内容值 为 0,则表示 段描述符 需要到 GDT 全局描述符表 中去寻找!找到 指定的 段描述符 后,我们就获得了 指定段 的 段基址、段限长、段属性 等信息,通过这些信息,我们就能够访问 指定的 内存段空间了!
如果 段选择子 的 第3个比特位 (对应的 比特位索引 为 2 )T1 的内容值 为 1,则表示 段描述符 在 LDT 局部描述符 表中!如果 段描述符 ,在 LDT 局部描述符表中,我们需要先去 LDTR 局部描述符表 寄存器 中 读取 LDT 局部描述符表(LDT 段)在 GDT 全局描述符表 中的 索引值!当我们通过使用 LDTR 局部描述符表 寄存器中存储的 LDT 段 在GDT 全局描述符表 中的 索引值, 在 GDT 全局描述符表 中找到 LDTR 寄存器内容值 所对应的 LDT 局部描述符表(LDT 段)的 段描述符 之后,通过解析 段描述符,我们就能获得 LDT 局部描述符表( LDT 段 )的 段基址、段限长、段属性 等信息!通过这些信息,我们可以十分轻松愉快地访问到 LDT 局部描述符表!再然后,我们就可以通过 段选择子 中的 段描述符表 索引信息,去 LDT 局部段描述符表 中寻找对应的 段空间信息(段基址、段限长、段属性)了!有了这些信息,我们就可以去访问 指定的 内存段空间 了!
GDT 全局描述符表 和 LDT 局部描述符表 的作用是什么?!
它们,会帮助我们得到 代码段、数据段、栈段 等的 段基址、段限长、段属性信息!
这是非常重要的!
如果,我们想通过虚拟地址( 这样的格式:段选择子 : 段偏移量 ),来定位线性地址!
我们需要先通过 段选择子 指定的 段选择子 内容,获得段基址!
之后,我们就可以通过 段基址 + 段偏移量 的方式,来定位 指定内存空间 的 线性地址 了!
你明白了吗?定位线性地址,我们需要 透彻理解 GDTR 全局段描述符表 寄存器 、LDTR 局部段描述符表 寄存器 、GDT 全局描述符表 、LDT 局部描述符表 等底层知识的硬性基础!
下一篇内容中,我们将重点讲解,线性地址 如何被转换成 物理地址!
(未完待续)
请关注下一篇,渗透测试之内核安全系列课程:Rootkit技术初探(三)