Exemple #1
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);
            }
        }
        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();
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates the <see cref="Wrapper"/> in memory allowing you to call a function
        /// at functionAddress as if it was a CDECL function.
        /// </summary>
        /// <param name="functionAddress">The address of the function.</param>
        /// <param name="fromFunction">Describes the properties of the function to wrap.</param>
        /// <returns>Address of the wrapper in memory you can call like a CDECL function.</returns>
        public static IntPtr Create <TFunction>(IntPtr functionAddress, FunctionAttribute fromFunction)
        {
            // toFunction (target) is CDECL
            int           numberOfParameters    = Utilities.GetNumberofParameters(typeof(TFunction));
            int           nonRegisterParameters = numberOfParameters - fromFunction.SourceRegisters.Length;
            List <string> assemblyCode          = new List <string> {
                "use32"
            };

            // Backup Stack Frame
            assemblyCode.Add("push ebp");       // Backup old call frame
            assemblyCode.Add("mov ebp, esp");   // Setup new call frame

            // Reserve Extra Stack Space
            if (fromFunction.ReservedStackSpace > 0)
            {
                assemblyCode.Add($"sub esp, {fromFunction.ReservedStackSpace}");
            }

            // Setup Function Parameters
            if (numberOfParameters > 0)
            {
                assemblyCode.AddRange(AssembleFunctionParameters(numberOfParameters, fromFunction.SourceRegisters));
            }

            // Call target function
            var    pointerBuffer     = Utilities.FindOrCreateBufferInRange(IntPtr.Size);
            IntPtr targetFunctionPtr = pointerBuffer.Add(ref functionAddress);

            assemblyCode.Add("call dword [0x" + targetFunctionPtr.ToString("X") + "]");

            // Stack cleanup if necessary
            if (nonRegisterParameters > 0 && fromFunction.Cleanup == FunctionAttribute.StackCleanup.Caller)
            {
                assemblyCode.Add($"add esp, {nonRegisterParameters * 4}");
            }

            // Setup return register
            if (fromFunction.ReturnRegister != FunctionAttribute.Register.eax)
            {
                assemblyCode.Add("mov eax, " + fromFunction.ReturnRegister);
            }

            // Unreserve Extra Stack Space
            if (fromFunction.ReservedStackSpace > 0)
            {
                assemblyCode.Add($"add esp, {fromFunction.ReservedStackSpace}");
            }

            // Restore Stack Frame and Return
            assemblyCode.Add("pop ebp");
            assemblyCode.Add("ret");

            // Write function to buffer and return pointer.
            byte[] assembledMnemonics = Utilities.Assembler.Assemble(assemblyCode.ToArray());
            var    wrapperBuffer      = Utilities.FindOrCreateBufferInRange(assembledMnemonics.Length);

            return(wrapperBuffer.Add(assembledMnemonics));
        }
        private static IntPtr Create(IntPtr functionAddress, FunctionAttribute fromFunction)
        {
            // CDECL is hot path, as our TFunction will already be CDECL, we marshal if it's anything else.
            if (fromFunction.Equals(new FunctionAttribute(CallingConventions.Cdecl)))
            {
                return(functionAddress);
            }

            // Retrieve number of parameters and setup list of ASM instructions to be compiled.
            int           numberOfParameters    = Utilities.GetNumberofParameters(typeof(TFunction));
            int           nonRegisterParameters = numberOfParameters - fromFunction.SourceRegisters.Length;
            List <string> assemblyCode          = new List <string> {
                "use32"
            };

            // Backup Stack Frame
            assemblyCode.Add("push ebp");       // Backup old call frame
            assemblyCode.Add("mov ebp, esp");   // Setup new call frame

            // Push registers for our C# method as necessary.
            assemblyCode.AddRange(AssembleFunctionParameters(numberOfParameters, fromFunction.SourceRegisters));

            // Call target function
            var    pointerBuffer     = Utilities.FindOrCreateBufferInRange(IntPtr.Size);
            IntPtr targetFunctionPtr = pointerBuffer.Add(ref functionAddress);

            assemblyCode.Add("call dword [0x" + targetFunctionPtr.ToString("X") + "]");

            // MOV EAX return register into custom calling convention's return register.
            if (fromFunction.ReturnRegister != FunctionAttribute.Register.eax)
            {
                assemblyCode.Add($"mov {fromFunction.ReturnRegister}, eax");
            }

            // Restore stack pointer.
            if (numberOfParameters > 0)
            {
                assemblyCode.Add($"add esp, {numberOfParameters * 4}");
            }

            // Restore Stack Frame and Return
            assemblyCode.Add("pop ebp");

            if (fromFunction.Cleanup == FunctionAttribute.StackCleanup.Callee)
            {
                assemblyCode.Add($"ret {nonRegisterParameters * 4}");
            }
            else
            {
                assemblyCode.Add("ret");
            }

            byte[] assembledMnemonics = Utilities.Assembler.Assemble(assemblyCode.ToArray());
            var    wrapperBuffer      = Utilities.FindOrCreateBufferInRange(assembledMnemonics.Length);

            return(wrapperBuffer.Add(assembledMnemonics));
        }
        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);
            }
        }
        public override bool Equals(Object obj)
        {
            FunctionAttribute functionAttribute = obj as FunctionAttribute;

            if (functionAttribute == null)
            {
                return(false);
            }

            return(functionAttribute.Cleanup == Cleanup &&
                   functionAttribute.ReturnRegister == ReturnRegister &&
                   functionAttribute.SourceRegisters.SequenceEqual(SourceRegisters));
        }
Exemple #7
0
        /// <summary>
        /// Creates the <see cref="Wrapper"/> which allows you to call a function with a custom calling
        /// convention as if it were a CDECL function.
        /// </summary>
        /// <param name="functionAddress">Address of the function to reverse wrap..</param>
        public static TFunction Create <TFunction>(long functionAddress)
        {
            var    attribute = FunctionAttribute.GetAttribute <TFunction>();
            IntPtr wrapperFunctionPointer = (IntPtr)functionAddress;

            // Hot path: CDECL functions require no wrapping.
            if (!attribute.Equals(new FunctionAttribute(CallingConventions.Cdecl)))
            {
                wrapperFunctionPointer = Create <TFunction>((IntPtr)functionAddress, attribute);
            }

            return(Marshal.GetDelegateForFunctionPointer <TFunction>(wrapperFunctionPointer));
        }