BlackBone
Windows memory hacking library
 All Classes Functions
LocalHook.hpp
1 #pragma once
2 
3 #include "HookHandlers.h"
4 #include "../Process/Process.h"
5 
6 namespace blackbone
7 {
8 
9 template<typename Fn, class C = NoClass>
10 class Detour: public HookHandler<Fn, C>
11 {
12 public:
13  typedef typename HookHandler<Fn, C>::type type;
14  typedef typename HookHandler<Fn, C>::hktype hktype;
15  typedef typename HookHandler<Fn, C>::hktypeC hktypeC;
16 
17 public:
18  Detour()
19  {
20  this->_internalHandler = &HookHandler<Fn, C>::Handler;
21  }
22 
23  ~Detour()
24  {
25  Restore();
26  }
27 
37  bool Hook( type ptr, hktype hkPtr, HookType::e type,
38  CallOrder::e order = CallOrder::HookFirst,
39  ReturnMethod::e retType = ReturnMethod::UseOriginal )
40  {
41  if (this->_hooked)
42  return false;
43 
44  this->_type = type;
45  this->_order = order;
46  this->_retType = retType;
47  this->_callOriginal = this->_original = ptr;
48  this->_callback = hkPtr;
49 
50  switch (this->_type)
51  {
52  case HookType::Inline:
53  return HookInline();
54 
55  case HookType::Int3:
56  return HookInt3();
57 
58  case HookType::HWBP:
59  return HookHWBP();
60 
61  default:
62  return false;
63  }
64  }
65 
76  bool Hook( type Ptr, hktypeC hkPtr, C* pClass, HookType::e type,
77  CallOrder::e order = CallOrder::HookFirst,
78  ReturnMethod::e retType = ReturnMethod::UseOriginal )
79  {
80  this->_callbackClass = pClass;
81  return Hook( Ptr, brutal_cast<hktype>(hkPtr), type, order, retType );
82  }
83 
84 
89  bool Restore()
90  {
91  if (!this->_hooked)
92  return false;
93 
94  switch (this->_type)
95  {
96  case HookType::Inline:
97  case HookType::InternalInline:
98  case HookType::Int3:
99  WriteProcessMemory( GetCurrentProcess(), this->_original, this->_origCode, this->_origSize, NULL );
100  break;
101 
102  case HookType::HWBP:
103  {
104  Process thisProc;
105  thisProc.Attach( GetCurrentProcessId() );
106 
107  for (auto& thd : thisProc.threads().getAll())
108  thd.RemoveHWBP( reinterpret_cast<ptr_t>(this->_original) );
109 
110  this->_hwbpIdx.clear();
111  }
112  break;
113 
114  default:
115  break;
116  }
117 
118  this->_hooked = false;
119  return true;
120  }
121 
122 private:
123 
128  bool HookInline()
129  {
130  AsmJitHelper jmpToHook, jmpToThunk;
131 
132  //
133  // Construct jump to thunk
134  //
135 #ifdef USE64
136  jmpToThunk->mov( asmjit::host::rax, (uint64_t)this->_buf );
137  jmpToThunk->jmp( asmjit::host::rax );
138 
139  this->_origSize = jmpToThunk->getCodeSize( );
140 #else
141  jmpToThunk->jmp( _buf );
142  this->_origSize = jmpToThunk->getCodeSize();
143 #endif
144 
145  DetourBase::CopyOldCode( (uint8_t*)this->_original );
146 
147  // Construct jump to hook handler
148 #ifdef USE64
149  // mov gs:[0x28], this
150  jmpToHook->mov( asmjit::host::rax, (uint64_t)this );
151  jmpToHook->mov( asmjit::host::qword_ptr_abs( 0x28 ).setSegment( asmjit::host::gs ), asmjit::host::rax );
152 #else
153  // mov fs:[0x14], this
154  jmpToHook->mov( asmjit::host::dword_ptr_abs( 0x14 ).setSegment( asmjit::host::fs ) , (uint32_t)this );
155 #endif // USE64
156 
157  jmpToHook->jmp( &HookHandler<Fn, C>::Handler );
158  jmpToHook->relocCode( this->_buf );
159 
160  BOOL res = WriteProcessMemory( GetCurrentProcess(), this->_original, this->_newCode,
161  jmpToThunk->relocCode( this->_newCode, (uintptr_t)this->_original ), NULL );
162 
163  return (this->_hooked = (res == TRUE));
164  }
165 
170  bool HookInt3()
171  {
172  this->_newCode[0] = 0xCC;
173  this->_origSize = sizeof( this->_newCode[0] );
174 
175  // Setup handler
176  if (this->_vecHandler == nullptr)
177  this->_vecHandler = AddVectoredExceptionHandler( 1, &DetourBase::VectoredHandler );
178 
179  if (!this->_vecHandler)
180  return false;
181 
182  this->_breakpoints.insert( std::make_pair( this->_original, (DetourBase*)this ) );
183 
184  // Save original code
185  memcpy( this->_origCode, this->_original, this->_origSize );
186 
187  // Write break instruction
188  BOOL res = WriteProcessMemory( GetCurrentProcess(), this->_original, this->_newCode, this->_origSize, NULL );
189 
190  return (this->_hooked = (res == TRUE));
191  }
192 
197  bool HookHWBP()
198  {
199  Process thisProc;
200  thisProc.Attach( GetCurrentProcessId() );
201 
202  // Setup handler
203  if (this->_vecHandler == nullptr)
204  this->_vecHandler = AddVectoredExceptionHandler( 1, &DetourBase::VectoredHandler );
205 
206  if (!this->_vecHandler)
207  return false;
208 
209  this->_breakpoints.insert( std::make_pair( this->_original, (DetourBase*)this ) );
210 
211  // Add breakpoint to every thread
212  for (auto& thd : thisProc.threads().getAll())
213  this->_hwbpIdx[thd.id()] = thd.AddHWBP( reinterpret_cast<ptr_t>(this->_original), hwbp_execute, hwbp_1 );
214 
215  return this->_hooked = true;
216  }
217 };
218 
219 }
bool Hook(type ptr, hktype hkPtr, HookType::e type, CallOrder::e order=CallOrder::HookFirst, ReturnMethod::e retType=ReturnMethod::UseOriginal)
Hook function
Definition: LocalHook.hpp:37
BLACKBONE_API std::vector< Thread > & getAll(bool dontUpdate=false)
Gets all process threads
Definition: Threads.cpp:39
Definition: Process.h:43
bool Restore()
Restore hooked function
Definition: LocalHook.hpp:89
bool Hook(type Ptr, hktypeC hkPtr, C *pClass, HookType::e type, CallOrder::e order=CallOrder::HookFirst, ReturnMethod::e retType=ReturnMethod::UseOriginal)
Hook function
Definition: LocalHook.hpp:76
Definition: LocalHook.hpp:10
Definition: HookHandlers.h:12
static BLACKBONE_API LONG NTAPI VectoredHandler(PEXCEPTION_POINTERS excpt)
Exception handlers
Definition: LocalHookBase.cpp:137
BLACKBONE_API void CopyOldCode(uint8_t *Ptr)
Copy original function bytes
Definition: LocalHookBase.cpp:74
BLACKBONE_API NTSTATUS Attach(DWORD pid, DWORD access=DEFAULT_ACCESS_P)
Attach to existing process
Definition: Process.cpp:36
Definition: AsmHelper32.cpp:6