最近我刚刚开始学习Windows内核漏洞利用,因此决定以博客的形式分享一些我的学习心得。
之前的部分我介绍了如何搭建环境:
初学Windows内核漏洞利用(二):熟悉HEVD
初学Windows内核漏洞利用(一):搭建实验环境
现在我们将接触熟悉用于权限提升的载荷。
本部分我所用到的工具环境如下:
在(1)和(2)中所描述的环境;
nasm工具(下载网址:NASM);
HxD工具(下载网址:HxD - Freeware Hex Editor and Disk Editor)。
回顾一下,我们的攻击目标是存在漏洞的驱动程序,我们将从用户层向其提交一段缓冲区数据。上一部分中,我们通过提交畸形的输入数据,成功触发了一些崩溃场景;然而我们的目标并不是破坏执行流程,而是通过精心构造输入来控制执行流程重定向到我们的代码中。
通常,传输载荷被用于提升攻击者应用程序的权限;而这可以通过窃取拥有更高权限的应用程序的访问凭证(关于访问凭证的具体含义,可参考相关维基百科,网址:Access token - Wikipedia)来实现。
查看访问凭证
系统中运行的每个进程都有其对应的EPROCESS数据结构,其中封装了所有与之相关的数据。该结构的完整定义,详见网址struct EPROCESS(EPROCESS数据结构在Windows操作系统的不同版本之间会有细微差别,更多信息参见网址EPROCESS)。EPROCESS结构的某些成员,比如PEB(Process Environment Block,进程环境块,具体含义可参考维基百科,网址:Process Environment Block),用户模式下即可访问;而另一些,比如所提到的访问凭证,只能在内核模式下访问。我们可以通过如下命令,使用WinDbg调试器查看EPROCESS结构的所有域成员,结果如下图所示。
dt nt!_EPROCESS
可见,结构起始位置到域成员Token的偏移为0xF8。
通过使用如下命令,让我们查看凭证中所包含类型的细节,结果如下图所示。
dt nt!_EX_FAST_REF
凭证存储于一个联合结构体_EX_FAST_REF中,其有两个域成员:RefCnt(引用计数)和Value。我们只对替代Value感兴趣;出于应用程序的稳定性考虑,最好不要改变引用计数。
现在,让我们查看被调试方主机上运行的某些应用程序的凭证。我们可以使用如下命令来列举进程:
!dml_proc
示例
结果如下图所示。
图中所示的第一列,是对应于特定进程的EPROCESS结构首地址。
现在,使用图中的地址,我们可以通过如下命令来发现更多选定进程相关的细节:
!process [address of EPROCESS]
在如下图所示的各个域成员之中,我们可以看到访问凭证。
通过如下命令,我们还可以在更低层次上查看凭证的具体内容:
dt nt!_EX_FAST_REF [address of EPROCESS] + [offset to the Token field]
命令执行结果如下图所示。
或者使用如下命令:
dd [address of EPROCESS] + [offset to the Token field]
结果如下图所示。
从上面的结果我们可以看出,!process命令会自动应用掩码,并从显示信息中过滤引用计数;我们可以通过使用最右3比特置零的掩码,在如下表达式求值的帮助下,人工实现相同的功能:
?[token] & 0xFFFFFFF8
结果如下图所示。
通过WinDbg调试器窃取访问凭证
作为练习,我们将在被调试方主机运行cmd.exe,并在调试方主机使用WinDbg调试器来提升其权限。
首先,列举所有进程;然后,显示查看选定进程System和cmd的访问凭证;之后,将System进程的访问凭证复制到cmd进程内,在这个过程中为了保持引用计数不变我们需要使用相应的掩码;最终,cmd.exe提权成功。
窃取凭证的载荷
现在我们需要通过注入代码来重现以上过程;当然这并不简单,因为我们不能再借助WinDbg调试器了。
在官方的HEVD知识库中,提供了一些用于窃取凭证的载荷的完整例子,作为漏洞利用代码的一部分(网址:https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/blob/master/Exploit/Payloads.c)。
代码中所包含的所有载荷的目的是相同的,即窃取访问凭证;然而我们可以看到,为了适应特定的漏洞,它们之间有一点差别。它们的代码大部分是相同的,只有结尾不同(该部分被称之为“内核恢复桩程序”);这部分代码被用于进行必要的清理工作,以便在载荷部分执行完成返回之后,应用程序不会崩溃。
接着,我们看一个通用版本(网址:https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/blob/master/Exploit/Payloads.c#L186),具体代码如下图所示。
首先,我们必须找到EPROCESS结构的起始位置。使用WinDbg调试器这轻而易举,一条命令就可以显示该信息;现在,我们需要从其他的域来顺藤摸瓜,自己动手找到该结构的起始位置。
我们使用KPCR(Kernel Processor Control Region,内核处理器控制区域)结构作为起点,32位Windows操作系统上的FS寄存器(64位系统上则是GS寄存器)指向该结构。
上图中所述的代码利用了以下结构之间的关系:
KPCR(PrcbData)->KPRCB(CurrentThread)->KTHREAD(ApcState)->KAPC_STATE(Process)->KPROCESS
KPROCESS结构是EPROCESS结构的第一个域,如下图所示;因此,通过找到它我们最终找到了EPROCESS结构的起始位置。
当前进程的EPROCESS结构找到之后,我们将利用其另一个域来找到SYSTEM进程的EPROCESS结构,如下图所示。
LIST_ENTRY是双向链表的一个成员类型,该表将所有正在运行的进程连接到一起。该结构的具体定义如下图所示。
其域成员Flink指向另一个进程的LIST_ENTRY域;因此,通过该指针索引并替代域成员的偏移,我们可以得到指向另一个进程的EPROCESS结构的指针。
然后,我们需要获取PID值(对应于域成员UniqueProcessId),并将其与System进程的特有PID进行比对;PID值在EPROCESS结构中的位置如图所示。
漏洞利用中对应以上过程的代码片段,如下图所示。
在获取我们的进程和System进程的EPROCESS结构之后,我们就可以将凭证从一方复制到另一方。在以下代码中,引用计数并没有保留(如下图所示)。
使用WinDbg调试器查看特定域成员的偏移非常方便,我们可以使用如下命令来显示指定结构的具体定义:
dt nt!
例如:
dt nt!_KPCR
结果如下图所示。
之后执行如下命令:
dt nt!_KPRCB
结果如下图所示。
因此,计算可得_KTHREAD的偏移为 0x120 + 0x004 = 0x124。
代码片段中给出上述偏移,如下图所示。
编写载荷
正如HEVD中的漏洞利用代码(网址:https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/blob/master/Exploit/Payloads.c#L63)所演示的那样,我们可以使用内嵌汇编(封装于C/C++代码之中)来编写载荷代码。
然而,在这种情况下,编译器将对我们的代码进行加工;如下图所示,代码前后添加了多余的前缀和后缀。
这就是我们在执行返回之前,通过堆栈指针(ESP)加上12(0xC)字节的方式,从堆栈中移除多余的DWORD类型数据的原因,具体代码(网址:https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/blob/master/Exploit/Payloads.c#L94)如下图所示。
如果想避免麻烦,我们可以将函数声明为裸代码类型(更多内容详见网址:Naked Function Calls);这可以通过在函数之前添加一个特殊声明来实现,例如如下代码(网址:https://github.com/hasherezade/wke_exercises/blob/master/stackoverflow_expl/payload.h#L16):
__declspec(naked) VOID TokenStealingPayloadWin7()
另一个选择是外部编译其汇编代码,例如使用NASM编译器;之后,我们可以将编译缓冲区内容导出为十六进制字符串。
作为练习,我们还将对上述载荷代码加以细微的修改,使其能够保持引用次数不变,具体代码(网址:hasherezade/wke_exercises)如下图所示。
使用如下命令,编译代码:
nasm.exe shellc.asm
然后,我们使用十六进制编辑器打开编译结果,并复制字节;某些十六进制编辑器(比如HxD)甚至支持以特定编程语言的数组格式来复制数据,如下图所示。
在我针对HEVD的栈溢出漏洞利用示例中,你可以找到内嵌和外部编译两个版本的载荷代码,具体代码网址:hasherezade/wke_exercises,编译后代码网址:https://drive.google.com/open?id=0Bzb5kQFOXkiSWTJOS2VZZ0JiU3c。
利用该漏洞的细节将在下一部分详细介绍,也可以阅读附录中所提到的Osanda和Sam的文章。
本文由 看雪翻译小组 木无聊偶 编译,来源 hasherezade's 1001 nights
转载请注明来自看雪论坛
如果你喜欢的话,不要忘记点个赞哦!