如何更换一个指针的指针在类我的方法的方法从系统类继承? [英] How to replace a pointer to a pointer to a method in a class of my method inherited from the system class?

查看:110
本文介绍了如何更换一个指针的指针在类我的方法的方法从系统类继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已经问过这个问题。
如何更换指针在我的方法的指针覆盖(虚拟)的方法? (发布x64和x86)
感谢@Machine学习,解决了这个问题。但是,新的问题又出现了。如果系统从类,如Systems.Windows.Forms继承,则变更不起作用。
示例:

Already asked this question. How to replace the pointer to the overridden (virtual) method in the pointer of my method? (Release x64 and x86) Thanks @Machine Learning, solved the problem. But a new problem arose. If the system inherited from the class, such as "Systems.Windows.Forms", then the change does not work. Example:

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace ReplaceHandles
{
    public class Target1 : UserControl
    {
        public void test()
        {
            Console.WriteLine("Target1.test()");
        }
    }

    public class Target2
    {
        public void test()
        {
            Console.WriteLine("Target2.test()");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Injection.Replace();
            var target = new Target1();
            target.test();
            Console.Read();
        }
    }
}



类,取代指针

Class that replaces pointers

    public class Injection
    {
        public static void Replace()
        {
            var methodToReplace = typeof(Target1).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
            var methodToInject = typeof(Target2).GetMethod("test", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
            RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
            RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
            if (methodToReplace.IsVirtual) ReplaceVirtualInner(methodToReplace, methodToInject);
            else ReplaceInner(methodToReplace, methodToInject);
        }



更换虚拟方法

Replacing the virtual methods

        static void ReplaceVirtualInner(MethodInfo methodToReplace, MethodInfo methodToInject)
        {
            unsafe
            {
                var methodDesc = (UInt64*)(methodToReplace.MethodHandle.Value.ToPointer());
                var index = (int)(((*methodDesc) >> 32) & 0xFF);
                if (IntPtr.Size == 4)
                {
                    if (methodToReplace.DeclaringType != null)
                    {
                        var classStart = (uint*)methodToReplace.DeclaringType.TypeHandle.Value.ToPointer();
                        classStart += 10;
                        classStart = (uint*)*classStart;
                        var tar = classStart + index;

                        var inj = (uint*)methodToInject.MethodHandle.Value.ToPointer() + 2;
#if DEBUG

                        var injInst = (byte*)*inj;
                        var tarInst = (byte*)*tar;
                        var injSrc = (int*)(injInst + 1);
                        var tarSrc = (int*)(tarInst + 1);
                        *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                        *tar = *inj;
#endif
                    }
                }
                else
                {
                    if (methodToReplace.DeclaringType != null)
                    {
                        var classStart = (ulong*)methodToReplace.DeclaringType.TypeHandle.Value.ToPointer();
                        classStart += 8;
                        classStart = (ulong*)*classStart;
                        var tar = classStart + index;

                        var inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
                        var injInst = (byte*)*inj;
                        var tarInst = (byte*)*tar;
                        var injSrc = (int*)(injInst + 1);
                        var tarSrc = (int*)(tarInst + 1);
                        *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                        *tar = *inj;
#endif
                    }
                }
            }
        }

和更换不虚方法

        static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject)
        {
            unsafe
            {
                if (IntPtr.Size == 4)
                {
                    var inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
                    var tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
                    var injInst = (byte*)*inj;
                    var tarInst = (byte*)*tar;
                    var injSrc = (int*)(injInst + 1);
                    var tarSrc = (int*)(tarInst + 1);

                    *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    *tar = *inj;
#endif
                }
                else
                {
                    ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1;
                    ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
                    var injInst = (byte*)*inj;
                    var tarInst = (byte*)*tar;
                    var injSrc = (int*)(injInst + 1);
                    var tarSrc = (int*)(tarInst + 1);

                    *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
                    *tar = *inj;
#endif
                }
            }
        }
    }


推荐答案

在目标类是从 MarshalByRefObject的,那么 ReplaceInner (正常方法)停止工作,但 ReplaceVirtualInner (为覆盖方法)就可以了。

When the target class is derived from MarshalByRefObject, then the ReplaceInner (for normal methods) stops working but ReplaceVirtualInner (for overridden methods) is ok.

MarshalByRefObject的是,通过使用
代理交换信息沟通
跨应用程序域边界的对象的基类。不从MarshalByRefObject继承的对象是
隐含价值元帅。当远程应用程序引用通过值对象的
元帅,该对象的副本跨
应用程序域边界传递。

MarshalByRefObject is the base class for objects that communicate across application domain boundaries by exchanging messages using a proxy. Objects that do not inherit from MarshalByRefObject are implicitly marshal by value. When a remote application references a marshal by value object, a copy of the object is passed across application domain boundaries.

这可以通过标记为虚拟的方法来替代。

This could be partially fixed by marking as virtual the method to replace.

但是,当目标已部分修复类是从内容也衍生 ReplaceVirtualInner (为的覆盖方法)停止工作。

But when the target class is derived from Content also the ReplaceVirtualInner (for overridden methods) stops working.

不幸的是 Windows.Forms的从他们两个都得到,所以我没有看到一个简单的解决方法。

Unfortunately Windows.Forms are derived from both of them, so I don't see an easy work-around.

您可能要考虑一种不同的方法:的与PostSharp和面向方面编程,一个CodeProject上的文章文档有关跟踪

You may want to consider a different approach: a basic example of tracing with PostSharp and Aspect-Oriented Programming, a CodeProject article and the doc about tracing.

此外,另一种选择(不知道是否可能为你)是使用用户控件 WPF,而不是形式并在这种情况下的正常的方法的替代会的正常工作的(导入了所需的组件和取得的主要<$ C $之后C> [STAThread]

Furthermore, another alternative (don't know if possible for you) is to use the UserControl of WPF instead of Forms and in that case the normal method replacement would work fine (after you've imported the needed assemblies and made the Main [STAThread])

好吧,如果你真的想使它工作的不惜任何代价的,让我们继续倒车目标。

Ok, if you really want to make it work at any cost, let's proceed with reversing the target.

打开你用的 CFF浏览器

下找到<一表。HREF =http://www.ntcore.com/files/dotnetformat.htm#NETDir相对=nofollow> net目录 >元数据流键,取消组合方法表
你会发现2种方法与对应的2类(相同的名称和不同的 RVA 的TypeDef )。
你只需要ovverride目标 RVA 通过注射法 RVA 并保存反转的exe用新的名称。

Locate the tables under .Net Directory> MetaData Streams and ungroup the Method Tables. You will find the 2 methods with the same name and different RVA corresponding to the 2 classes (TypeDef). You simply have to ovverride the target RVA with the injection method RVA and save the reversed exe with a new name.

这篇关于如何更换一个指针的指针在类我的方法的方法从系统类继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