From 2921538719459c2efbc1ea90fa196ea7ed23ff0a Mon Sep 17 00:00:00 2001 From: DarthTon Date: Tue, 13 Jan 2015 13:50:48 +0200 Subject: [PATCH] remote local hook WIP --- src/BlackBone/BlackBone.vcxproj | 2 + src/BlackBone/BlackBone.vcxproj.filters | 28 +- src/BlackBone/LocalHook/LocalHookBase.cpp | 376 +++++++++--------- src/BlackBone/LocalHook/LocalHookBase.h | 10 +- src/BlackBone/Process/Process.cpp | 1 + src/BlackBone/Process/Process.h | 36 +- src/BlackBone/Process/ProcessCore.h | 1 - src/BlackBone/Process/ProcessModules.cpp | 23 +- src/BlackBone/Process/ProcessModules.h | 3 +- src/BlackBone/Process/RPC/RemoteContext.hpp | 3 +- src/BlackBone/Process/RPC/RemoteLocalHook.cpp | 52 +++ src/BlackBone/Process/RPC/RemoteLocalHook.h | 60 +++ src/BlackBone/Subsystem/Wow64Subsystem.cpp | 3 + 13 files changed, 371 insertions(+), 227 deletions(-) create mode 100644 src/BlackBone/Process/RPC/RemoteLocalHook.cpp create mode 100644 src/BlackBone/Process/RPC/RemoteLocalHook.h diff --git a/src/BlackBone/BlackBone.vcxproj b/src/BlackBone/BlackBone.vcxproj index 6bc69b3..975190f 100644 --- a/src/BlackBone/BlackBone.vcxproj +++ b/src/BlackBone/BlackBone.vcxproj @@ -408,6 +408,7 @@ + @@ -499,6 +500,7 @@ + diff --git a/src/BlackBone/BlackBone.vcxproj.filters b/src/BlackBone/BlackBone.vcxproj.filters index 75efb2c..1948637 100644 --- a/src/BlackBone/BlackBone.vcxproj.filters +++ b/src/BlackBone/BlackBone.vcxproj.filters @@ -25,9 +25,6 @@ {ed49eaa5-5d59-4422-9da7-4e68f2e82774} - - {f688ae04-991b-40b2-9243-89e38275be42} - {400c27bd-fb7a-4125-abf2-90a4bdb04f09} @@ -46,6 +43,9 @@ {84644925-22dd-4022-be68-30ddf267b977} + + {f688ae04-991b-40b2-9243-89e38275be42} + @@ -82,10 +82,10 @@ Process\Threads - Process\RPC + Process\Remote - Process\RPC + Process\Remote PE @@ -121,7 +121,7 @@ DriverControl - Process\RPC + Process\Remote AsmJit\Helpers @@ -189,6 +189,9 @@ AsmJit\Core + + Process\Remote + @@ -226,16 +229,16 @@ Process\Threads - Process\RPC + Process\Remote - Process\RPC + Process\Remote - Process\RPC + Process\Remote - Process\RPC + Process\Remote PE @@ -316,7 +319,7 @@ DriverControl - Process\RPC + Process\Remote AsmJit\Helpers @@ -426,5 +429,8 @@ AsmJit\Core + + Process\Remote + \ No newline at end of file diff --git a/src/BlackBone/LocalHook/LocalHookBase.cpp b/src/BlackBone/LocalHook/LocalHookBase.cpp index d46e25b..1bbea78 100644 --- a/src/BlackBone/LocalHook/LocalHookBase.cpp +++ b/src/BlackBone/LocalHook/LocalHookBase.cpp @@ -2,209 +2,209 @@ namespace blackbone { - std::unordered_map DetourBase::_breakpoints; - void* DetourBase::_vecHandler = nullptr; +std::unordered_map DetourBase::_breakpoints; +void* DetourBase::_vecHandler = nullptr; - DetourBase::DetourBase() +DetourBase::DetourBase() +{ + _buf = (uint8_t*)VirtualAlloc( nullptr, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + _origCode = _buf + 0x100; + _newCode = _buf + 0x200; +} + +DetourBase::~DetourBase() +{ + VirtualFree( _buf, 0, MEM_RELEASE ); +} + +/// +/// Temporarily disable hook +/// +/// true on success +bool DetourBase::DisableHook() +{ + if (_type == HookType::InternalInline || _type == HookType::Int3) + WriteProcessMemory( GetCurrentProcess(), _original, _origCode, _origSize, NULL ); + else if (_type == HookType::HWBP) + ToggleHBP( _hwbpIdx[GetCurrentThreadId()], false ); + + return true; +} + +/// +/// Enable disabled hook +/// +/// true on success +bool DetourBase::EnableHook() +{ + if (_type == HookType::InternalInline || _type == HookType::Int3) + WriteProcessMemory( GetCurrentProcess(), _original, _newCode, _origSize, NULL ); + else if (_type == HookType::HWBP) + ToggleHBP( _hwbpIdx[GetCurrentThreadId()], true ); + + return true; +} + +/// +/// Toggle hardware breakpoint for current thread +/// +/// Breakpoint index ( 0-4 ) +/// true to enable, false to disable +/// true on success +bool DetourBase::ToggleHBP( int index, bool enable ) +{ + CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + if (GetThreadContext( GetCurrentThread(), &context ) != TRUE) + return FALSE; + + if (enable) + BitTestAndSetT( (LONG_PTR*)&context.Dr7, 2 * index ); + else + BitTestAndResetT( (LONG_PTR*)&context.Dr7, 2 * index ); + + return (SetThreadContext( GetCurrentThread(), &context ) != FALSE); +} + +/// +/// Copy original function bytes +/// +/// Origianl function address +void DetourBase::CopyOldCode( uint8_t* ptr ) +{ + // Store original bytes + uint8_t* src = ptr; + uint8_t* old = (uint8_t*)_origCode; + uint32_t all_len = 0; + ldasm_data ld = { 0 }; + + do { - _buf = (uint8_t*)VirtualAlloc( nullptr, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - _origCode = _buf + 0x100; - _newCode = _buf + 0x200; - } + uint32_t len = ldasm( src, &ld, is_x64 ); - DetourBase::~DetourBase() - { - VirtualFree( _buf, 0, MEM_RELEASE ); - } - - /// - /// Temporarily disable hook - /// - /// true on success - bool DetourBase::DisableHook() - { - if (_type == HookType::InternalInline || _type == HookType::Int3) - WriteProcessMemory( GetCurrentProcess(), _original, _origCode, _origSize, NULL ); - else if (_type == HookType::HWBP) - ToggleHBP( _hwbpIdx[GetCurrentThreadId()], false ); - - return true; - } - - /// - /// Enable disabled hook - /// - /// true on success - bool DetourBase::EnableHook() - { - if (_type == HookType::InternalInline || _type == HookType::Int3) - WriteProcessMemory( GetCurrentProcess(), _original, _newCode, _origSize, NULL ); - else if (_type == HookType::HWBP) - ToggleHBP( _hwbpIdx[GetCurrentThreadId()], true ); - - return true; - } - - /// - /// Toggle hardware breakpoint for current thread - /// - /// Breakpoint index ( 0-4 ) - /// true to enable, false to disable - /// true on success - bool DetourBase::ToggleHBP( int index, bool enable ) - { - CONTEXT context = { 0 }; - context.ContextFlags = CONTEXT_DEBUG_REGISTERS; - - if (GetThreadContext( GetCurrentThread(), &context ) != TRUE) - return FALSE; - - if (enable) - BitTestAndSetT( (LONG_PTR*)&context.Dr7, 2 * index ); - else - BitTestAndResetT( (LONG_PTR*)&context.Dr7, 2 * index ); - - return (SetThreadContext( GetCurrentThread(), &context ) != FALSE); - } - - /// - /// Copy original function bytes - /// - /// Origianl function address - void DetourBase::CopyOldCode( uint8_t* ptr ) - { - // Store original bytes - uint8_t* src = ptr; - uint8_t* old = (uint8_t*)_origCode; - uint32_t all_len = 0; - ldasm_data ld = { 0 }; - - do + // Determine code end + if (ld.flags & F_INVALID + || (len == 1 && (src[ld.opcd_offset] == 0xCC || src[ld.opcd_offset] == 0xC3)) + || (len == 3 && src[ld.opcd_offset] == 0xC2) + || len + all_len > 128) { - uint32_t len = ldasm( src, &ld, is_x64 ); + break; + } - // Determine code end - if (ld.flags & F_INVALID - || (len == 1 && (src[ld.opcd_offset] == 0xCC || src[ld.opcd_offset] == 0xC3)) - || (len == 3 && src[ld.opcd_offset] == 0xC2) - || len + all_len > 128) - { + // move instruction + memcpy( old, src, len ); + + // if instruction has relative offset, calculate new offset + if (ld.flags & F_RELATIVE) + { + #ifdef USE64 + // exit if jump is greater then 2GB + if (_abs64( (uintptr_t)(src + *((int*)(old + ld.opcd_size))) - (uintptr_t)old ) > INT_MAX) break; - } - - // move instruction - memcpy( old, src, len ); - - // if instruction has relative offset, calculate new offset - if (ld.flags & F_RELATIVE) - { - #ifdef USE64 - // exit if jump is greater then 2GB - if (_abs64( (uintptr_t)(src + *((int*)(old + ld.opcd_size))) - (uintptr_t)old ) > INT_MAX) - break; - else - *(uint32_t*)(old + ld.opcd_size) += (uint32_t)(src - old); - #else - *(uintptr_t*)(old + ld.opcd_size) += src - old; - #endif - } - - src += len; - old += len; - all_len += len; - - } while (all_len < _origSize); - - // Failed to copy old code, use backup plan - if (all_len < _origSize) - { - _type = HookType::InternalInline; - memcpy( _origCode, ptr, _origSize ); - } - else - { - SET_JUMP( old, src ); - _callOriginal = _origCode; - } - } - - - /// - /// Exception handler - /// - /// Exception information - /// Exception disposition - LONG NTAPI DetourBase::VectoredHandler( PEXCEPTION_POINTERS excpt ) - { - switch (excpt->ExceptionRecord->ExceptionCode) - { - case EXCEPTION_BREAKPOINT: - return Int3Handler( excpt ); - - case EXCEPTION_ACCESS_VIOLATION: - return AVHandler( excpt ); - - case EXCEPTION_SINGLE_STEP: - return StepHandler( excpt ); - - default: - return EXCEPTION_CONTINUE_SEARCH; - } - } - - /// - /// Int3 exception handler - /// - /// Exception information - /// Exception disposition - LONG NTAPI DetourBase::Int3Handler( PEXCEPTION_POINTERS excpt ) - { - if (_breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) - { - DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; - - ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; - excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; - - return EXCEPTION_CONTINUE_EXECUTION; + else + *(uint32_t*)(old + ld.opcd_size) += (uint32_t)(src - old); + #else + *(uintptr_t*)(old + ld.opcd_size) += src - old; + #endif } - return EXCEPTION_CONTINUE_SEARCH; - } + src += len; + old += len; + all_len += len; - /// - /// Access violation handler - /// - /// Exception information - /// Exception disposition - LONG NTAPI DetourBase::AVHandler( PEXCEPTION_POINTERS /*excpt*/ ) + } while (all_len < _origSize); + + // Failed to copy old code, use backup plan + if (all_len < _origSize) { - return EXCEPTION_CONTINUE_SEARCH; - } - - /// - /// Single step exception handler - /// - /// Exception information - /// Exception disposition - LONG NTAPI DetourBase::StepHandler( PEXCEPTION_POINTERS excpt ) + _type = HookType::InternalInline; + memcpy( _origCode, ptr, _origSize ); + } + else { - DWORD index = 0; - int found = _BitScanForward( &index, static_cast(excpt->ContextRecord->Dr6) ); + SET_JUMP( old, src ); + _callOriginal = _origCode; + } +} - if (found != 0 && index < 4 && _breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) - { - DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; - // Disable breakpoint at current index - BitTestAndResetT( (LONG_PTR*)&excpt->ContextRecord->Dr7, 2 * index ); +/// +/// Exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::VectoredHandler( PEXCEPTION_POINTERS excpt ) +{ + switch (excpt->ExceptionRecord->ExceptionCode) + { + case EXCEPTION_BREAKPOINT: + return Int3Handler( excpt ); - ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; - excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; + case EXCEPTION_ACCESS_VIOLATION: + return AVHandler( excpt ); - return EXCEPTION_CONTINUE_EXECUTION; - } - return EXCEPTION_CONTINUE_SEARCH; + case EXCEPTION_SINGLE_STEP: + return StepHandler( excpt ); + + default: + return EXCEPTION_CONTINUE_SEARCH; } +} + +/// +/// Int3 exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::Int3Handler( PEXCEPTION_POINTERS excpt ) +{ + if (_breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) + { + DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; + + ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; + excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +/// +/// Access violation handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::AVHandler( PEXCEPTION_POINTERS /*excpt*/ ) +{ + return EXCEPTION_CONTINUE_SEARCH; +} + +/// +/// Single step exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::StepHandler( PEXCEPTION_POINTERS excpt ) +{ + DWORD index = 0; + int found = _BitScanForward( &index, static_cast(excpt->ContextRecord->Dr6) ); + + if (found != 0 && index < 4 && _breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) + { + DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; + + // Disable breakpoint at current index + BitTestAndResetT( (LONG_PTR*)&excpt->ContextRecord->Dr7, 2 * index ); + + ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; + excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; + + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} } \ No newline at end of file diff --git a/src/BlackBone/LocalHook/LocalHookBase.h b/src/BlackBone/LocalHook/LocalHookBase.h index 9bd7d92..6a0dff8 100644 --- a/src/BlackBone/LocalHook/LocalHookBase.h +++ b/src/BlackBone/LocalHook/LocalHookBase.h @@ -16,9 +16,9 @@ namespace CallOrder { enum e { - HookFirst, - HookLast, - NoOriginal, + HookFirst, // Hook called before original function + HookLast, // Hook called after original function + NoOriginal, // Original function doesn't get called }; } @@ -40,8 +40,8 @@ namespace ReturnMethod { enum e { - UseNew, - UseOriginal + UseNew, // Return value returned by hook + UseOriginal // Return original function value }; } diff --git a/src/BlackBone/Process/Process.cpp b/src/BlackBone/Process/Process.cpp index b981194..0c1c2c2 100644 --- a/src/BlackBone/Process/Process.cpp +++ b/src/BlackBone/Process/Process.cpp @@ -13,6 +13,7 @@ Process::Process() , _memory( this ) , _threads( _core ) , _hooks( _memory ) + , _localHooks( *this ) , _remote( *this ) , _mmap( *this ) , _nativeLdr( *this ) diff --git a/src/BlackBone/Process/Process.h b/src/BlackBone/Process/Process.h index 2e2e64f..f2a1b39 100644 --- a/src/BlackBone/Process/Process.h +++ b/src/BlackBone/Process/Process.h @@ -6,6 +6,7 @@ #include "Threads/Threads.h" #include "RPC/RemoteExec.h" #include "RPC/RemoteHook.h" +#include "RPC/RemoteLocalHook.h" #include "../ManualMap/Native/NtLoader.h" #include "../ManualMap/MMap.h" @@ -141,14 +142,15 @@ public: // // Subroutines // - BLACKBONE_API inline ProcessCore& core() { return _core; } // Core routines and native - BLACKBONE_API inline ProcessMemory& memory() { return _memory; } // Memory manipulations - BLACKBONE_API inline ProcessModules& modules() { return _modules; } // Module management - BLACKBONE_API inline ProcessThreads& threads() { return _threads; } // Threads - BLACKBONE_API inline RemoteHook& hooks() { return _hooks; } // Hooking code remotely - BLACKBONE_API inline RemoteExec& remote() { return _remote; } // Remote code execution - BLACKBONE_API inline MMap& mmap() { return _mmap; } // Manual module mapping - BLACKBONE_API inline NtLdr& nativeLdr() { return _nativeLdr; } // Native loader routines + BLACKBONE_API inline ProcessCore& core() { return _core; } // Core routines and native + BLACKBONE_API inline ProcessMemory& memory() { return _memory; } // Memory manipulations + BLACKBONE_API inline ProcessModules& modules() { return _modules; } // Module management + BLACKBONE_API inline ProcessThreads& threads() { return _threads; } // Threads + BLACKBONE_API inline RemoteHook& hooks() { return _hooks; } // Hooking code remotely + BLACKBONE_API inline RemoteLocalHook& localHooks() { return _localHooks; } // Hooking code remotely + BLACKBONE_API inline RemoteExec& remote() { return _remote; } // Remote code execution + BLACKBONE_API inline MMap& mmap() { return _mmap; } // Manual module mapping + BLACKBONE_API inline NtLdr& nativeLdr() { return _nativeLdr; } // Native loader routines private: /// @@ -160,15 +162,17 @@ private: Process(const Process&) = delete; Process& operator =(const Process&) = delete; + private: - ProcessCore _core; // Core routines and native subsystem - ProcessModules _modules; // Module management - ProcessMemory _memory; // Memory manipulations - ProcessThreads _threads; // Threads - RemoteHook _hooks; // Hooking code remotely - RemoteExec _remote; // Remote code execution - MMap _mmap; // Manual module mapping - NtLdr _nativeLdr; // Native loader routines + ProcessCore _core; // Core routines and native subsystem + ProcessModules _modules; // Module management + ProcessMemory _memory; // Memory manipulations + ProcessThreads _threads; // Threads + RemoteHook _hooks; // Hooking code remotely + RemoteLocalHook _localHooks; // In-process remote hooks + RemoteExec _remote; // Remote code execution + MMap _mmap; // Manual module mapping + NtLdr _nativeLdr; // Native loader routines }; } diff --git a/src/BlackBone/Process/ProcessCore.h b/src/BlackBone/Process/ProcessCore.h index b19b20e..af4e2d6 100644 --- a/src/BlackBone/Process/ProcessCore.h +++ b/src/BlackBone/Process/ProcessCore.h @@ -1,6 +1,5 @@ #pragma once -#include "../Include/Winheaders.h" #include "../Include/NativeStructures.h" #include "../Subsystem/Wow64Subsystem.h" #include "../Subsystem/x86Subsystem.h" diff --git a/src/BlackBone/Process/ProcessModules.cpp b/src/BlackBone/Process/ProcessModules.cpp index 167f0c1..9acef50 100644 --- a/src/BlackBone/Process/ProcessModules.cpp +++ b/src/BlackBone/Process/ProcessModules.cpp @@ -343,9 +343,11 @@ exportData ProcessModules::GetExport( const ModuleData* hMod, const char* name_o /// Inject image into target process /// /// Full-qualified image path +/// Injection status code /// Module info. nullptr if failed -const ModuleData* ProcessModules::Inject( const std::wstring& path ) +const ModuleData* ProcessModules::Inject( const std::wstring& path, NTSTATUS* pStatus /*= nullptr*/ ) { + NTSTATUS status = STATUS_SUCCESS; const ModuleData* mod = nullptr; ptr_t res = 0; auto& barrier = _core.native()->GetWow64Barrier(); @@ -358,7 +360,12 @@ const ModuleData* ProcessModules::Inject( const std::wstring& path ) // Already loaded if ((mod = GetModule( path, LdrList, img.mType() )) != nullptr) + { + if (pStatus) + *pStatus = STATUS_IMAGE_ALREADY_LOADED; + return mod; + } // Image path UNICODE_STRING ustr = { 0 }; @@ -378,7 +385,7 @@ const ModuleData* ProcessModules::Inject( const std::wstring& path ) // Try to use LoadLibrary if possible if (pLoadLibrary != 0 && sameArch) { - _proc.remote().ExecDirect( pLoadLibrary, modName.ptr() + sizeof(ustr) ); + _proc.remote().ExecDirect( pLoadLibrary, modName.ptr() + sizeof( ustr ) ); } // Can't generate code through WOW64 barrier else if ((barrier.type != wow_32_64 && img.mType() == mt_mod64) || @@ -386,7 +393,12 @@ const ModuleData* ProcessModules::Inject( const std::wstring& path ) { auto pLdrLoadDll = GetExport( GetModule( L"ntdll.dll", Sections, img.mType() ), "LdrLoadDll" ).procAddress; if (pLdrLoadDll == 0) + { + if (pStatus) + *pStatus = STATUS_NOT_FOUND; + return nullptr; + } // Patch LdrFindOrMapDll to enable kernel32.dll loading #ifdef USE64 @@ -410,9 +422,14 @@ const ModuleData* ProcessModules::Inject( const std::wstring& path ) a.GenCall( (size_t)pLdrLoadDll, { 0, 0, modName.ptr(), modName.ptr() + 0x800 } ); a->ret(); - _proc.remote().ExecInNewThread( a->make(), a->getCodeSize(), res ); + status = _proc.remote().ExecInNewThread( a->make(), a->getCodeSize(), res ); + if (NT_SUCCESS( status )) + status = static_cast(res); } + if (pStatus) + *pStatus = status; + if (res == STATUS_SUCCESS) return GetModule( path, LdrList, img.mType() ); else diff --git a/src/BlackBone/Process/ProcessModules.h b/src/BlackBone/Process/ProcessModules.h index 2f9c874..5dda2f3 100644 --- a/src/BlackBone/Process/ProcessModules.h +++ b/src/BlackBone/Process/ProcessModules.h @@ -120,8 +120,9 @@ public: /// Inject image into target process /// /// Full-qualified image path + /// Injection status code /// Module info. nullptr if failed - BLACKBONE_API const ModuleData* Inject( const std::wstring& path ); + BLACKBONE_API const ModuleData* Inject( const std::wstring& path, NTSTATUS* pStatus = nullptr ); #ifdef COMPILER_MSVC /// diff --git a/src/BlackBone/Process/RPC/RemoteContext.hpp b/src/BlackBone/Process/RPC/RemoteContext.hpp index 2030061..071e1d5 100644 --- a/src/BlackBone/Process/RPC/RemoteContext.hpp +++ b/src/BlackBone/Process/RPC/RemoteContext.hpp @@ -1,8 +1,7 @@ #pragma once -#include "../../Include/Winheaders.h" -#include "../ProcessMemory.h" #include "../ProcessCore.h" +#include "../ProcessMemory.h" #include "../Threads/Thread.h" #include "../../Include/Macro.h" diff --git a/src/BlackBone/Process/RPC/RemoteLocalHook.cpp b/src/BlackBone/Process/RPC/RemoteLocalHook.cpp new file mode 100644 index 0000000..08347ba --- /dev/null +++ b/src/BlackBone/Process/RPC/RemoteLocalHook.cpp @@ -0,0 +1,52 @@ +#include "RemoteLocalHook.h" + +#include "../Process.h" + +#ifdef USE64 +#define HOOK_CTX_T(v, ctx) HookCtx64& v = ctx.hook64 +#else +#define HOOK_CTX_T(v, ctx) HookCtx32& v = ctx.hook32 +#endif + +namespace blackbone +{ + +RemoteLocalHook::RemoteLocalHook( class Process& process ) + : _process( process ) +{ +} + + +RemoteLocalHook::~RemoteLocalHook() +{ +} + +NTSTATUS RemoteLocalHook::SetHook( ptr_t address, asmjit::Assembler& /*hook*/ ) +{ + HookCtx ctx = { 0 }; + HOOK_CTX_T( ctx_t, ctx ); + UNREFERENCED_PARAMETER( ctx_t ); + + // Already hooked + if (_hooks.count( address ) != 0) + return STATUS_ADDRESS_ALREADY_EXISTS; + + _hooks.emplace( std::make_pair( address, ctx ) ); + + return STATUS_SUCCESS; +} + +NTSTATUS RemoteLocalHook::Restore( ptr_t address ) +{ + // No such hook + if (_hooks.count( address ) == 0) + return STATUS_NOT_FOUND; + + HOOK_CTX_T( ctx_t, _hooks[address] ); + + _hooks.erase( address ); + + return STATUS_SUCCESS; +} + +} \ No newline at end of file diff --git a/src/BlackBone/Process/RPC/RemoteLocalHook.h b/src/BlackBone/Process/RPC/RemoteLocalHook.h new file mode 100644 index 0000000..2e3dfdd --- /dev/null +++ b/src/BlackBone/Process/RPC/RemoteLocalHook.h @@ -0,0 +1,60 @@ +#pragma once + +#include "../../Config.h" +#include "../../Asm/AsmHelper.h" +#include "../../Include/Types.h" + +#include + +namespace blackbone +{ + +/// +/// Hook data, sizeof = 0x50 bytes +/// +struct HookCtx32 +{ + uint32_t codeSize; // Size of saved code + uint8_t original_code[34]; // Original function code +}; + +struct HookCtx64 +{ + uint64_t dst_ptr; // Target address + uint32_t codeSize; // Size of saved code + uint8_t original_code[32]; // Original function code + uint8_t far_jmp[6]; // Far jump code +}; + +union HookCtx +{ + HookCtx32 hook32; + HookCtx64 hook64; +}; + + +/// +/// In-process remote hook +/// +class RemoteLocalHook +{ + typedef std::unordered_map mapCtx; + +public: + RemoteLocalHook( class Process& process ); + ~RemoteLocalHook(); + + NTSTATUS SetHook( ptr_t address, asmjit::Assembler& hook ); + + NTSTATUS Restore( ptr_t address ); + +private: + RemoteLocalHook( const RemoteLocalHook& ) = delete; + RemoteLocalHook& operator = (const RemoteLocalHook&) = delete; + +private: + class Process& _process; + mapCtx _hooks; +}; + +} \ No newline at end of file diff --git a/src/BlackBone/Subsystem/Wow64Subsystem.cpp b/src/BlackBone/Subsystem/Wow64Subsystem.cpp index aef1403..5bba51e 100644 --- a/src/BlackBone/Subsystem/Wow64Subsystem.cpp +++ b/src/BlackBone/Subsystem/Wow64Subsystem.cpp @@ -357,7 +357,10 @@ ptr_t NativeWow64::getTEB( HANDLE hThread, _TEB64* pteb ) static ptr_t ntQit = _local.GetProcAddress64( _local.getNTDLL64(), "NtQueryInformationThread" ); if (ntQit == 0) + { LastNtStatus( STATUS_ORDINAL_NOT_FOUND ); + return 0; + } _local.X64Call( ntQit, hThread, 0, &info, sizeof(info), &bytes );