コード例 #1
0
        /// <summary>
        /// Generate a DynamicMethod to easily call the given native function from another DynamicMethod.
        /// </summary>
        /// <param name="target">The pointer to the native function to call.</param>
        /// <param name="signature">A MethodBase with the target function's signature.</param>
        /// <returns>The detoured DynamicMethod.</returns>
        public static DynamicMethod GenerateNativeProxy(IntPtr target, MethodBase signature)
        {
            Type returnType = (signature as MethodInfo)?.ReturnType ?? typeof(void);

            ParameterInfo[] args     = signature.GetParameters();
            Type[]          argTypes = new Type[args.Length];
            for (int i = 0; i < args.Length; i++)
            {
                argTypes[i] = args[i].ParameterType;
            }

            DynamicMethod dm = new DynamicMethod(
                $"native_{((long) target).ToString("X16")}",
                returnType, argTypes,
                true
                ).StubCriticalDetour();

            // Detour the new DynamicMethod into the target.
            NativeDetourData detour = Native.Create(dm.GetNativeStart(), target);

            Native.MakeWritable(detour);
            Native.Apply(detour);
            Native.MakeExecutable(detour);
            Native.Free(detour);

            return(dm.Pin());
        }
コード例 #2
0
        public Detour(MethodBase from, MethodBase to)
        {
            Method = from;
            Target = to;

            // TODO: Check target method arguments.

            if (!_BackupMethods.ContainsKey(Method))
            {
                _BackupMethods[Method] = Method.CreateILCopy();
            }

            // Generate a "chained trampoline" DynamicMethod.
            ParameterInfo[] args = Method.GetParameters();
            Type[]          argTypes;
            if (!Method.IsStatic)
            {
                argTypes    = new Type[args.Length + 1];
                argTypes[0] = Method.DeclaringType;
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i + 1] = args[i].ParameterType;
                }
            }
            else
            {
                argTypes = new Type[args.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i] = args[i].ParameterType;
                }
            }

            _ChainedTrampoline = new DynamicMethod(
                $"chain_{Method.Name}_{GetHashCode()}",
                (Method as MethodInfo)?.ReturnType ?? typeof(void), argTypes,
                Method.DeclaringType,
                false // Otherwise just ret is invalid for whatever reason.
                ).StubCriticalDetour().Pin();

            // Add the detour to the detour map.
            List <Detour> detours;

            lock (_DetourMap) {
                if (!_DetourMap.TryGetValue(Method, out detours))
                {
                    _DetourMap[Method] = detours = new List <Detour>();
                }
            }
            lock (detours) {
                // New Detour instances are always on the top.
                if (detours.Count > 0)
                {
                    detours[detours.Count - 1]._TopUndo();
                }
                _TopApply();

                // Do the initial "chained trampoline" setup.
                NativeDetourData link;
                if (detours.Count > 0)
                {
                    // If a previous Detour exists in the chain, detour our "chained trampoline" to it,
                    link = DetourManager.Native.Create(
                        _ChainedTrampoline.GetNativeStart(),
                        detours[detours.Count - 1].Target.GetNativeStart()
                        );
                }
                else
                {
                    // If this is the first Detour in the chain, detour our "chained trampoline" to the original method.
                    link = DetourManager.Native.Create(
                        _ChainedTrampoline.GetNativeStart(),
                        _BackupMethods[Method].GetNativeStart()
                        );
                }
                DetourManager.Native.MakeWritable(link);
                DetourManager.Native.Apply(link);
                DetourManager.Native.MakeExecutable(link);
                DetourManager.Native.Free(link);

                detours.Add(this);
            }
        }