内核漏洞利用:通过WARBIRD在Windows 10上提升权限

2017 年 12 月 9 日 FreeBuf Covfefe

在这篇文章中,我想谈一谈通过基于Windows内核的exploit来提升权限。之所以没有使用像HackSys Extreme Vulnerable Windows Driver这样的东西,是因为想做点不同的事情。恰逢Google Project Zero近期公布了漏洞,由于mjurczyk把漏洞进行了记录,所以感觉便于理解。该漏洞还被Microsoft标记为“Wont-Fix”,意思就是32位的Windows 10 Creator版本仍然存在漏洞。

漏洞概览

根据披露出的消息,我们可以了解到这个漏洞影响了32位Windows 10 Creators版本的更新。这个漏洞的存在是由于一个新的信息类“WARBIRD”被添加到NtQuerySystemInformation中,但是这个类在32位Windows 10上被错误处理了。
当触发漏洞时,内核指令指针被设置为NULL,在现代操作系统中,内存地址0h通常被限制以避免这些类型的漏洞被利用。然而谷歌已经确认,在Windows上启用了16位支持,特别是通过NTVDM使用NULL地址来支持16位程序执行的情况下,漏洞实际上是可利用的。
在编写exploit之前,我们需要先搭建环境。

搭建实验环境

为了能搭建实验环境,我们需要一些虚拟机:

Windows 10 Creators Update x86 - 这是靶机

带有WinDBG的Windows系统 - 这个供调试使用

在靶机上,我们需要使用以下命令启用16位支持:

FONDUE.exe /enable-feature:NTVDM

我们还需要启用内核调试,这可以通过以下命令来完成:

在执行之后,你会获得一个WinDBG用来在启动时建立主机连接的密钥。在我们的调试目的的主机中,我们需要启动WinDBG,并通过“File -> Kernel Debug”设置我们的内核调试会话:

重新启动靶机后,在WinDBG中会打开内核调试会话,并且会在利用过程中更容易地探索内核状态:

完成之后,我们就移步到exploit使用的重要概念—进程注入

进程注入

如果参考所公开的信息,那么将看到以下内容:

如果我们创建一个16位程序(如debug.exe),并将利用代码注入ntvdm,那么就可以防止系统在尝试写入nt!WbAddLookupEntryEx中的地址0时立即崩溃。

了解这个对于利用来说是非常重要的,我们需要理解进程注入是如何运作的,以及如何使用这种技术让NTVDM在其地址空间执行我们的代码,从而允许我们使用NULL映射页面。
Windows中的进程注入通常使用许多Win32 API(出于练习目的,我们会忽略其他技术,如Atom Bombing),具体为:

OpenProcess

VirtualAllocEx

WriteProcessMemory

CreateRemoteThread

你可以从API的描述中了解每个调用的作用,为了完整起见,还是在下面详细说明一下每个调用的作用:

OpenProcess.aspx):这个调用将从PID中检索一个Windows进程,从而允许我们对进程进一步地操作。

VirtualAllocEx.aspx):这个调用用于在目标进程中分配内存,为我们预留要添加自定义代码的空间,或者将参数传递给一个远程线程。

WriteProcessMemory.aspx):提供一个地址和一个进程句柄,这个调用可以允许我们将数据复制到远程进程地址空间。

CreateRemoteThread.aspx):这将允许我们在远程进程中创建一个新的线程,并指定执行的位置。

通过调用这些API,我们就可以将shellcode注入到NTVDM进程中,但是为了更简单一点,我们把一个DLL加载到NTVDM中。这样做有很多好处,DLL可以在Visual Studio这样的软件中创建,它还包含漏洞利用代码,且不必担心在运行时解析API的情况。
为了加载我们的DLL,我们将使用另一个Win32 API调用LoadLibrary,它可以获取DLL的路径并将其动态加载到进程地址空间中。 现在我们需要构建注入工具:

1.使用OpenProcess获取NTVDM进程的句柄。

2.使用VirtualAllocEx分配足够的空间以便复制我们的LoadLibrary参数值,这将成为用于利用的DLL的路径。

3.使用WriteProcessMemory将用于利用的DLL路径写入远程分配的内存。

