#pragma once #include "../../Config.h" #include "../../Include/Winheaders.h" #include "../../Include/NativeStructures.h" #include "../../Include/CallResult.h" #include "../../Include/HandleGuard.h" #include "../../Include/Types.h" #include "../../Misc/Utils.h" #include namespace blackbone { #define DEFAULT_ACCESS_T THREAD_SUSPEND_RESUME | \ THREAD_GET_CONTEXT | \ THREAD_SET_CONTEXT | \ THREAD_QUERY_INFORMATION | \ THREAD_TERMINATE | \ SYNCHRONIZE #define MAXULONG64_2 ((uint64_t)~((uint64_t)0)) #define MAXULONG32_2 ((uint32_t)~((uint32_t)0)) // Breakpoint type enum HWBPType { hwbp_access = 3, // Read or write hwbp_write = 1, // Write only hwbp_execute = 0, // Execute only }; enum HWBPLength { hwbp_1 = 0, // 1 byte hwbp_2 = 1, // 2 bytes hwbp_4 = 3, // 4 bytes hwbp_8 = 2, // 8 bytes }; /// /// DR7 register bitfield /// struct regDR7 { // // Local/global enabled index // uint32_t l0 : 1; uint32_t g0 : 1; uint32_t l1 : 1; uint32_t g1 : 1; uint32_t l2 : 1; uint32_t g2 : 1; uint32_t l3 : 1; uint32_t g3 : 1; uint32_t l_enable : 1; // Local breakpoints, obsolete for P6+ uint32_t g_enable : 1; // Global breakpoints, obsolete for P6+ uint32_t one : 1; // Reserved uint32_t rtm : 1; // Restricted transactional memory uint32_t ice : 1; // ICE debugger uint32_t gd : 1; // General detect table uint32_t tr1 : 1; // Trace 1 uint32_t tr2 : 1; // Trace2 // // Breakpoint type/length // uint32_t rw0 : 2; uint32_t len0 : 2; uint32_t rw1 : 2; uint32_t len1 : 2; uint32_t rw2 : 2; uint32_t len2 : 2; uint32_t rw3 : 2; uint32_t len3 : 2; inline void setLocal( int idx, int val ) { idx == 0 ? l0 = val : (idx == 1 ? l1 = val : (idx == 2 ? l2 = val : l3 = val)); } inline void setRW ( int idx, int val ) { idx == 0 ? rw0 = val : (idx == 1 ? rw1 = val : (idx == 2 ? rw2 = val : rw3 = val)); } inline void setLen ( int idx, int val ) { idx == 0 ? len0 = val : (idx == 1 ? len1 = val : (idx == 2 ? len2 = val : len3 = val)); } inline bool empty() const { return (l0 | l1 | l2 | l3) ? false : true; } inline int getFreeIndex() const { return !l0 ? 0 : (!l1 ? 1 : (!l2 ? 2 : (!l3 ? 3 : -1))); } }; /// /// Thread management /// class Thread { public: BLACKBONE_API Thread( DWORD id, class ProcessCore* hProcess, DWORD access = DEFAULT_ACCESS_T ); BLACKBONE_API Thread( HANDLE handle, class ProcessCore* hProcess ); BLACKBONE_API ~Thread(); BLACKBONE_API Thread( const Thread& ) = delete; BLACKBONE_API Thread& operator =( const Thread& ) = delete; BLACKBONE_API Thread( Thread&& ) = default; BLACKBONE_API Thread& operator =( Thread&& ) = default; /// /// Get thread ID /// /// Thread ID BLACKBONE_API DWORD id() const { return _id; } /// /// Get thread handle /// /// Thread hande BLACKBONE_API HANDLE handle() const { return _handle; } /// /// Check if thread exists /// /// true if thread exists BLACKBONE_API bool valid() const { return (_handle && ExitCode() == STILL_ACTIVE); } /// /// Get WOW64 TEB /// /// Process TEB /// TEB pointer BLACKBONE_API ptr_t teb( _TEB32* pteb ) const; /// /// Get Native TEB /// /// Process TEB /// TEB pointer BLACKBONE_API ptr_t teb( _TEB64* pteb ) const; /// /// Get TEB /// /// TEB pointer BLACKBONE_API ptr_t teb() const { return teb( (TEB_T*)nullptr ); } /// /// Get thread creation time /// /// Thread creation time BLACKBONE_API uint64_t startTime() const; /// /// Get total execution time(user mode and kernel mode) /// /// Total execution time BLACKBONE_API uint64_t execTime() const; /// /// Suspend thread /// /// true on success BLACKBONE_API bool Suspend(); /// /// Resumes thread. /// /// true on success BLACKBONE_API bool Resume(); /// /// Check if thread is suspended /// /// true if suspended BLACKBONE_API bool Suspended(); /// /// Get WOW64 thread context /// /// Returned context /// Context flags. /// true if thread shouldn't be suspended before retrieving context /// Status code BLACKBONE_API NTSTATUS GetContext( _CONTEXT32& ctx, DWORD flags = CONTEXT_ALL, bool dontSuspend = false ); /// /// Get native thread context /// /// Returned context /// Context flags. /// true if thread shouldn't be suspended before retrieving context /// Status code BLACKBONE_API NTSTATUS GetContext( _CONTEXT64& ctx, DWORD flags = CONTEXT64_ALL, bool dontSuspend = false ); /// /// Set WOW64 thread context /// /// Context to set /// true if thread shouldn't be suspended before retrieving context /// Status code BLACKBONE_API NTSTATUS SetContext( _CONTEXT32& ctx, bool dontSuspend = false ); /// /// Set native thread context /// /// Context to set /// true if thread shouldn't be suspended before retrieving context /// Status code BLACKBONE_API NTSTATUS SetContext( _CONTEXT64& ctx, bool dontSuspend = false ); /// /// Terminate thread /// /// Exit code /// Status code BLACKBONE_API NTSTATUS Terminate( DWORD code = 0 ); /// /// Join thread /// /// Join timeout /// true on success BLACKBONE_API bool Join( int timeout = INFINITE ); /// /// Get thread exit code /// /// Thread exit code BLACKBONE_API DWORD ExitCode() const; /// /// Add hardware breakpoint to thread /// /// Breakpoint address /// Breakpoint type(read/write/execute) /// Number of bytes to include into breakpoint /// Index of used breakpoint; -1 if failed BLACKBONE_API call_result_t AddHWBP( ptr_t addr, HWBPType type, HWBPLength length ); /// /// Remove existing hardware breakpoint /// /// Breakpoint index /// Status code BLACKBONE_API NTSTATUS RemoveHWBP( int idx ); /// /// Remove existing hardware breakpoint /// /// Breakpoint address /// Status code BLACKBONE_API NTSTATUS RemoveHWBP( ptr_t ptr ); /// /// Close handle /// BLACKBONE_API void Close(); BLACKBONE_API inline bool operator ==( const Thread& other ) { return (_id == other._id); } private: /// /// GetThreadId support for XP /// /// Thread handle /// Thread ID DWORD GetThreadIdT( HANDLE hThread ); private: class ProcessCore* _core; // Core routines DWORD _id = 0; // Thread ID Handle _handle; // Thread handle }; using ThreadPtr = std::shared_ptr; }