Skip to content

Instantly share code, notes, and snippets.

@float3
Last active March 6, 2023 10:08
Show Gist options
  • Select an option

  • Save float3/f2d8436043a207210f9574f7475c4382 to your computer and use it in GitHub Desktop.

Select an option

Save float3/f2d8436043a207210f9574f7475c4382 to your computer and use it in GitHub Desktop.
Detour
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
public class C {
static Dictionary<MethodInfo, byte[]> PatchedData = new();
static unsafe void TryDetourFromTo(MethodInfo src, MethodInfo dst)
{
try
{
if (IntPtr.Size == sizeof(Int64))
{
// 64-bit systems use 64-bit absolute address and jumps
// 12 byte destructive
var Source_IntPtr = src.MethodHandle.GetFunctionPointer();
// Backup Source Data
var backup = new byte[0xC];
Marshal.Copy(Source_IntPtr, backup, 0, 0xC);
PatchedData.Add(src, backup);
// Get function pointers
long Source_Base = Source_IntPtr.ToInt64();
long Destination_Base = dst.MethodHandle.GetFunctionPointer().ToInt64();
// Native source address
byte* Pointer_Raw_Source = (byte*) Source_Base;
// Pointer to insert jump address into native code
long* Pointer_Raw_Address = (long*) (Pointer_Raw_Source + 0x02);
// Insert 64-bit absolute jump into native code (address in rax)
// mov rax, immediate64
// jmp [rax]
*(Pointer_Raw_Source + 0x00) = 0x48;
*(Pointer_Raw_Source + 0x01) = 0xB8;
*Pointer_Raw_Address = Destination_Base; // ( Pointer_Raw_Source + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 )
*(Pointer_Raw_Source + 0x0A) = 0xFF;
*(Pointer_Raw_Source + 0x0B) = 0xE0;
}
else
{
// 32-bit systems use 32-bit relative offset and jump
// 5 byte destructive
var Source_IntPtr = src.MethodHandle.GetFunctionPointer();
// Backup Source Data
var backup = new byte[0x5];
Marshal.Copy(Source_IntPtr, backup, 0, 0x5);
PatchedData.Add(src, backup);
// Get function pointers
int Source_Base = Source_IntPtr.ToInt32();
int Destination_Base = dst.MethodHandle.GetFunctionPointer().ToInt32();
// Native source address
byte* Pointer_Raw_Source = (byte*) Source_Base;
// Pointer to insert jump address into native code
int* Pointer_Raw_Address = (int*) (Pointer_Raw_Source + 1);
// Jump offset (less instruction size)
int offset = (Destination_Base - Source_Base) - 5;
// Insert 32-bit relative jump into native code
*Pointer_Raw_Source = 0xE9;
*Pointer_Raw_Address = offset;
}
}
catch (Exception ex)
{
Debug.LogError($"Unable to detour: {src?.Name ?? "UnknownSrc"} -> {dst?.Name ?? "UnknownDst"}\n{ex}");
throw;
}
}
static unsafe void RestoreDetour(MethodInfo src) {
var Source_IntPtr = src.MethodHandle.GetFunctionPointer();
var backup = PatchedData[src];
Marshal.Copy(backup, 0, Source_IntPtr, backup.Length);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment