public RenderHooks(float aspectRatioLimit, IReloadedHooks hooks) { _memory = Memory.CurrentProcess; _aspectConverter = new AspectConverter(aspectRatioLimit); _draw2PViewPortHook = hooks.CreateHook <sub_422AF0>(Draw2PViewportHook, 0x422AF0).Activate(); _drawSpecialStageGaugeHook = hooks.CreateHook <sub_5263C0>(DrawSpecialStageGaugeImpl, 0x5263C0).Activate(); _drawSpecialStageBarHook = hooks.CreateHook <sub_526280>(DrawSpecialStageBarImpl, 0x526280, 0xD).Activate(); _draw2PStatusHook = hooks.CreateHook <sub_422A70>(Draw2pStatusImpl, 0x422A70).Activate(); _renderPrimitiveHook = hooks.CreateHook <_rwD3D8Im2DRenderPrimitive>(RenderPrimitiveImpl, 0x00662B00).Activate(); _renderVideoHook = hooks.CreateHook <sub_644450>(RenderVideoHookImpl, 0x644450).Activate(); _drawFullVideoFrameHook = hooks.CreateHook <DrawFullVideoFrame>(DrawFullVideoFrameHookImpl, 0x0042A100).Activate(); _drawSmallVideoFrameHook = hooks.CreateHook <DrawSmallFrame>(DrawSmallFrameImpl, 0x00429F80).Activate(); _drawTitlecardElementsHook = hooks.CreateHook <sub_442850>(DrawTitlecardElementsImpl, 0x442850).Activate(); _drawSpecialStageLinkHook = hooks.CreateHook <sub_526F60>(DrawSpecialStageLinkImpl, 0x526F60).Activate(); _getVertexBufferSubmission = hooks.CreateWrapper <sub_651E20>(0x651E20, out _); _drawNowLoadingHook = hooks.CreateHook <sub_44EAC0>(DrawNowLoadingImpl, 0x44EAC0).Activate(); _executeCreditsHook = hooks.CreateHook <sub_4545F0>(ExecuteCredits, 0x4545F0).Activate(); _drawResultScreenDotsHook = hooks.CreateHook <sub_438A90>(DrawResultScreenDotsImpl, 0x438A90).Activate(); _drawPowerupBoxHook = hooks.CreateHook <DrawPowerupBox>(DrawPowerupBoxImpl, 0x479AB0).Activate(); _drawEmeraldHookReverseWrap = hooks.CreateReverseWrapper <DrawEmeraldHook>(DrawSpecialStageEmeraldImpl); _addressOfHook = new Pinnable <IntPtr>(_drawEmeraldHookReverseWrap.WrapperPointer); _drawSpecialStageEmeraldIndicatorHook = hooks.CreateAsmHook(new[] { "use32", // Offset to first param (after execution of code) "push eax", // + 8 "push esi", // + 12 "push ecx", // + 16 "push edx", // + 20 /* Push address of stack parameters up stack. */ "lea edx, [esp + 32]", "lea ecx, [esp + 28]", "lea ebx, [esp + 24]", "lea eax, [esp + 20]", "push edx", "push ecx", "push ebx", "push eax", $"call dword [0x{(long)_addressOfHook.Pointer:X}]", "add esp, 16", "pop edx", "pop ecx", "pop esi", "pop eax" }, 0x458920).Activate(); _memory.ChangePermission((IntPtr)_descriptionX, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_descriptionY, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_descriptionWidth, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_descriptionHeight, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_pickupBoxSeparation, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_dotsVertSeparation, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_dotsHorzSeparation, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_dotsHeight, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); _memory.ChangePermission((IntPtr)_dotsWidth, sizeof(void *), Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE); }
public IndirectHook(IntPtr addressToFunctionPointer, TFunction function, IReloadedHooks hookFactory) { mAddressToFunctionPointer = addressToFunctionPointer; OriginalFunctionAddress = *( IntPtr * )mAddressToFunctionPointer; OriginalFunction = hookFactory.CreateWrapper <TFunction>((long)OriginalFunctionAddress, out IntPtr originalFunctionWrapperAddress); OriginalFunctionWrapperAddress = OriginalFunctionAddress; ReverseWrapper = hookFactory.CreateReverseWrapper(function); }
/// <summary> /// Creates a hook for a function at a given address. /// </summary> /// <param name="function">The function to detour the original function to.</param> /// <param name="functionAddress">The address of the function to hook.</param> /// <param name="minHookLength">Optional explicit length of hook. Use only in rare cases where auto-length check overflows a jmp/call opcode.</param> public Hook(TFunction function, long functionAddress, int minHookLength = -1) { _is64Bit = IntPtr.Size == 8; ReverseWrapper = CreateReverseWrapper(function); /* * === Hook Summary === * * A. Insert Absolute Jump to ReverseWrapper (Convention => CDECL Marshaller) * A1. Backup original bytes and patch between start and end of JMP for (B). * * B. Setup Wrapper to call original function (CDECL => Convention Marshaller) * B1. Take bytes backed up from A, and create stub function with those * bytes and JMP to end of hook. * B2. Assign OriginalFunction to that function stub. * * Note: For X64 the same principles apply, just replace CDECL with Microsoft calling convention. */ Mutex.MakeHookMutex.WaitOne(); /* Create Convention => CDECL Wrapper. */ List <byte> jumpOpcodes = Utilities.AssembleAbsoluteJump(ReverseWrapper.WrapperPointer, _is64Bit).ToList(); /* Calculate Hook Length (Unless Explicit) */ if (minHookLength == -1) { minHookLength = Utilities.GetHookLength((IntPtr)functionAddress, jumpOpcodes.Count, _is64Bit); } // Sometimes our hook can be larger than the amount of bytes taken by the jmp opcode. // We need to fill the remaining bytes with NOPs. Utilities.FillArrayUntilSize <byte>(jumpOpcodes, 0x90, minHookLength); /* Get bytes from original function prologue and patch them. */ CurrentProcess.SafeReadRaw((IntPtr)functionAddress, out byte[] originalFunction, minHookLength); var functionPatcher = new FunctionPatcher(_is64Bit); var functionPatch = functionPatcher.Patch(originalFunction.ToList(), (IntPtr)functionAddress); IntPtr hookEndAddress = (IntPtr)(functionAddress + minHookLength); functionPatch.NewFunction.AddRange(Utilities.AssembleAbsoluteJump(hookEndAddress, _is64Bit)); /* Second wave of patching. */ var icedPatcher = new IcedPatcher(_is64Bit, functionPatch.NewFunction.ToArray(), (IntPtr)functionAddress); /* Create Hook instance. */ OriginalFunctionAddress = icedPatcher.ToMemoryBuffer(); OriginalFunction = CreateWrapper((long)icedPatcher.ToMemoryBuffer(), out IntPtr originalFunctionWrapperAddress); OriginalFunctionWrapperAddress = originalFunctionWrapperAddress; _otherHookPatches = functionPatch.Patches; _hookPatch = new Patch((IntPtr)functionAddress, jumpOpcodes.ToArray()); Mutex.MakeHookMutex.ReleaseMutex(); }
/// <summary> /// Gets the sequence of assembly instructions required to assemble an absolute call to a C# function address. /// </summary> /// <param name="function">The C# function to create a jump to.</param> /// <param name="reverseWrapper"> /// The native reverse wrapper used to call your function. /// Please keep a reference to this class as long as you are using the generated code. /// i.e. make it a class/struct member on heap. /// </param> public static string GetAbsoluteCallMnemonics < #if NET5_0_OR_GREATER [DynamicallyAccessedMembers(Trimming.ReloadedAttributeTypes)] #endif TFunction>(TFunction function, out IReverseWrapper <TFunction> reverseWrapper) where TFunction : Delegate { var hooks = ReloadedHooks.Instance; reverseWrapper = hooks.CreateReverseWrapper <TFunction>(function); return(GetAbsoluteCallMnemonics(reverseWrapper.WrapperPointer.ToUnsigned(), IntPtr.Size == 8)); }
public IndirectHook(IntPtr addressToFunctionPointer, TFunction function) { mAddressToFunctionPointer = addressToFunctionPointer; OriginalFunctionAddress = *( IntPtr * )mAddressToFunctionPointer; OriginalFunction = sIs64Bit ? Reloaded.Hooks.X64.Wrapper.Create <TFunction>(( long )OriginalFunctionAddress, out IntPtr originalFunctionWrapperAddress) : Reloaded.Hooks.X86.Wrapper.Create <TFunction>(( long )OriginalFunctionAddress, out originalFunctionWrapperAddress); OriginalFunctionWrapperAddress = OriginalFunctionAddress; ReverseWrapper = sIs64Bit ? (IReverseWrapper <TFunction>) new Reloaded.Hooks.X64.ReverseWrapper <TFunction>(function) : (IReverseWrapper <TFunction>) new Reloaded.Hooks.X86.ReverseWrapper <TFunction>(function); }
/// <summary> /// Gets the sequence of assembly instructions required to assemble an absolute call to a C# function address. /// </summary> /// <param name="function">The C# function to create a jump to.</param> /// <param name="reverseWrapper"> /// The native reverse wrapper used to call your function. /// Please keep a reference to this class as long as you are using the generated code. /// i.e. make it a class/struct member on heap. /// </param> public static string GetAbsoluteCallMnemonics <TFunction>(TFunction function, out IReverseWrapper <TFunction> reverseWrapper) where TFunction : Delegate { var hooks = ReloadedHooks.Instance; reverseWrapper = hooks.CreateReverseWrapper <TFunction>(function); return(GetAbsoluteCallMnemonics(reverseWrapper.WrapperPointer, IntPtr.Size == 8)); }
public string GetAbsoluteCallMnemonics <TFunction>(TFunction function, out IReverseWrapper <TFunction> reverseWrapper) where TFunction : Delegate => Utilities.GetAbsoluteCallMnemonics(function, out reverseWrapper);
/// <summary> /// Creates a hook for a function at a given address. /// </summary> /// <param name="targetAddress">Address of the function to detour the original function to.</param> /// <param name="functionAddress">The address of the function to hook.</param> /// <param name="minHookLength">Optional explicit length of hook. Use only in rare cases where auto-length check overflows a jmp/call opcode.</param> public unsafe Hook(void *targetAddress, long functionAddress, int minHookLength = -1) { _is64Bit = sizeof(IntPtr) == 8; ReverseWrapper = CreateReverseWrapper(targetAddress); CreateHook(functionAddress, minHookLength); }
/// <summary> /// Creates a hook for a function at a given address. /// </summary> /// <param name="function">The function to detour the original function to.</param> /// <param name="functionAddress">The address of the function to hook.</param> /// <param name="minHookLength">Optional explicit length of hook. Use only in rare cases where auto-length check overflows a jmp/call opcode.</param> public unsafe Hook(TFunction function, long functionAddress, int minHookLength = -1) { _is64Bit = sizeof(IntPtr) == 8; ReverseWrapper = CreateReverseWrapper(function); CreateHook(functionAddress, minHookLength); }
public string GetAbsoluteCallMnemonics < #if NET5_0_OR_GREATER [DynamicallyAccessedMembers(Trimming.ReloadedAttributeTypes)] #endif TFunction>(TFunction function, out IReverseWrapper <TFunction> reverseWrapper) where TFunction : Delegate => Utilities.GetAbsoluteCallMnemonics(function, out reverseWrapper);
/// <summary> /// Creates a hook for a function at a given address. /// </summary> /// <param name="targetAddress">Address of the function to detour the original function to.</param> /// <param name="functionAddress">The address of the function to hook.</param> /// <param name="minHookLength">Optional explicit length of hook. Use only in rare cases where auto-length check overflows a jmp/call opcode.</param> /// <param name="options">Options which control the hook generation procedure.</param> public unsafe Hook(void *targetAddress, nuint functionAddress, int minHookLength = -1, FunctionHookOptions options = null) { _is64Bit = sizeof(IntPtr) == 8; ReverseWrapper = CreateReverseWrapper(targetAddress); CreateHook(functionAddress, minHookLength, options); }