4.最后,使用CreateRemoteThread生成一个线程并在远程进程中执行LoadLibrary调用,将复制的DLL路径地址作为参数传递。

如果我们用一个非常简单的DLL来运行,那么就可以看到NTVDM完美地调用了我们的代码:

构建exploit

目前我们可以将任意DLL加载到NTVDM进程中了,现在就需要开始考虑如何构建我们的exploit。一个建议提供了以下示例来触发此漏洞:

如果我们将这段代码添加到一个DLL中,并将其注入到NTVDM进程中,我们发现WinDBG会触发以下断点:

在这里我们可以看到EIP是00000000h,中断已经成功地被触发了….真棒,现在就控制内核的代码执行了:)
接下来就需要撸起袖子开始编写shellcode,该shellcode将会被exploit执行。

编写Shellcode

对于这个exploit,我想要编写shellcode来尝试获取“cmd.exe”会话的SYSTEM权限。不幸的是,shellcode做类似这样的事情并不像“bind tcp”那样简单,但是这里有几个质量较好的教程,例如@ samdb的优秀文档。
在这篇文章中,我们会创建自己的shellcode。要做到这一点,我们需要了解一些内核结构。(在这方面,如果你还没有阅读我以前的文章,【点击原文】阅读)。
与之前的文章类似,我们编写的shellcode将负责找到与cmd.exe和System进程对应的EPROCESS结构,然后将access token从System复制到cmd.exe,从而将我们提升到SYSTEM用户。 首先,我们需要找到我们的cmd.exe进程的EPROCESS。 为此,我们将从fs寄存器开始,它在32位Windows内核中指向nt!_KPCR结构。
KPCR是“内核处理器控制区”,其拥有关于当前正在执行的处理器状态的信息,我们还可以用来获取进程和线程的信息和许多有用的字段。
为了得到WinDBG中的fs寄存器地址,可以使用下面的命令:

dg fs

然后会返回像下图这样的东西:

上面的例子中,在地址80dd7000h中有我们的nt!_KPCR结构。知道了这一点,我们就可以使用下方命令查看KPCR的内容:

dt nt!_KPCR 80dd7000

偏移120h(在_KPCR结构的末尾)是nt!_KPRCB结构,可以通过以下命令查看:

dt nt!_KPRCB 80dd7000+0x120

这样我们就可以看到KPRCB结构,看起来就像这样:

我们在这里找的是在偏移4h(或KPCR开始的124h)处找到的,并且是对应于当前正在执行的线程的nt!_KTHREAD结构。我们可以使用下方命令转储这些信息:

dt nt!_KTHREAD 0x87507940

在偏移地址150h处,我们找到一个指向Process的指针,它对应于我们正在寻找的EPROCESS结构:

现在就可以访问EPROCESS结构了,我们可以使用ActiveProcessLinks属性(实际上是一个指向LIST_ENTRY的指针,它是一个双向链表)来枚举当前正在运行的所有进程,直到找到cmd.exe进程和SYSTEM进程。
要找到“cmd.exe”,需要使用在偏移150h处找到的EPROCESS.ImageFileName属性:

对于System进程,我们知道通常PID为“4”,所以可以在偏移量为b4h的UniqueProcessId属性中找。

构建后,最终的shellcode如下所示:

从内核返回

不幸的是,在处理内核漏洞利用时,如果不先确认操作系统是否处于安全状态,我们就不能让我们的利用返回。
当内核地址空间中的内存被破坏时,保持操作系统正常运行会变得非常困难,这个exploit也不例外。 简单地通过ret或ret 0xc指令将执行返回给内核将导致如下所示结果:

在这方面,能做的只有试图让内核恢复到安全状态以继续执行。
在这个exploit的情况下,我们需要了解为什么以及如何调用我们的函数。这个问题围绕着如下的结构:

我们也知道,在shellcode被调用的地方,调用堆栈看起来像这样:

如果我们反汇编shellcode之前的最后一个函数WbFindLookupEntry,就可以找到调用shellcode的位置:

在这里,dword ptr [ebx+14h]调用实际上是调用上述结构中的cmp_func属性,这意味着在进入shellcode时,ebx寄存器指向_WARBIRD_EXTENSION结构。
如果我们用WinDBG检查内存,会看到以下内容:

