using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace stupid.solutions; public class TestHook { internal class Import { [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool VirtualProtect(IntPtr address, uint size, uint newProtect, out uint oldProtect); } private byte[] original; private const uint HOOK_SIZE_X64 = 12u; private const uint HOOK_SIZE_X86 = 7u; public MethodInfo OriginalMethod { get; private set; } public MethodInfo HookMethod { get; private set; } public TestHook() { original = null; OriginalMethod = (HookMethod = null); } public TestHook(MethodInfo orig, MethodInfo hook) { original = null; Init(orig, hook); } public MethodInfo GetMethodByName(Type typeOrig, string nameOrig) { return typeOrig.GetMethod(nameOrig); } public TestHook(Type typeOrig, string nameOrig, Type typeHook, string nameHook) { original = null; Init(GetMethodByName(typeOrig, nameOrig), GetMethodByName(typeHook, nameHook)); } public void Init(MethodInfo orig, MethodInfo hook) { if (orig == null || hook == null) { throw new ArgumentException("Both original and hook need to be valid methods"); } RuntimeHelpers.PrepareMethod(orig.MethodHandle); RuntimeHelpers.PrepareMethod(hook.MethodHandle); OriginalMethod = orig; HookMethod = hook; } public unsafe void Hook() { if (OriginalMethod == null || HookMethod == null) { throw new ArgumentException("Hook has to be properly Init'd before use"); } try { IntPtr functionPointer = OriginalMethod.MethodHandle.GetFunctionPointer(); IntPtr functionPointer2 = HookMethod.MethodHandle.GetFunctionPointer(); if (IntPtr.Size == 8) { original = new byte[12]; if (Import.VirtualProtect(functionPointer, 12u, 64u, out var _)) { byte* ptr = (byte*)(void*)functionPointer; for (int i = 0; (long)i < 12L; i++) { original[i] = ptr[i]; } *ptr = 72; ptr[1] = 184; *(IntPtr*)(ptr + 2) = functionPointer2; ptr[10] = byte.MaxValue; ptr[11] = 224; } return; } original = new byte[7]; if (Import.VirtualProtect(functionPointer, 7u, 64u, out var _)) { byte* ptr2 = (byte*)(void*)functionPointer; for (int j = 0; (long)j < 7L; j++) { original[j] = ptr2[j]; } *ptr2 = 184; *(IntPtr*)(ptr2 + 1) = functionPointer2; ptr2[5] = byte.MaxValue; ptr2[6] = 224; } } catch (Exception) { } } public unsafe void Unhook() { if (original == null) { return; } try { IntPtr functionPointer = OriginalMethod.MethodHandle.GetFunctionPointer(); uint num = (uint)original.Length; if (Import.VirtualProtect(functionPointer, num, 64u, out var _)) { byte* ptr = (byte*)(void*)functionPointer; for (int i = 0; i < num; i++) { ptr[i] = original[i]; } } } catch (Exception) { } finally { original = null; } } }