VOID CProcessControl::UnInitialize() { ADD_LOG(); if (m_hExitEvent!= NULL) SetEvent(m_hExitEvent); if (m_hThread != NULL) { if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) TerminateProcess(m_hThread, -1); CLOSE_HANDLE(m_hThread); } if (m_hExitEvent!= NULL) ResetEvent(m_hExitEvent); CLOSE_HANDLE(m_hExitEvent); int nsum = m_pTransformData->m_pWatchData->size(); for (int i = 0; i < nsum; i++) { PWATCH_PROCESS_INFORMATION pwatch = m_pTransformData->m_pWatchData->at(i); if (pwatch->proinfo.hProcess != NULL) { ::EnumWindows((WNDENUMPROC)EnumClosePro, (LPARAM)pwatch->proinfo.dwProcessId); if (WaitForSingleObject(pwatch->proinfo.hProcess, 5000) == WAIT_TIMEOUT) { TerminateProcess(pwatch->proinfo.hProcess, -1); } } } FreeWatchData(); }
BOOL CProcessControl::IsRunningWatchThread(BOOL bwatch) { ADD_LOG(); if (bwatch) { ADD_WORSELOG_CONTAINER(m_pTransformData->m_pWatchData); if (m_pTransformData->m_pWatchData->size() <= 0) return FALSE; if (m_hThread != NULL) { ::SetEvent(m_hExitEvent); if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) TerminateThread(m_hThread, -1); CLOSE_HANDLE(m_hThread); ::ResetEvent(m_hExitEvent); } m_hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchThread, this, NULL, 0); } else { if (m_hThread != NULL) { ::SetEvent(m_hExitEvent); if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) TerminateThread(m_hThread, -1); CLOSE_HANDLE(m_hThread); ::ResetEvent(m_hExitEvent); } } return TRUE; }
VOID Server::Stop_Helper(VOID) { printf("Stop_Helper: Server\n"); eState_ = STATE::stopping; StopMainThread(); for (DWORD counter = 0; counter < S_PIPES_INSTANCES; counter++ ) { DisconnectNamedPipe(Pipe_[counter].hPipeInst); CLOSE_HANDLE(Pipe_[counter].hPipeInst); } for (DWORD counter = 0; counter < S_PIPES_EVENTS; counter++ ) { CLOSE_HANDLE(hPipes_Events_[counter]); } for (DWORD counter = 0; counter < S_EVENTS_; counter++ ) { CLOSE_HANDLE(hS_Events_[counter]); } CLOSE_HANDLE(hServerIsUp_Mutex); DeleteCriticalSection(&csReadPipe_); for (DWORD counter = 0; counter < S_PIPES_INSTANCES; counter++) { DeleteCriticalSection(&Pipe_[counter].csWritePipe); } eState_ = STATE::stopped; }
void CTransformData::freeallwatchdata() { int n = m_pWatchData->size(); assert(n > -1); for (int i = 0; i < n; i++) { CLOSE_HANDLE(m_pWatchData->at(i)->proinfo.hProcess); CLOSE_HANDLE(m_pWatchData->at(i)->proinfo.hThread); } freedata<WATCH_PROCESS_INFORMATION>(m_pWatchData); }
void CDbController::CloseDbHandler( void ) { if( m_hIocp ) { ::PostQueuedCompletionStatus( m_hIocp, 0, NULL, NULL ); ::WaitForSingleObject( m_hDbHndlr, INFINITE ); CLOSE_HANDLE( m_hIocp ); CLOSE_HANDLE( m_hDbHndlr ); } }
bool ComputeHash_FromFile(const int hashType, const TCHAR *const fileName, TCHAR *const hashOut, const size_t hashOutSize) { const size_t hashSize = GetHashSize(hashType); if((hashSize == SIZE_MAX) || (hashSize >= (hashOutSize / 2))) { if(hashSize != SIZE_MAX) ERROR_MSG(T("Output buffer is too small to hold the hash value!")); return false; } HANDLE h = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(!VALID_HANDLE(h)) { ERROR_MSG(T("Failed to open input file for reading!")); return false; } hash_ctx ctx; if(!HashFunction_Init(hashType, &ctx)) { CLOSE_HANDLE(h); return false; } static const DWORD BUFF_SIZE = 4096; BYTE buffer[BUFF_SIZE]; for(;;) { DWORD nBytesRead = 0; if(!ReadFile(h, buffer, BUFF_SIZE, &nBytesRead, NULL)) { ERROR_MSG(T("Failed to read data from input file!")); CLOSE_HANDLE(h); return false; } if(nBytesRead < 1) { CLOSE_HANDLE(h); break; } HashFunction_Update(&ctx, buffer, nBytesRead); } BYTE hashValue[128]; HashFunction_Final(&ctx, hashValue); ConvertHashToHex(hashSize, hashValue, hashOut); return true; }
void CProcessControl::RunWatchThread() { while (true) { Sleep(100); m_cSection.Lock(); int nsum = m_pTransformData->m_pWatchData->size(); for (int i = 0; i < nsum; i++) { PWATCH_PROCESS_INFORMATION pwatch = m_pTransformData->m_pWatchData->at(i); if (m_bIsWatchProcess) { if (!IsProcessExit(i) || pwatch->proinfo.dwProcessId == 0) { ADD_LOG_TIPS("can not find watching process, and recreate it"); CLOSE_HANDLE(pwatch->proinfo.hProcess); CreateProcessList(i); } } else { if (pwatch->nstatus == RUN) { if (!IsProcessExit(i)) { ADD_CHECKLOG_TIPS("a abnormal process, changeing it status"); pwatch->nstatus = EXIT; if (m_hWnd) ::PostMessage(m_hWnd, WM_UPDATEWATCHLIST, NULL, NULL); } } } } m_cSection.Unlock(); if (WaitForSingleObject(m_hExitEvent, 1000) == WAIT_OBJECT_0) { break; } } }
VOID Client::Stop_Helper(VOID) { printf("Stop_Helper: Client\n"); eState_ = STATE::stopping; StopMainThread(); CLOSE_HANDLE(hPipe_); CLOSE_HANDLE(hC_Event_Stop_Server_); DeleteCriticalSection(&csPipe_Write_); DeleteCriticalSection(&csPipe_Read_); eState_ = STATE::stopped; }
CDbManager::~CDbManager() { for( int i = 0; i < DEFAULT_DB_WORKER_THREAD_NUM; i++ ) { PostQueuedCompletionStatus( m_hIOCP[i], 0, NULL, NULL ); CLOSE_HANDLE( m_hIOCP[i] ); } WaitForMultipleObjects( DEFAULT_DB_WORKER_THREAD_NUM, m_hDbWorkerThreadTerminate, TRUE, INFINITE ); for( i = 0; i < DEFAULT_DB_WORKER_THREAD_NUM; i++ ) { CLOSE_HANDLE( m_hDbWorkerThreadTerminate[i] ); } SAFE_DELETE( m_pDbIOData ); }
VOID CProcessControl::CloseAllProcess() { if (m_hExitEvent!= NULL) SetEvent(m_hExitEvent); if (m_hThread != NULL) { if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) TerminateProcess(m_hThread, -1); CLOSE_HANDLE(m_hThread); } if (m_hExitEvent!= NULL) ResetEvent(m_hExitEvent); CLOSE_HANDLE(m_hExitEvent); HANDLE h = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CloseProcessThread, (LPVOID)this, NULL, 0); CLOSE_HANDLE(h); }
VOID CProcessControl::ReCreateEstablishThread() { ADD_LOG(); UnInitialize(); HANDLE h = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EstablishThread, (LPVOID)this, NULL, 0); CLOSE_HANDLE(h); }
void Thumbnail::start(void) { CLOSE_HANDLE(mEvent); mEvent = ::CreateEvent(XPR_NULL, XPR_TRUE, XPR_FALSE, XPR_NULL); xpr_rcode_t sRcode = mThread.start(dynamic_cast<xpr::Thread::Runnable *>(this)); }
/* * The main service routine, which we use to connect a named pipe server before finishing. */ VOID elevator_serviceproc( DWORD argc, LPSTR * argv ) { DWORD dwResult = ERROR_SUCCESS; HANDLE hPipe = NULL; char cServicePipe[MAX_PATH] = {0}; DWORD dwBytes = 0; BYTE bByte = 0; do { hStatus = RegisterServiceCtrlHandler( lpServiceName, (LPHANDLER_FUNCTION)elevator_servicectrl ); if( !hStatus ) BREAK_ON_ERROR( "[ELAVATOR-NAMEDPIPE] elevator_service_proc. RegisterServiceCtrlHandler failed" ); status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwServiceSpecificExitCode = 0; elevator_servicestatus( SERVICE_RUNNING, NO_ERROR, 0 ); _snprintf( cServicePipe, MAX_PATH, "\\\\.\\pipe\\%s", lpServiceName ); while( TRUE ) { hPipe = CreateFileA( cServicePipe, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hPipe ) { if( WriteFile( hPipe, &bByte, 1, &dwBytes, NULL ) ) break; CLOSE_HANDLE( hPipe ); } Sleep( 50 ); } } while( 0 ); CLOSE_HANDLE( hPipe ); dwElevateStatus = dwResult; elevator_servicestatus( SERVICE_STOPPED, NO_ERROR, 0 ); SetEvent( hTerminate ); }
int TThreadLock::Destroy() { #ifdef SYSTEM_WIN CLOSE_HANDLE(m_hMutex); #else if (0 != pthread_mutex_destroy(&m_hMutex)) return -1; #endif return 0; }
static __forceinline void doLockFile(HANDLE &fileHandle, const QString &filePath, QFile *const outFile) { bool success = false; fileHandle = INVALID_HANDLE_VALUE; //Try to open the file! for(int i = 0; i < 64; i++) { const HANDLE hTemp = CreateFileW(MUTILS_WCHR(QDir::toNativeSeparators(filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if(VALID_HANDLE(hTemp)) { PROTECT_HANDLE(fileHandle = hTemp, true); break; /*file opened successfully*/ } if(i == 0) { qWarning("Failed to open file on first attemp, retrying..."); } Sleep(1); } //Now try to actually lock the file! if (VALID_HANDLE(fileHandle)) { for (int i = 0; i < 64; i++) { LARGE_INTEGER fileSize; if (GetFileSizeEx(fileHandle, &fileSize)) { OVERLAPPED overlapped = { 0U, 0U, 0U, 0U, 0U }; if (LockFileEx(fileHandle, LOCKFILE_FAIL_IMMEDIATELY, 0, fileSize.LowPart, fileSize.HighPart, &overlapped)) { success = true; break; /*file locked successfully*/ } Sleep(1); } if (i == 0) { qWarning("Failed to lock file on first attemp, retrying..."); } } } //Locked successfully? if(!success) { CLOSE_HANDLE(fileHandle); if(outFile) { QFile::remove(QFileInfo(*outFile).canonicalFilePath()); } MUTILS_THROW_FMT("File '%s' could not be locked!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } }
VOID Server::StopMainThread() { if (hMainThread_ != NULL) { SetEvent(hPipes_Events_[S_PIPES_EVENTS - 1]); WaitForSingleObject(hMainThread_, INFINITE); CLOSE_HANDLE(hMainThread_); nMainThreadId_ = NULL; } }
void Thumbnail::destroy(void) { stop(); clearAysncImage(); CLOSE_HANDLE(mEvent); XPR_SAFE_DELETE(mThumbImgList); mIdMgr = 0; }
/* * Create and run a VNC server on this socket. */ DWORD vncdll_run( AGENT_CTX * lpAgentContext ) { DWORD dwResult = ERROR_SUCCESS; VSocketSystem * vsocketsystem = NULL; vncServer * vserver = NULL; HDESK desk = NULL; WSADATA WSAData = {0}; SOCKET sock = 0; BYTE bFlags = 0; do { dprintf( "[VNCDLL] vncdll_run. Started..." ); if( !lpAgentContext ) BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. invalid parameters", ERROR_INVALID_PARAMETER ); hMessageMutex = CreateMutex( NULL, FALSE, NULL ); desk = vncdll_getinputdesktop( TRUE ); vncdll_unlockwindowstation(); if( !lpAgentContext->bDisableCourtesyShell ) vncdll_courtesyshell( desk ); vsocketsystem = new VSocketSystem(); if( !vsocketsystem->Initialised() ) BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. VSocketSystem Initialised failed", ERROR_NETWORK_ACCESS_DENIED ); vserver = new vncServer(); vncClientId cid = vserver->AddClient( lpAgentContext ); dprintf( "[VNCDLL-0x%08X] vncdll_run. Going into wait state... cid=%d", hAppInstance, cid ); WaitForSingleObject( lpAgentContext->hCloseEvent, INFINITE ); vserver->RemoveClient( cid ); } while( 0 ); dprintf( "[VNCDLL-0x%08X] vncdll_run. terminating...", hAppInstance ); delete vserver; delete vsocketsystem; CLOSE_HANDLE( hMessageMutex ); return 0; }
VOID CProcessControl::CloseNProcess(INT nIndex) { ADD_LOG(); m_cSection.Lock(); PWATCH_PROCESS_INFORMATION pWatch = m_pTransformData->m_pWatchData->at(nIndex); ::EnumWindows((WNDENUMPROC)EnumClosePro, (LPARAM)pWatch->proinfo.dwProcessId); GetWatchData(nIndex)->nstatus = EXIT; m_cSection.Unlock(); if (WaitForSingleObject(pWatch->proinfo.hProcess, 5000) == WAIT_TIMEOUT) { TerminateProcess(pWatch->proinfo.hProcess, -1); } CLOSE_HANDLE(pWatch->proinfo.hProcess); }
BOOL Client::WatchOverServer(VOID) { BOOL watch_over_server_result = false; HANDLE watch_over_server_mutex_handle = CreateMutexA(NULL, FALSE, SERVER_IS_WORKING_MUTEX_GUID); if (( watch_over_server_mutex_handle != NULL ) && (GetLastError() != ERROR_ALREADY_EXISTS)) { watch_over_server_result = true; } CLOSE_HANDLE(watch_over_server_mutex_handle); return watch_over_server_result; }
BOOL CProcessControl::FreeWatchData() { IsRunningWatchThread(FALSE); if (m_pTransformData->m_pWatchData == NULL) return FALSE; int n = m_pTransformData->m_pWatchData->size(); if (n <= 0) return FALSE; for (int i = 0; i < n; i++) { PWATCH_PROCESS_INFORMATION pwatch = m_pTransformData->m_pWatchData->at(i); CLOSE_HANDLE((pwatch->proinfo).hProcess); } m_pTransformData->freeallwatchdata(); return TRUE; }
VOID Client::StopMainThread(VOID) { if (hMainThread_ != NULL) { do { DWORD res = PostThreadMessage(nMainThreadId_, WM_QUIT, 0, 0); DWORD error = GetLastError(); } while (WAIT_TIMEOUT == WaitForSingleObject(hMainThread_, 0)); // В WaitForSingleObject не используем INFINITE, т.к. возможен вариант: // "Maybe the thread doesn't have a message queue. // A thread can create a message queue for itself // by calling GetMessage or PeekMessage, for example." // TODO: Решить. CLOSE_HANDLE(hMainThread_); nMainThreadId_ = NULL; } }
static __forceinline void doValidateHash(HANDLE &fileHandle, const int &fileDescriptor, const QByteArray &expectedHash, const QString &filePath) { QFile checkFile; //Now re-open the file for reading if(g_useFileDescrForQFile) { checkFile.open(fileDescriptor, QIODevice::ReadOnly); } else { checkFile.setFileName(filePath); for(int i = 0; i < 64; i++) { if(checkFile.open(QIODevice::ReadOnly)) break; if(!i) qWarning("Failed to re-open file on first attemp, retrying..."); Sleep(100); } } //Opened successfully if((!checkFile.isOpen()) || checkFile.peek(1).isEmpty()) { QFile::remove(filePath); MUTILS_THROW_FMT("File '%s' could not be read!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } //Verify file contents const QByteArray hash = FileHash::computeHash(checkFile); checkFile.close(); //Compare hashes if(hash.isNull() || _stricmp(hash.constData(), expectedHash.constData())) { qWarning("\nFile checksum error:\n A = %s\n B = %s\n", expectedHash.constData(), hash.constData()); CLOSE_HANDLE(fileHandle); QFile::remove(filePath); MUTILS_THROW_FMT("File '%s' is corruputed, take care!", MUTILS_UTF8(QFileInfo(filePath).fileName())); } }
/* * A post injection hook called after our dll has been injected into a process. */ DWORD loader_inject_post( DWORD dwPid, HANDLE hProcess, DWORD dwInjectResult ) { do { // if we have successfully injected, run the io thread and return if( dwInjectResult == ERROR_SUCCESS ) { // we only want the agent to do the RFB initilization once (for the remote viewer) if( AgentContext.bInit ) AgentContext.bInit = FALSE; break; } // but if injection failed close the process handle CLOSE_HANDLE( hProcess ); loader_agent_close(); } while( 0 ); return dwInjectResult; }
/* * Enable or disable a privilege in our processes current token. */ BOOL elevate_priv( char * cpPrivilege, BOOL bEnable ) { DWORD dwResult = ERROR_SUCCESS; HANDLE hToken = NULL; TOKEN_PRIVILEGES priv = {0}; do { if( !cpPrivilege ) BREAK_WITH_ERROR( "[ELEVATE] elevate_priv. invalid arguments", ERROR_BAD_ARGUMENTS ); if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) BREAK_ON_ERROR( "[ELEVATE] elevate_priv. OpenProcessToken failed" ); priv.PrivilegeCount = 1; if( bEnable ) priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else priv.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED; if( !LookupPrivilegeValue( NULL, cpPrivilege, &priv.Privileges[0].Luid ) ) BREAK_ON_ERROR( "[ELEVATE] elevate_priv. LookupPrivilegeValue failed" ); if( !AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) ) BREAK_ON_ERROR( "[ELEVATE] elevate_priv. AdjustTokenPrivileges failed" ); } while( 0 ); CLOSE_HANDLE( hToken ); SetLastError( dwResult ); if( dwResult == ERROR_SUCCESS ) return TRUE; return FALSE; }
/* * Send a buffer to a named pipe server. */ DWORD screenshot_send( char * cpNamedPipe, BYTE * pJpegBuffer, DWORD dwJpegSize ) { DWORD dwResult = ERROR_ACCESS_DENIED; HANDLE hPipe = NULL; DWORD dwWritten = 0; DWORD dwTotal = 0; do { hPipe = CreateFileA( cpNamedPipe, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( !hPipe ) BREAK_ON_ERROR( "[SCREENSHOT] screenshot_send. CreateFileA failed" ); if( !WriteFile( hPipe, (LPCVOID)&dwJpegSize, sizeof(DWORD), &dwWritten, NULL ) ) BREAK_ON_ERROR( "[SCREENSHOT] screenshot_send. WriteFile JPEG length failed" ); if( !dwJpegSize || !pJpegBuffer ) BREAK_WITH_ERROR( "[SCREENSHOT] screenshot_send. No JPEG to transmit.", ERROR_BAD_LENGTH ); while( dwTotal < dwJpegSize ) { if( !WriteFile( hPipe, (LPCVOID)(pJpegBuffer + dwTotal), (dwJpegSize - dwTotal), &dwWritten, NULL ) ) break; dwTotal += dwWritten; } if( dwTotal != dwJpegSize ) BREAK_WITH_ERROR( "[SCREENSHOT] screenshot_send. dwTotal != dwJpegSize", ERROR_BAD_LENGTH ); dwResult = ERROR_SUCCESS; } while( 0 ); CLOSE_HANDLE( hPipe ); return dwResult; }
/* * Elevate a pipe server by allowing it to impersonate us. */ BOOL elevator_namedpipeservice( char * cpServiceName ) { DWORD dwResult = ERROR_SUCCESS; SERVICE_TABLE_ENTRY servicetable[2] = {0}; do { if( !cpServiceName ) BREAK_WITH_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. cpServiceName == NULL", ERROR_INVALID_HANDLE ); lpServiceName = _strdup( cpServiceName ); hTerminate = CreateEvent( 0, TRUE, FALSE, 0 ); if( !hTerminate ) BREAK_ON_ERROR( "[ELAVATOR-NAMEDPIPE] elevator_service_proc. CreateEvent hTerminate failed" ); servicetable[0].lpServiceName = lpServiceName; servicetable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)elevator_serviceproc; servicetable[1].lpServiceName = NULL; servicetable[1].lpServiceProc = NULL; if( !StartServiceCtrlDispatcher( servicetable ) ) BREAK_ON_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. StartServiceCtrlDispatcher failed" ); if( WaitForSingleObject( hTerminate, INFINITE ) != WAIT_OBJECT_0 ) BREAK_ON_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. WaitForSingleObject failed" ); dwResult = dwElevateStatus; } while( 0 ); CLOSE_HANDLE( hTerminate ); return dwResult; }
/* * Entry Point. */ DWORD Init( SOCKET s ) { DWORD dwResult = ERROR_SUCCESS; BOOL bTerminate = FALSE; HANDLE hMessageThread = NULL; DLL_BUFFER VncDllBuffer = {0}; char cCommandLine[MAX_PATH] = {0}; DWORD dwHostSessionId = 0; DWORD dwActiveSessionId = 0; DWORD dwAgentSessionId = 0xFFFFFFFF; BYTE bFlags = 0; __try { do { // We maintain state for the rfb stream so as not to desynchronize the remote // client after session switching and the injection of multiple agents server side. context_init(); sock = s; if( sock == INVALID_SOCKET ) BREAK_WITH_ERROR( "[LOADER] Init. INVALID_SOCKET", ERROR_INVALID_PARAMETER ); if( recv( sock, (char *)&bFlags, 1, 0 ) == SOCKET_ERROR ) BREAK_ON_WSAERROR( "[LOADER] Init. recv bFlags failed" ); if( bFlags & VNCFLAG_DISABLECOURTESYSHELL ) AgentContext.bDisableCourtesyShell = TRUE; if( bFlags & VNCFLAG_DISABLESESSIONTRACKING ) bDisableSessionTracking = TRUE; dprintf( "[LOADER] Init. Starting, hAppInstance=0x%08X, sock=%d, bFlags=%d", hAppInstance, sock, bFlags ); // get the vnc dll we will inject into the active session if( loader_vncdll( &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_ON_ERROR( "[LOADER] Init. loader_vncdll failed" ); // create a socket event and have it signaled on FD_CLOSE hSocketCloseEvent = WSACreateEvent(); if( hSocketCloseEvent == WSA_INVALID_EVENT ) BREAK_ON_WSAERROR( "[LOADER] Init. WSACreateEvent failed" ); if( WSAEventSelect( sock, hSocketCloseEvent, FD_CLOSE ) == SOCKET_ERROR ) BREAK_ON_WSAERROR( "[LOADER] Init. WSAEventSelect failed" ); // get the session id that our host process belongs to dwHostSessionId = session_id( GetCurrentProcessId() ); hMessageThread = CreateThread( NULL, 0, context_message_thread, NULL, 0, NULL ); if( !hMessageThread ) BREAK_ON_ERROR( "[LOADER] Init. CreateThread context_message_thread failed" ); // loop untill the remote client closes the connection, creating a vnc // server agent inside the active session upon the active session changing while( !bTerminate ) { // in case we have been waiting for a session to attach to the physical // console and the remote client has quit, we detect this here... if( WaitForSingleObject( hSocketCloseEvent, 0 ) == WAIT_OBJECT_0 ) { dprintf( "[LOADER] Init. Remote socket closed, terminating1..." ); break; } // get the session id for the interactive session dwActiveSessionId = session_activeid(); // test if there is no session currently attached to the physical console... if( dwActiveSessionId == 0xFFFFFFFF ) { dprintf( "[LOADER] Init. no session currently attached to the physical console..." ); // just try to wait it out... Sleep( 250 ); continue; } else if( dwActiveSessionId == dwAgentSessionId ) { dprintf( "[LOADER] Init. dwActiveSessionId == dwAgentSessionId..." ); // just try to wait it out... Sleep( 250 ); continue; } // do the local process or session injection if( dwHostSessionId != dwActiveSessionId ) { dprintf( "[LOADER] Init. Injecting into active session %d...", dwActiveSessionId ); if( session_inject( dwActiveSessionId, &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_WITH_ERROR( "[LOADER] Init. session_inject failed", ERROR_ACCESS_DENIED ); } else { dprintf( "[LOADER] Init. Allready in the active session %d.", dwActiveSessionId ); if( ps_inject( GetCurrentProcessId(), &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_WITH_ERROR( "[LOADER] Init. ps_inject current process failed", ERROR_ACCESS_DENIED ); } dwAgentSessionId = dwActiveSessionId; // loop, waiting for either the agents process to die, the remote socket to die or // the active session to change... while( TRUE ) { HANDLE hEvents[2] = {0}; DWORD dwWaitResult = 0; // wait for these event to be signaled or a timeout to occur... hEvents[0] = hSocketCloseEvent; hEvents[1] = hAgentProcess; dwWaitResult = WaitForMultipleObjects( 2, (HANDLE *)&hEvents, FALSE, 250 ); // bail if we have somehow failed (e.g. invalid handle) if( dwWaitResult == WAIT_FAILED ) { dprintf( "[LOADER] Init. WaitForMultipleObjects failed." ); // if we cant synchronize we bail out... bTerminate = TRUE; break; } // if we have just timedout, test the current active session... else if( dwWaitResult == WAIT_TIMEOUT ) { // if the agent is still in the active session just continue... if( dwAgentSessionId == session_activeid() ) continue; // if we are not to perform session tracking try and stay in the current session (as it might become the active input session at a later stage) if( bDisableSessionTracking ) { dprintf( "[LOADER] Init. Active session has changed, trying to stay in current session as session tracking disabled..." ); Sleep( 500 ); continue; } // if the agent is no longer in the active session we signal the agent to terminate if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 1 hAgentCloseEvent failed. error=%d", GetLastError() ); dprintf( "[LOADER] Init. Active session has changed. Moving agent into new session..." ); dwAgentSessionId = 0xFFFFFFFF; // and we go inject a new agent into the new active session (or terminate if session tracking disabled) loader_agent_close(); break; } // sanity check the result for an abandoned mutex else if( (dwWaitResult >= WAIT_ABANDONED_0) && (dwWaitResult <= (WAIT_ABANDONED_0 + 1)) ) { dprintf( "[LOADER] Init. WAIT_ABANDONED_0 for %d", dwWaitResult - WAIT_ABANDONED_0 ); bTerminate = TRUE; break; } else { // otherwise if we have an event signaled, handle it switch( dwWaitResult - WAIT_OBJECT_0 ) { case 0: dprintf( "[LOADER] Init. Remote socket closed, terminating2..." ); bTerminate = TRUE; if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 2 hAgentCloseEvent failed. error=%d", GetLastError() ); ReleaseMutex( hAgentCloseEvent ); break; case 1: dprintf( "[LOADER] Init. Injected agent's process has terminated..." ); loader_agent_close(); dwAgentSessionId = 0xFFFFFFFF; break; default: dprintf( "[LOADER] Init. WaitForMultipleObjects returned dwWaitResult=0x%08X", dwWaitResult ); bTerminate = TRUE; if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 3 hAgentCloseEvent failed. error=%d", GetLastError() ); break; } } // get out of this loop... break; } } } while( 0 ); CLOSE_HANDLE( hSocketCloseEvent ); loader_agent_close(); closesocket( sock ); if( hMessageThread ) TerminateThread( hMessageThread, 0 ); } __except( EXCEPTION_EXECUTE_HANDLER ) { dprintf( "[LOADER] Init. EXCEPTION_EXECUTE_HANDLER\n\n" ); } dprintf( "[LOADER] Init. Finished." ); return dwResult; }
/* * Close the various global handles we created for the agent.. */ VOID loader_agent_close( VOID ) { CLOSE_HANDLE( hAgentCloseEvent ); CLOSE_HANDLE( hAgentProcess ); }
/* * A pre injection hook called before our dll has been injected into a process. */ DWORD loader_inject_pre( DWORD dwPid, HANDLE hProcess, char * cpCommandLine ) { DWORD dwResult = ERROR_SUCCESS; LPVOID lpMemory = NULL; AGENT_CTX RemoteAgentContext = {0}; int i = 0; do { if( !hProcess || !cpCommandLine ) BREAK_WITH_ERROR( "[LOADER] loader_inject_pre. !hProcess || !cpCommandLine", ERROR_INVALID_PARAMETER ); // Use User32!WaitForInputIdle to slow things down so if it's a new // process (like a new winlogon.exe) it can have a chance to initilize... // Bad things happen if we inject into an uninitilized process. WaitForInputIdle( hProcess, 10000 ); CLOSE_HANDLE( hAgentCloseEvent ); CLOSE_HANDLE( hAgentProcess ); memcpy( &RemoteAgentContext, &AgentContext, sizeof(AGENT_CTX) ); hAgentCloseEvent = CreateMutex( NULL, TRUE, NULL ); if( !hAgentCloseEvent ) BREAK_ON_ERROR( "[LOADER] loader_inject_pre. CreateEvent hAgentCloseEvent failed" ); if( !DuplicateHandle( GetCurrentProcess(), hAgentCloseEvent, hProcess, &RemoteAgentContext.hCloseEvent, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) BREAK_ON_ERROR( "[LOADER] loader_inject_pre. DuplicateHandle hAgentCloseEvent failed" ) dprintf( "[LOADER] WSADuplicateSocket for sock=%d", sock ); // Duplicate the socket for the target process if( WSADuplicateSocket( sock, dwPid, &RemoteAgentContext.info ) != NO_ERROR ) BREAK_ON_WSAERROR( "[LOADER] WSADuplicateSocket failed" ) // Allocate memory for the migrate stub, context and payload lpMemory = VirtualAllocEx( hProcess, NULL, sizeof(AGENT_CTX), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); if( !lpMemory ) BREAK_ON_ERROR( "[LOADER] VirtualAllocEx failed" ) /*for( i=0 ; i<4 ; i++ ) { DWORD dwSize = 0; if( !AgentContext.dictionaries[i] ) continue; dwSize = ( sizeof(DICTMSG) + AgentContext.dictionaries[i]->dwDictLength ); RemoteAgentContext.dictionaries[i] = VirtualAllocEx( hProcess, NULL, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); if( !RemoteAgentContext.dictionaries[i] ) continue; if( !WriteProcessMemory( hProcess, RemoteAgentContext.dictionaries[i], AgentContext.dictionaries[i], dwSize, NULL ) ) RemoteAgentContext.dictionaries[i] = NULL; }*/ // Write the ctx to memory... if( !WriteProcessMemory( hProcess, lpMemory, &RemoteAgentContext, sizeof(AGENT_CTX), NULL ) ) BREAK_ON_ERROR( "[MIGRATE] WriteProcessMemory 1 failed" ) hAgentProcess = hProcess; _snprintf( cpCommandLine, COMMANDLINE_LENGTH, "/v /c:0x%08X", lpMemory ); } while( 0 ); if( dwResult != ERROR_SUCCESS ) { dprintf( "[LOADER] loader_inject_pre. CLOSE_HANDLE( hAgentCloseEvent );" ); CLOSE_HANDLE( hAgentCloseEvent ); } return dwResult; }