/// <summary> /// Initializes a new instance of the OnyxRedirect class. /// </summary> public OnyxRedirect(IntPtr targetAddress, IntPtr detourAddress, string detourName, byte[] _originalBytes) { if (detourName != null) { m_name = detourName; } if (targetAddress == IntPtr.Zero) { throw new ArgumentNullException("targetAddress"); } if (detourAddress == IntPtr.Zero) { throw new ArgumentNullException("detourAddress"); } m_targetAddress = targetAddress; m_detourAddress = detourAddress; this._originalBytes = _originalBytes; var fasm = new RemoteFasm(); fasm.Clear(); fasm.AddLine("push {0}", detourAddress); fasm.AddLine("retn"); m_detourBytes = fasm.Assemble(); }
/// <summary> /// Initializes a new instance of the OnyxDetour class. /// </summary> public OnyxDetour(IntPtr _targetAddress, Delegate _detour, string _detourName = null) { if (_detourName != null) { m_name = _detourName; } if (_targetAddress == IntPtr.Zero) { throw new ArgumentNullException("_targetAddress"); } if (_detour == null) { throw new ArgumentNullException("_detour"); } m_detour = _detour; m_targetAddress = _targetAddress; IntPtr detourAddress = Marshal.GetFunctionPointerForDelegate(_detour); m_checkThread = CheckThread; var pCheckThread = Marshal.GetFunctionPointerForDelegate(m_checkThread); var fasm = new RemoteFasm(); fasm.Clear(); fasm.AddLine("@checkthread:"); fasm.AddLine("call $+5"); fasm.AddLine("add dword [esp], {0}", 5 + 4 + 1); fasm.AddLine("push 0{0:X}h", pCheckThread.ToInt64()); fasm.AddLine("retn"); fasm.AddLine("@checkthread_TestResults:"); fasm.AddLine("test eax,eax"); fasm.AddLine("jz @functionretn"); fasm.AddLine("@userfunction:"); fasm.AddLine("push 0{0:X}h", detourAddress.ToInt64()); fasm.AddLine("retn"); fasm.AddLine("@functionretn:"); var jumperBytes = fasm.Assemble(); pJumperCodeCave = Onyx.Instance.Memory.AllocateMemory(256); Onyx.Instance.Memory.WriteBytes(pJumperCodeCave, jumperBytes); fasm.Clear(); fasm.AddLine("push 0{0:X}h", pJumperCodeCave.ToInt64()); fasm.AddLine("retn"); m_detourBytes = fasm.Assemble(); disasm = new Disasm(); var realEip = m_targetAddress; var bytesDisassembled = 0; while (bytesDisassembled < m_detourBytes.Length) { var managedInstructionBuffer = Onyx.Instance.Memory.ReadBytes(realEip, 15); var instructionBuffer = new UnmanagedBuffer(managedInstructionBuffer); disasm.EIP = instructionBuffer.Ptr; var length = BeaEngine32.Disasm(disasm); if ((length != (int)BeaConstants.SpecialInfo.OUT_OF_BLOCK) && (length != (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)) { bytesDisassembled += length; if ((disasm.Instruction.BranchType == (int)BeaConstants.BranchType.JmpType) && (disasm.Instruction.AddrValue != 0)) { // jmp = modify EIP //disasm.EIP = (IntPtr)disasm.Instruction.AddrValue; } realEip = (IntPtr)((ulong)realEip + (ulong)length); } else { throw new Exception(String.Format("Disassembly error occured, exception code = {0}", length)); } } //Store the orginal bytes of decoded instructions in memory after jumper code m_originalBytes = Onyx.Instance.Memory.ReadBytes(m_targetAddress, bytesDisassembled); var pOriginalFunction = pJumperCodeCave.Add((UInt32)jumperBytes.Length); Onyx.Instance.Memory.WriteBytes(pOriginalFunction, m_originalBytes); m_originalFunction = Marshal.GetDelegateForFunctionPointer(pOriginalFunction, _detour.GetType()); var pReturnerCodeCave = pJumperCodeCave.Add((UInt32)jumperBytes.Length + (UInt32)bytesDisassembled); fasm.Clear(); fasm.AddLine("push 0{0:X}h", m_targetAddress.Add((UInt32)bytesDisassembled).ToInt64()); fasm.AddLine("retn"); var returnerBytes = fasm.Assemble(); Onyx.Instance.Memory.WriteBytes(pReturnerCodeCave, returnerBytes); // adding calling thread to exclusions Onyx.Instance.Detours.GlobalExcludedThreadId.Add(OnyxNative.GetCurrentThreadId()); }