-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
.NET: Initial working method hooking
- Loading branch information
Showing
6 changed files
with
166 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include "./API.hpp" | ||
#include "MethodHookWrapper.hpp" | ||
|
||
using namespace System::Runtime::InteropServices; | ||
using namespace System::Collections::Generic; | ||
|
||
namespace REFrameworkNET { | ||
void MethodHookWrapper::InstallHooks(bool ignore_jmp) | ||
{ | ||
if (m_hooks_installed) { | ||
return; | ||
} | ||
|
||
REFrameworkNET::API::LogInfo("Creating .NET hook for method: " + m_method->GetName()); | ||
|
||
m_hooks_installed = true; | ||
|
||
reframework::API::Method* raw = (reframework::API::Method*)m_method->GetRaw(); | ||
|
||
IntPtr preHookPtr = Marshal::GetFunctionPointerForDelegate(m_preHookLambda); | ||
IntPtr postHookPtr = Marshal::GetFunctionPointerForDelegate(m_postHookLambda); | ||
m_hook_id = raw->add_hook((REFPreHookFn)preHookPtr.ToPointer(), (REFPostHookFn)postHookPtr.ToPointer(), ignore_jmp); | ||
} | ||
|
||
void MethodHookWrapper::UninstallHooks() { | ||
if (!m_hooks_installed) { | ||
return; | ||
} | ||
|
||
reframework::API::Method* raw = (reframework::API::Method*)m_method->GetRaw(); | ||
|
||
m_hooks_installed = false; | ||
raw->remove_hook(m_hook_id); | ||
} | ||
|
||
int32_t MethodHookWrapper::OnPreStart_Raw(int argc, void** argv, REFrameworkTypeDefinitionHandle* arg_tys, unsigned long long ret_addr) | ||
{ | ||
OnPreStart(gcnew List<System::Object^>()); // todo: pass the arguments | ||
System::Console::WriteLine("Hello from" + m_method->GetName() + " pre-hook!"); | ||
return 0; // Or another appropriate value | ||
} | ||
|
||
void MethodHookWrapper::OnPostStart_Raw(void** ret_val, REFrameworkTypeDefinitionHandle ret_ty, unsigned long long ret_addr) { | ||
//OnPostStart(/* arguments */); | ||
System::Console::WriteLine("Hello from" + m_method->GetName() + " post-hook!"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
|
||
#include "./API.hpp" | ||
#include "./Method.hpp" | ||
|
||
namespace REFrameworkNET { | ||
// Wrapper class we create when we create an initial hook | ||
// Additional hook calls on the same method will return the instance we already made | ||
// and additional callbacks will be appended to the existing events | ||
public ref class MethodHookWrapper | ||
{ | ||
public: | ||
// Public factory method to create a new hook | ||
static MethodHookWrapper^ Create(Method^ method, bool ignore_jmp) | ||
{ | ||
if (s_hooked_methods->ContainsKey(method)) { | ||
return s_hooked_methods[method]; | ||
} | ||
|
||
auto wrapper = gcnew MethodHookWrapper(method, ignore_jmp); | ||
s_hooked_methods->Add(method, wrapper); | ||
return wrapper; | ||
} | ||
|
||
MethodHookWrapper^ AddPre(Method::REFPreHookDelegate^ callback) | ||
{ | ||
OnPreStart += callback; | ||
return this; | ||
} | ||
|
||
MethodHookWrapper^ AddPost(Method::REFPostHookDelegate^ callback) | ||
{ | ||
OnPostStart += callback; | ||
return this; | ||
} | ||
|
||
private: | ||
event Method::REFPreHookDelegate^ OnPreStart; | ||
event Method::REFPostHookDelegate^ OnPostStart; | ||
|
||
|
||
// This is never meant to publicly be called | ||
MethodHookWrapper(Method^ method, bool ignore_jmp) | ||
{ | ||
m_method = method; | ||
m_preHookLambda = gcnew REFPreHookDelegateRaw(this, &MethodHookWrapper::OnPreStart_Raw); | ||
m_postHookLambda = gcnew REFPostHookDelegateRaw(this, &MethodHookWrapper::OnPostStart_Raw); | ||
InstallHooks(ignore_jmp); | ||
} | ||
|
||
~MethodHookWrapper() | ||
{ | ||
if (m_hooks_installed) { | ||
UninstallHooks(); | ||
} | ||
} | ||
|
||
static System::Collections::Generic::Dictionary<Method^, MethodHookWrapper^>^ s_hooked_methods = gcnew System::Collections::Generic::Dictionary<Method^, MethodHookWrapper^>(); | ||
|
||
delegate int32_t REFPreHookDelegateRaw(int argc, void** argv, REFrameworkTypeDefinitionHandle* arg_tys, unsigned long long ret_addr); | ||
delegate void REFPostHookDelegateRaw(void** ret_val, REFrameworkTypeDefinitionHandle ret_ty, unsigned long long ret_addr); | ||
|
||
void InstallHooks(bool ignore_jmp); | ||
void UninstallHooks(); | ||
|
||
int32_t OnPreStart_Raw(int argc, void** argv, REFrameworkTypeDefinitionHandle* arg_tys, unsigned long long ret_addr); | ||
void OnPostStart_Raw(void** ret_val, REFrameworkTypeDefinitionHandle ret_ty, unsigned long long ret_addr); | ||
|
||
Method^ m_method{}; | ||
uint32_t m_hook_id{}; | ||
bool m_hooks_installed{false}; | ||
|
||
REFPreHookDelegateRaw^ m_preHookLambda{}; | ||
REFPostHookDelegateRaw^ m_postHookLambda{}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters