public static RedirectCallsState RevertJumpTo(IntPtr site, RedirectCallsState state) { RedirectCallsState detourState; unsafe { byte* sitePtr = (byte*)site.ToPointer(); detourState = GetState(sitePtr); *sitePtr = state.a; // mov r11, target *(sitePtr + 1) = state.b; *((ulong*)(sitePtr + 2)) = state.f; *(sitePtr + 10) = state.c; // jmp r11 *(sitePtr + 11) = state.d; *(sitePtr + 12) = state.e; } return detourState; }
public static void Deploy() { if (_deployed) { return; } if (_originalPtr == IntPtr.Zero) { _originalPtr = typeof(BuildingManager).GetMethod("CalculateOutsideConnectionCount", BindingFlags.Instance | BindingFlags.Public).MethodHandle.GetFunctionPointer(); } if (_detourPtr == IntPtr.Zero) { _detourPtr = typeof(BuildingManagerDetour).GetMethod("CalculateOutsideConnectionCount", BindingFlags.Instance | BindingFlags.Public).MethodHandle.GetFunctionPointer(); } _state = RedirectionHelper.PatchJumpTo(_originalPtr, _detourPtr); _deployed = true; }
private static unsafe RedirectCallsState GetState(byte* sitePtr) { var state = new RedirectCallsState { a = *sitePtr, b = *(sitePtr + 1), c = *(sitePtr + 10), d = *(sitePtr + 11), e = *(sitePtr + 12), f = *((ulong*) (sitePtr + 2)) }; return state; }
public static void RevertRedirect(MethodInfo from, RedirectCallsState state) { var fptr1 = from.MethodHandle.GetFunctionPointer(); RevertJumpTo(fptr1, state); }