예제 #1
0
        /// <summary>
        /// Allows you to insert a set of your own assembly instructions in the middle of a game function and have the game conditionally redirect
        /// to said function.
        ///
        /// The hook requires a minimum of 6 (X86) or 7 (X64) bytes and will therefore overwrite as many instructions as it needs until it can get enough space
        /// to place the hook. If you have ever used Cheat ENgine's assembly injection, you're already familliar on how to work with this class.
        /// </summary>
        /// <param name="hookAddress">
        ///     The memory address for which the hook is to be generated.
        /// </param>
        /// <param name="mnemonics">
        ///     X86-32 or X64 FASM compatible assembly code that starts with the line use16, use32 or use64 for identifying the architecture.
        /// </param>
        /// <param name="originalInstructionOptions">
        ///     Defines a switch for the assembly hook builder telling it what should be done with the original set of bytes that are going to be
        ///     replaced with the jump opcode.
        /// </param>
        /// <param name="hookLength">[Optional] The explicit amount of bytes to overwrite when inserting the actual hook.</param>
        public AssemblyHook(IntPtr hookAddress, string[] mnemonics, OriginalInstructionOptions originalInstructionOptions, int hookLength = -1)
        {
            // Set hook address.
            HookAddress = hookAddress;

            // Our 32bit and 64bit code paths will differ once we get the disassembler rolling.
            bool is64bit = mnemonics[0] == "use64";

            // Get the default for architecture, then true hook length.
            if (hookLength == -1)
            {
                hookLength = GetDefaultHookLength(is64bit);

                ArchitectureMode disassemblerMode = is64bit ? ArchitectureMode.x86_64 : ArchitectureMode.x86_32;
                hookLength = HookCommon.GetHookLength(HookAddress, hookLength, disassemblerMode);
            }

            // Assemble our custom ASM hook function to be jumped to and executed by the game, then write it to memory.
            IntPtr returnAddress = HookAddress + hookLength;

            byte[] assembledBytes = Assembler.Assembler.Assemble(mnemonics);
            assembledBytes = ProcessCustomInstructions(assembledBytes, OriginalBytes, originalInstructionOptions);
            assembledBytes = AppendJumpBack(assembledBytes, is64bit, returnAddress);
            AsmHookAddress = MemoryBufferManager.Add(assembledBytes);

            // Backup our bytes to hook.
            OriginalBytes = Bindings.TargetProcess.ReadMemory(HookAddress, hookLength);

            // Setup our new bytes to overwrite the old ones with (absolute jump).
            NewBytes = new byte[hookLength];
            Populate(NewBytes, (byte)0x90);                          // NOP
            byte[] hookJump = AssembleJump(is64bit, AsmHookAddress); // Assemble absolute jump and copy to array of NOPs.
            Array.Copy(hookJump, NewBytes, hookJump.Length);
        }
예제 #2
0
 /// <summary>
 /// Assembles an absolute jump either from the end of the hook back, or to the hook.
 /// </summary>
 /// <param name="is64Bit">Set to true to assemble a 64bit jump, else 32bit.</param>
 /// <param name="jumpAddress">The address to jump to.</param>
 /// <returns>An bytes for an absolute jump back to the end of the hook.</returns>
 private byte[] AssembleJump(bool is64Bit, IntPtr jumpAddress)
 {
     return(is64Bit ?
            HookCommon.X64AssembleAbsoluteJump(jumpAddress, new X64ReloadedFunctionAttribute(X64CallingConventions.Microsoft)):
            HookCommon.X86AssembleAbsoluteJump(jumpAddress));
 }
예제 #3
0
 /// <summary>
 /// Assembles a dummy jump to an absolute address in order to get the length of an absolute jump under
 /// X86/X64.
 /// </summary>
 /// <param name="is64Bit">Set to true to calculate a 64bit absolute jump length.</param>
 /// <returns></returns>
 private int GetDefaultHookLength(bool is64Bit)
 {
     return(is64Bit ?
            HookCommon.X64AssembleAbsoluteJump((IntPtr)0x11223344, new X64ReloadedFunctionAttribute(X64CallingConventions.Microsoft)).Length :
            HookCommon.X86AssembleAbsoluteJump((IntPtr)0x11223344).Length);
 }