本文是阅读《0day安全:软件漏洞分析技术》后的笔记。
内核漏洞主要的作用包括:远程任意代码执行,本地权限提升,远程拒绝服务攻击,本地拒绝服务攻击。从漏洞的利用来看,远程拒绝服务和本地拒绝服务类型的内核漏洞利用起来比较简单,不必过多地考虑“构造”(构造漏洞成功触发的条件和数据)。相反,远程任意代码执行和本地权限提升类型的内核漏洞,利用起来往往比较复杂,需要有精心的构造,包括漏洞触发条件的构造,相关数据的构造等。
从公布的漏洞数量来看,远程任意代码执行类型的内核漏洞已经很少见了,更多的是本地权限提升类型的内核漏洞。(说的没错,老铁!!!)
目前主要有这三种:任意地址写任意数据
、固定地址写任意数据
和任意地址写固定数据
类型的内核漏洞。
目前常见的内核漏洞利用方法主要有两种:一是篡改内核内存数据;二是执行 Ring0 Shellcode。
执行 Ring0 Shellcode的实现:
例如 SSDT(SystemService Dispatch Table)、HalDispatchTable 等。如果能修改这些表中的内核 API 函数地址为事先准备好的 ShellCode 存放的地址(本进程空间内存地址),然后在本进程中调用这个内核 API函数,这样便实现了在 Ring0 权限下执行 Shellcode 的目的。
在选用内核 API 函数的时候,一定要选用那些“冷门”函数,最好是那些不常被调用的函数。因为我们的 Shellcode 保存在自己进程的 Ring3 内存地址中,别的进程无法访问到,别的进程一旦也调用这个内核 API 函数,就会导致内存访问错误或内核崩溃,是相当危险的。
调用门/中断门/任务门/陷阱门。有兴趣的可以学习一下四门机制。
四门机制是出入 Ring0/Ring3 的重要手段。若能在系统中成功添加一个门,就能在后续代码中,自由出入 Ring0 和 Ring3。
这里以调用门为例,展示如何利用瑞星这个漏洞向系统中添加一个调用门。调用门描述符可以放在 GDT、LDT 中,但是不能放在 IDT 中。在 Windows XP 中,没有 LDT。也就是说,我们要添加调用门需要修改 GDT。Ring3 实际上是可以获取 GDT 地址的,通过 sgdt 指令即可。因此我们的思路就是,在 Ring3 获取 GDT 地址,然后通过这个漏洞来修改 GDT,添加调用门。
DPL 为 3 表示 Ring3 有权限调用,调用无参数。DT=0,说明是系统段描述符和门描述符。类型为二进制的 1010,即 0xA,表示“执行/读”属性。
调用此新添加的调用门后,实际上是以 Ring0 权限调用了 GDT 中 0 偏移处的代码,而 GDT 偏移处的第一个指令是一条返回指令,即 0xC3。那么在 Ring3 调用该调用门后,就会直接返回,并且携带有 Ring0 的权限。
利用过程可以大致分成以下 5 个步骤:
- 获取 HalDispatchTable 表地址
HalDispatchTable 是由内核模块导出的。要得到 HalDispatchTable 在内核中的准确地址,首
先要得到内核模块的基址,再加上 HalDispatchTable 与内核模块基址的偏移。
有了这个表的地址 x,那么x+4 便存放的是 HalQuerySystemInformation 函数地址。 - 在 0x0 处申请一段内存,并写入 Ring0 Shellcode
在指定的地址申请内存,推荐使用 ZwAllocateVirtualMemory 函数,该函数第二个参数BaseAddress 是一个指针,指向的值便是您指定的要申请内存的地址。系统会从指定的地址开始向下搜寻,找到一段需要大小的内存。 - 利用漏洞向地址 x+4写入 0x0
- 调用 NtQueryIntervalProfile 函数