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 );