/// <summary>
        /// This hook class executes your own ASM Code from a supplied list of bytes.
        /// To use this hook, you require at least a hook length of 6 bytes + any stray bytes from any instruction. For more information, do refer to the Wiki on Github.
        /// </summary>
        /// <param name="hookAddress">The address at which we will start our hook process.</param>
        /// <param name="asmBytes">Delegate to the method we will want to run. (DelegateName)Method</param>
        /// <param name="hookLength">The amount of bytes the hook lasts, all stray bytes will be replaced with NOP/No Operation.</param>
        /// <param name="modLoaderServerSocket">Current Socket that is Connected to the Mod Loader Server</param>
        /// <param name="cleanHook">Set true to not execute original bytes after your own ASM</param>
        public ASM_Hook(IntPtr hookAddress, byte[] asmBytes, int hookLength, WebSocket_Client modLoaderServerSocket, bool cleanHook)
        {
            // Setup Common Hook Properties
            SetupHookCommon(hookAddress, hookLength);

            // Check for compatible Mod Loader Hook Method Signature, If Signature Found, Do not Clean Hook!
            if (cleanHook)
            {
                cleanHook = CheckCleanHook();
            }

            // Run the hook builder.
            Hook_ASM_Internal(modLoaderServerSocket, asmBytes, cleanHook);
        }
        /// <summary>
        /// The inner workings of the Injection Hook Type.
        /// </summary>
        private void Hook_ASM_Internal(WebSocket_Client modLoaderServerSocket, byte[] asmBytes, bool cleanHook)
        {
            // Allocate memory to write old bytes in Sonic Heroes.
            SetNewInstructionAddress(PUSH_RETURN_INSTRUCTION_LENGTH + asmBytes.Length + hookLength + PUSH_RETURN_INSTRUCTION_LENGTH);

            ///
            /// The Bytes of code we will overwrite the original to toggle the injection.
            ///

            // Assemble a return address to our own injection code.
            newBytes = AssembleReturn((int)newInstructionAddress, modLoaderServerSocket);

            // Fill with NOPs until the hook length.
            newBytes = FillNOPs(newBytes);

            ///
            /// The Bytes of our Injected Code
            ///

            // The bytes to be written to the newly allocated memory.
            List <byte> injectionBytes = new List <byte>();

            // Append Jump call to Own Code
            injectionBytes.AddRange(asmBytes);

            // Insert the original bytes to be executed.
            if (cleanHook)
            {
                injectionBytes.AddRange(ProduceNOPArray(originalBytes.Length));
            }
            else
            {
                injectionBytes.AddRange(originalBytes);
            }

            // Insert bytes to return back.
            injectionBytes.AddRange(AssembleReturn((int)hookAddress + PUSH_RETURN_INSTRUCTION_LENGTH, modLoaderServerSocket));

            // List to Array!
            newInstructionBytes = injectionBytes.ToArray();

            /// Write our payload which will be redirected to using activate and deactivate hook!
            Marshal.Copy(newInstructionBytes, 0, newInstructionAddress, newInstructionBytes.Length);
        }
Example #3
0
        /// <summary>
        /// The inner workings of the Injection Hook Type.
        /// </summary>
        private void Injection_Internal(WebSocket_Client modLoaderServerSocket, bool cleanHook)
        {
            // Allocate memory to write old bytes in Sonic Heroes.
            SetNewInstructionAddress(REGISTERS_TO_BACKUP_LENGTH + PUSH_RETURN_INSTRUCTION_LENGTH + hookLength + REGISTERS_TO_BACKUP_LENGTH + PUSH_RETURN_INSTRUCTION_LENGTH);

            ///
            /// The Bytes of code we will overwrite the original to toggle the injection.
            ///

            // Assemble a return address to our own injection code.
            newBytes = AssembleReturn((int)newInstructionAddress, modLoaderServerSocket);

            // Fill with NOPs until the hook length.
            newBytes = FillNOPs(newBytes);

            ///
            /// The Bytes of our Injected Code
            ///

            // The bytes to be written to the newly allocated memory.
            List <byte> injectionBytes = new List <byte>();

            // Append Register Backup
            injectionBytes.AddRange(ASM_PUSH_REGISTERS_BYTES);

            // Calculate PUSH Which will allow our own code to return beyond the return statement for the call to our own code.
            // PUSH, PUSH, RET, <JUMP BACK HERE>

            /*
             * e.g.
             * [1000] PUSH 1007
             * [1005] PUSH <Own Code Address>
             * [1006] RET
             * [1007] pop edi
             */
            injectionBytes.AddRange(AssemblePush((int)newInstructionAddress + REGISTERS_TO_BACKUP_LENGTH + PUSH_INSTRUCTION_LENGTH + PUSH_RETURN_INSTRUCTION_LENGTH, modLoaderServerSocket));

            // Append Push + Return Call to Own Code
            injectionBytes.AddRange(AssembleReturn((int)funcionPointerToOwnMethodCall, modLoaderServerSocket));

            // Append Restoration of Registers.
            injectionBytes.AddRange(ASM_POP_REGISTERS_BYTES);

            // Insert the original bytes to be executed.
            if (cleanHook)
            {
            }
            else
            {
                injectionBytes.AddRange(originalBytes);
            }

            // Insert bytes to return back.
            injectionBytes.AddRange(AssembleReturn((int)hookAddress + PUSH_RETURN_INSTRUCTION_LENGTH, modLoaderServerSocket));

            // List to Array!
            newInstructionBytes = injectionBytes.ToArray();

            /// Write our payload which will be redirected to using activate and deactivate hook!
            Marshal.Copy(newInstructionBytes, 0, newInstructionAddress, newInstructionBytes.Length);
        }
Example #4
0
        /// <summary>
        /// This hook class generates a call to your code, keeps registers intact and executes the original code after your code has finished executing.
        /// To use this hook, you require at least a hook length of 5 bytes + any stray bytes from any instruction. For more information, do refer to the Wiki on Github.
        /// </summary>
        /// <param name="hookAddress">The address at which we will start our hook process.</param>
        /// <param name="destinationDelegate">Delegate to the method we will want to run. (DelegateName)Method</param>
        /// <param name="hookLength">The amount of bytes the hook lasts, all stray bytes will be replaced with NOP/No Operation.</param>
        /// <param name="cleanHook">Set true to not execute original bytes after your own code.</param>
        public Injection(IntPtr hookAddress, Delegate destinationDelegate, int hookLength, WebSocket_Client modLoaderServerSocket, bool cleanHook)
        {
            // Assign class members.
            customMethodDelegate = destinationDelegate;

            // Obtain pointer to our own C# method.
            funcionPointerToOwnMethodCall = Marshal.GetFunctionPointerForDelegate(customMethodDelegate);

            // Setup Common Hook Properties
            SetupHookCommon(hookAddress, hookLength);

            // Run the hook builder.
            Injection_Internal(modLoaderServerSocket, cleanHook);
        }