这表明,虽然struct memory的初始值是NULL,但偏移量为0x4的count属性被设置为1,导致内核试图对shellcode进行多次调用。为了避免这种情况,我们需要将count属性更新为0。
接下来,我们必须在没有任何异常的情况下从NtQuerySystemInformation调用中返回,在尝试清理_WARBIRD_EXTENSION结构并取得了一些成功,且经历许多蓝屏之后,我发现让内核恢复到正常状态的最快方法是简单地遍历每个堆栈帧,直到在ExpQuerySystemInformation继续执行。要做到这一点,我们需要检查每个执行的函数,直到执行结果被传递给shellcode,并将寄存器和内存值恢复到它们的原始值。
完成后,看起来像这样:

如果在上面更新shellcode,并重新运行exploit,会出现错误检查:

这是可以预料的,因为我们只是忽略了在内核中恢复APC执行的任何形式。 在这个例子中,我们可以简单地通过更新当前线程来修正这个错误:

如果在恢复APC后继续,我们发现会遇到了另一个异常:

这是由于我们的方法只是跳过内核释放锁获取的过程。为了让我们退出syscall,我们需要更新shellcode,通过将我们的线程值清零来从线程中删除锁定:

最后一步

剩下要做的就是编译shellcode并把它转换成一个C buffer,这个C buffer将被我们注入的DLL使用。
为了编译shellcode,我通常会使用nasm,在这个例子中可以这样调用:

nasm shellcode.asm -o shellcode.bin -f bin

然后我们可以使用Radare2提取一个不错的C buffer:

radare2 -b 32 -c 'pc' ./shellcode.bin


这里给了我们最终的exploit DLL的源代码:

完成后,运行一下试试:

视频


通过Windows 内核的提升权限利用到此就结束了。项目可以从Github上下载。【点击原文】

*参考来源:xpnsec,FB小编Covfefe编译,转载请注明来自FreeBuf.COM

登录查看更多
0

相关内容

shellcode是一段不依赖于上下文的可执行机器码。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【ICMR2020】持续健康状态接口事件检索
专知会员服务
17+阅读 · 2020年4月18日
【经典书】数据结构与算法C++,第二版,738页pdf
专知会员服务
166+阅读 · 2020年3月27日
深度神经网络实时物联网图像处理,241页pdf
专知会员服务
76+阅读 · 2020年3月15日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
179+阅读 · 2020年1月1日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
msf实现linux shell反弹
黑白之道
49+阅读 · 2019年8月16日
“黑客”入门学习之“windows系统漏洞详解”
安全优佳
8+阅读 · 2019年4月17日
支持多标签页的Windows终端:Fluent 终端
Python程序员
7+阅读 · 2019年4月15日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
10个深度学习软件的安装指南(附代码)
数据派THU
17+阅读 · 2017年11月18日
Factor Graph Attention
Arxiv
6+阅读 · 2019年4月11日
3D Face Modeling from Diverse Raw Scan Data
Arxiv
5+阅读 · 2019年2月13日
Learning Recommender Systems from Multi-Behavior Data
Arxiv
3+阅读 · 2018年6月14日
VIP会员
相关VIP内容
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【ICMR2020】持续健康状态接口事件检索
专知会员服务
17+阅读 · 2020年4月18日
【经典书】数据结构与算法C++,第二版,738页pdf
专知会员服务
166+阅读 · 2020年3月27日
深度神经网络实时物联网图像处理,241页pdf
专知会员服务
76+阅读 · 2020年3月15日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
179+阅读 · 2020年1月1日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
相关资讯
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
msf实现linux shell反弹
黑白之道
49+阅读 · 2019年8月16日
“黑客”入门学习之“windows系统漏洞详解”
安全优佳
8+阅读 · 2019年4月17日
支持多标签页的Windows终端:Fluent 终端
Python程序员
7+阅读 · 2019年4月15日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
如何用GitLab本地私有化部署代码库?
Python程序员
9+阅读 · 2018年12月29日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
10个深度学习软件的安装指南(附代码)
数据派THU
17+阅读 · 2017年11月18日
Top
微信扫码咨询专知VIP会员