#include "Threads.h" #include "../ProcessCore.h" #include "../../DriverControl/DriverControl.h" #include #include #include namespace blackbone { ProcessThreads::ProcessThreads( ProcessCore& core ) : _core( core ) { } ProcessThreads::~ProcessThreads() { } /// /// Create the thread. /// /// Thread enty point /// Thread argument. /// Thread creation flags /// New thread object call_result_t ProcessThreads::CreateNew( ptr_t threadProc, ptr_t arg, enum CreateThreadFlags flags /*= NoThreadFlags*/ ) { HANDLE hThd = NULL; auto status = _core.native()->CreateRemoteThreadT( hThd, threadProc, arg, flags, THREAD_ALL_ACCESS ); if (!NT_SUCCESS( status )) { // Ensure full thread access status = _core.native()->CreateRemoteThreadT( hThd, threadProc, arg, flags, THREAD_QUERY_LIMITED_INFORMATION ); if (NT_SUCCESS( status )) { if (Driver().loaded()) status = Driver().PromoteHandle( GetCurrentProcessId(), hThd, THREAD_ALL_ACCESS ); } } if (!NT_SUCCESS( status )) return status; return std::make_shared( hThd, &_core ); } /// /// Gets all process threads /// /// Threads collection std::vector ProcessThreads::getAll() const { std::vector result; auto hThreadSnapshot = SnapHandle( CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ) ); if (!hThreadSnapshot) return result; THREADENTRY32 tEntry = { 0 }; tEntry.dwSize = sizeof( THREADENTRY32 ); // Iterate threads for (BOOL success = Thread32First( hThreadSnapshot, &tEntry ); success != FALSE; success = Thread32Next( hThreadSnapshot, &tEntry )) { if (tEntry.th32OwnerProcessID != _core.pid()) continue; result.emplace_back( std::make_shared( tEntry.th32ThreadID, &_core ) ); } return result; } /// /// Get main process thread /// /// Pointer to thread object, nullptr if failed ThreadPtr ProcessThreads::getMain() const { uint64_t mintime = MAXULONG64_2; auto threads = getAll(); ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); for (const auto& thread : threads) { uint64_t time = thread->startTime(); if (time < mintime) { mintime = time; result = thread; } } return result; } /// /// Get least executed thread /// /// Pointer to thread object, nullptr if failed ThreadPtr ProcessThreads::getLeastExecuted() const { uint64_t mintime = MAXULONG64_2; auto threads = getAll(); ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); for (const auto& thread : threads) { uint64_t time = thread->execTime(); if (time < mintime) { mintime = time; result = thread; } } return result; } /// /// Get most executed thread /// /// Pointer to thread object, nullptr if failed ThreadPtr ProcessThreads::getMostExecuted() const { uint64_t maxtime = 0; auto threads = getAll(); ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); for (const auto& thread : threads) { if (thread->id() == GetCurrentThreadId()) continue; uint64_t time = thread->execTime(); if (thread->id() != GetCurrentThreadId() && time >= maxtime) { maxtime = time; result = thread; } } return result; } /// /// Get random thread /// /// Pointer to thread object, nullptr if failed ThreadPtr ProcessThreads::getRandom() const { auto threads = getAll(); if (threads.empty()) return nullptr; static std::random_device rd; std::uniform_int_distribution dist( 0, threads.size() - 1 ); return threads[dist(rd)]; } /// /// Get thread by ID /// /// Thread ID /// Pointer to thread object, nullptr if failed ThreadPtr ProcessThreads::get( DWORD id ) const { auto threads = getAll(); auto iter = std::find_if( threads.begin(), threads.end(), [id]( const auto& thread ) { return thread->id() == id; } ); return iter != threads.end() ? *iter : nullptr; } }