Пример #1
0
        /// <summary>
        /// Creates a function hook for a function at a user specified address.
        /// This class provides Windows API (and general process) hooking functionality for standard cdecl, stdcall, as well as custom
        /// ReloadedFunction Attribute declared functions. For more details, see the description of the <see cref="FunctionHook{TDelegate}"/> class.
        /// </summary>
        /// <param name="gameFunctionAddress">The address of the game function to create the wrapper for.</param>
        /// <param name="functionDelegate">
        ///     A delegate instance of the supplied generic delegate type which calls/invokes
        ///     the C# method that will be used to handle the hook.
        /// </param>
        /// <param name="hookLength">
        ///     Optional explicit length of the hook to perform used in the impossibly rare
        ///     cases whereby auto-length checking overflows the default into a jmp/call.
        /// </param>
        /// <returns>
        ///     An instance of <see cref="FunctionHook{TFunction}"/>, which may be used
        ///     to call the original function.
        /// </returns>
        /// <remarks>
        ///     Due to safety and depth concerns regarding the use of multiple hooks on a singular address,
        ///     the class does not provide an implementation allowing you to unhook. Please instead implement
        ///     a flag and just call + return value from the original method without changing any of the input
        ///     parameters if you wish to achieve the same effect.
        /// </remarks>
        public FunctionHook(long gameFunctionAddress, TFunction functionDelegate, int hookLength)
        {
            FunctionHook <TFunction> localFunctionHook = CreateFunctionHook(gameFunctionAddress, functionDelegate, hookLength);

            this.OriginalFunction  = localFunctionHook.OriginalFunction;
            this._originalDelegate = localFunctionHook._originalDelegate;
        }
Пример #2
0
        /// <summary>
        /// Creates a function hook for a function at a user specified address.
        /// This class provides Windows API (and general process) hooking functionality for standard cdecl, stdcall, as well as custom
        /// ReloadedFunction Attribute declared functions. For more details, see the description of the <see cref="FunctionHook{TDelegate}"/> class.
        /// </summary>
        /// <param name="gameFunctionAddress">The address of the game function to create the wrapper for.</param>
        /// <param name="functionDelegate">
        ///     A delegate instance of the supplied generic delegate type which calls/invokes
        ///     the C# method that will be used to handle the hook.
        /// </param>
        /// <param name="hookLength">
        ///     Optional explicit length of the hook to perform used in the impossibly rare
        ///     cases whereby auto-length checking overflows the default into a jmp/call.
        /// </param>
        /// <returns>
        ///     An instance of <see cref="FunctionHook{TFunction}"/>, which may be used
        ///     to call the original function.
        /// </returns>
        /// <remarks>
        ///     Due to safety and depth concerns regarding the use of multiple hooks on a singular address,
        ///     the class does not provide an implementation allowing you to unhook. Please instead implement
        ///     a flag and just call + return value from the original method without changing any of the input
        ///     parameters if you wish to achieve the same effect.
        /// </remarks>
        public static FunctionHook <TFunction> CreateFunctionHook(long gameFunctionAddress, TFunction functionDelegate, int hookLength)
        {
            /*
             *  Retrieve C# function details.
             */

            // Retrieve the function address from the supplied user delegate.
            // Our ReloadedFunction attribute.
            IntPtr cSharpFunctionAddress = Marshal.GetFunctionPointerForDelegate(functionDelegate);
            ReloadedFunctionAttribute reloadedFunction = GetReloadedFunctionAttribute <TFunction>();

            /*
             *  [Hook Part I] Create Custom => CDECL Wrapper and Assemble
             */

            // Assemble the wrapper function.
            // Assemble a jump to our wrapper function.
            IntPtr      wrapperFunctionAddress = CreateWrapperFunction <TFunction>(cSharpFunctionAddress, reloadedFunction);
            List <byte> jumpBytes = HookCommon.AssembleAbsoluteJump(wrapperFunctionAddress).ToList();

            /*
             *  [Hook Part II] Calculate Hook Length (Unless Explicit)
             */

            // Retrieve hook length explicitly
            if (hookLength == -1)
            {
                hookLength = HookCommon.GetHookLength((IntPtr)gameFunctionAddress, jumpBytes.Count);
            }

            // Assemble JMP + NOPs for stolen/stray bytes.
            if (hookLength > jumpBytes.Count)
            {
                // Append NOPs after JMP to fill remaining bytes.
                int nopBytes = hookLength - jumpBytes.Count;

                for (int x = 0; x < nopBytes; x++)
                {
                    jumpBytes.Add(0x90);
                }
            }

            /*
             *  [Call Original Function Part I] Read stolen bytes and assemble function wrapper to call original function.
             */

            // Backup game's hook bytes.
            // Check if stolen bytes contains a jmp as first (other hooks)
            // Calculate jump back address for original function.
            // Append absolute JMP instruction to return to original function for calling the original function in hook.
            List <byte> stolenBytes = Bindings.TargetProcess.ReadMemoryExternal((IntPtr)gameFunctionAddress, hookLength).ToList();

            stolenBytes = HookCommon.ProcessStolenBytes(stolenBytes, (IntPtr)gameFunctionAddress);

            IntPtr jumpBackAddress = (IntPtr)(gameFunctionAddress + hookLength);

            stolenBytes.AddRange(HookCommon.AssembleAbsoluteJump(jumpBackAddress));

            /*
             *  [Call Original Function part II] Instantiate and return functionHook with the original game function address.
             */

            // Assign original function.
            FunctionHook <TFunction> functionHook = new FunctionHook <TFunction>();

            // Write original bytes and jump to memory, and return address.
            IntPtr gameFunctionWrapperAddress = MemoryBuffer.Add(stolenBytes.ToArray());

            // Create wrapper for calling the original function.
            functionHook.OriginalFunction = FunctionWrapper.CreateWrapperFunction <TFunction>((long)gameFunctionWrapperAddress);

            // Store a copy of the original function.
            functionHook._originalDelegate = functionDelegate;

            /*
             *  [Apply Hook] Write hook bytes.
             */
            Bindings.TargetProcess.WriteMemoryExternal((IntPtr)gameFunctionAddress, jumpBytes.ToArray());

            return(functionHook);
        }