private static void Create(ReverseWrapper <TFunction> reverseFunctionWrapper, nuint functionPtr)
        {
            var attribute = FunctionAttribute.GetAttribute <TFunction>();

            // Hot path: Don't create wrapper if both conventions are already compatible.
            var managedFuncAttribute = Misc.TryGetAttributeOrDefault <TFunction, ManagedFunctionAttribute>();

            if (managedFuncAttribute != null)
            {
                if (managedFuncAttribute.Equals(attribute))
                {
                    reverseFunctionWrapper.WrapperPointer = Utilities.CreateJump(functionPtr, false, Constants.MaxAbsJmpSize).ToSigned();
                    return;
                }

                reverseFunctionWrapper.WrapperPointer = Wrapper.Create <TFunction>(functionPtr, managedFuncAttribute, attribute).ToSigned();
                return;
            }

            var funcPtrAttribute = Misc.TryGetAttributeOrDefault <TFunction, UnmanagedFunctionPointerAttribute>();

            if (!attribute.IsEquivalent(funcPtrAttribute))
            {
                reverseFunctionWrapper.WrapperPointer = Wrapper.Create <TFunction>(functionPtr, attribute.GetEquivalent(funcPtrAttribute), attribute).ToSigned();
            }
            else
            {
                reverseFunctionWrapper.WrapperPointer = Utilities.CreateJump(functionPtr, false, Constants.MaxAbsJmpSize).ToSigned();
            }
        }
Exemplo n.º 2
0
        private static void Create(ReverseWrapper <TFunction> reverseFunctionWrapper, IntPtr functionPtr)
        {
            var attribute = FunctionAttribute.GetAttribute <TFunction>();

            // Hot path: Don't create wrapper if both conventions are already compatible.
            var managedFuncAttribute = Misc.TryGetAttributeOrDefault <TFunction, ManagedFunctionAttribute>();

            if (managedFuncAttribute != null)
            {
                if (managedFuncAttribute.Equals(attribute))
                {
                    return;
                }

                reverseFunctionWrapper.WrapperPointer = Wrapper.Create <TFunction>(functionPtr, managedFuncAttribute, attribute);
                return;
            }

            var funcPtrAttribute = Misc.TryGetAttributeOrDefault <TFunction, UnmanagedFunctionPointerAttribute>();

            if (!attribute.IsEquivalent(funcPtrAttribute))
            {
                reverseFunctionWrapper.WrapperPointer = Wrapper.Create <TFunction>(functionPtr, attribute.GetEquivalent(funcPtrAttribute), attribute);
            }
        }
Exemplo n.º 3
0
        private static void Create(Hook <TFunction> hook, ReverseWrapper <TFunction> reverseWrapper, long functionAddress, int minHookLength = -1)
        {
            /*
             *  === Hook Summary ===
             *
             *  A. Insert Absolute Jump to ReverseWrapper (Convention => CDECL Marshaller)
             *      A1. Backup original bytes and patch between start and end of JMP for (B).
             *
             *  B. Setup Wrapper to call original function (CDECL => Convention Marshaller)
             *      B1. Take bytes backed up from A, and create stub function with those
             *          bytes and JMP to end of hook.
             *      B2. Assign OriginalFunction to that function stub.
             */

            /* Create Convention => CDECL Wrapper. */
            List <byte> jumpOpcodes = Utilities.AssembleAbsoluteJump(reverseWrapper.WrapperPointer, false).ToList();

            /* Calculate Hook Length (Unless Explicit) */

            if (minHookLength == -1)
            {
                minHookLength = Utilities.GetHookLength((IntPtr)functionAddress, jumpOpcodes.Count, ArchitectureMode.x86_32);
            }

            // Sometimes our hook can be larger than the amount of bytes taken by the jmp opcode.
            // We need to fill the remaining bytes with NOPs.
            if (minHookLength > jumpOpcodes.Count)
            {
                int nopBytes = minHookLength - jumpOpcodes.Count;

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

            /* Get bytes from original function prologue and patch them. */
            CurrentProcess.SafeReadRaw((IntPtr)functionAddress, out byte[] originalFunction, minHookLength);

            var functionPatcher = new FunctionPatcher(ArchitectureMode.x86_32);
            var functionPatch   = functionPatcher.Patch(originalFunction.ToList(), (IntPtr)functionAddress);

            IntPtr hookEndAddress = (IntPtr)(functionAddress + minHookLength);

            functionPatch.NewFunction.AddRange(Utilities.AssembleAbsoluteJump(hookEndAddress, false));

            /* Commit the original modified function to memory. */
            byte[] patchedFunction        = functionPatch.NewFunction.ToArray();
            var    buffer                 = Utilities.FindOrCreateBufferInRange(patchedFunction.Length);
            var    patchedFunctionAddress = buffer.Add(patchedFunction);

            /* Create Hook instance. */
            hook.OriginalFunctionAddress = patchedFunctionAddress;
            hook.OriginalFunction        = Wrapper.Create <TFunction>((long)patchedFunctionAddress);
            hook.ReverseWrapper          = reverseWrapper;
            hook._otherHookPatches       = functionPatch.Patches;
            hook._hookPatch = new Patch((IntPtr)functionAddress, jumpOpcodes.ToArray());
        }
Exemplo n.º 4
0
        private static void Create(ReverseWrapper <TFunction> reverseFunctionWrapper, IntPtr functionPtr)
        {
            var reloadedFunctionAttribute = FunctionAttribute.GetAttribute <TFunction>();

            // CDECL is hot path, as our TFunction will already be CDECL, we marshal if it's anything else.
            if (!reloadedFunctionAttribute.Equals(new FunctionAttribute(CallingConventions.Cdecl)))
            {
                reverseFunctionWrapper.WrapperPointer = Create(functionPtr, reloadedFunctionAttribute);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a hook for a function at a given address.
        /// </summary>
        /// <param name="function">The function to detour the original function to.</param>
        /// <param name="functionAddress">The address of the function to hook.</param>
        /// <param name="minHookLength">Optional explicit length of hook. Use only in rare cases where auto-length check overflows a jmp/call opcode.</param>
        public Hook(TFunction function, long functionAddress, int minHookLength = -1)
        {
            var reverseWrapper = new ReverseWrapper <TFunction>(function);

            Create(this, reverseWrapper, functionAddress, minHookLength);
        }