Как использовать GetMethod в моем собственном классе, запутанном ConfuserEx?

У меня есть собственная DLL, которую я защищаю с помощью ConfuserEx. В ConfuserEx я использую защиту "переименовать":

<protection id="rename">
    <argument name="mode" value="unicode" />
    <argument name="renEnum" value="true" />        
</protection>    

Это, конечно, защищает DLL от просмотра кода, но мой класс (который я защитил как часть DLL) использует:

MethodInfo mi = typeof(MyClass).GetMethod(nameof(MyStaticMethod), BindingFlags.Static | BindingFlags.NonPublic);

Здесь начинается проблема, потому что даже мой собственный код не может найти и использовать мой (защищенный ConfuserEx) метод. Я использую GetMethod для вызова: Delegate.CreateDelegate. Что я могу сделать, чтобы решить эту проблему?


person g_m    schedule 11.12.2018    source источник
comment
Почему вам нужно использовать отражение для доступа к членам вашей собственной сборки?   -  person Damien_The_Unbeliever    schedule 11.12.2018
comment
Потому что я использую внешний класс, у которого есть делегат, и я хочу подключиться к нему, чтобы вызывался мой метод.   -  person g_m    schedule 11.12.2018
comment
Если метод предназначен для вызова внешним классом, вам, вероятно, следует исключить его из обфускации. .   -  person John Wu    schedule 11.12.2018
comment
Вы можете создать делегата для частного/внутреннего метода и передать его другой сборке без размышлений. Проверка доступности выполняется в момент создания экземпляра делегата.   -  person Damien_The_Unbeliever    schedule 11.12.2018


Ответы (2)


Я до сих пор не понимаю, почему вы не можете просто создать делегат, который вам нужен, напрямую, без отражения, но если вам действительно нужно получить MethodInfo, попробуйте сделать что-то вроде этого:

using System;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Thingy t = DoStuff;
        var mi = t.Method;
    }
    private delegate void Thingy(object sender, EventArgs e);
    private static void DoStuff(object sender, EventArgs e)
    {

    }
}

То есть используйте свой собственный локально определенный делегат, который соответствует другому определению делегата, создайте его экземпляр непосредственно в своем коде, а затем извлеките MethodInfo из этого экземпляра.

Этот код будет использовать токен метода для идентификации DoStuff, а не его имени, поэтому он должен выдержать обфускацию без проблем.

person Damien_The_Unbeliever    schedule 11.12.2018
comment
Похоже, мы пришли к похожей идее :) Спасибо за помощь. - person g_m; 11.12.2018

Я решил эту проблему, применив дополнительный «мост-делегат» между GetMethod и целевым методом. Затем вместо nameof(MyStaticMethod) я использую BridgeDelegate.Method.Name. Я проверил и работает правильно.

Пример решения:

internal static class MyClass
{
    private delegate void ExecuteObfuscatedMethod(string value);
    private static ExecuteObfuscatedMethod Bridge; //This is my "bridge"

    internal static void CaptureExternalDelegate(object source)
    {
        //Using a "bridge" instead of the direct method name
        MethodInfo mi = typeof(MyClass).GetMethod(Bridge.Method.Name, BindingFlags.Static | BindingFlags.NonPublic);

        //Less interesting code
        PropertyInfo p = source.GetType().GetProperty("SomePrivateDelegate", BindingFlags.NonPublic | BindingFlags.Instance);
        Delegate del = Delegate.CreateDelegate(p.PropertyType, mi) as Delegate;
        Delegate original = p.GetValue(source) as Delegate;
        Delegate combined = Delegate.Combine(original, del);
        p.SetValue(property, combined);
    }

    static MyClass()
    {
        Bridge += MyStaticMethod;
    }

    //This is the method whose name can not be retrieved by nameof () after applying ConfuserEx
    private static void MyStaticMethod(string value)
    {
        //I am testing the method's name after calling it.
        var st = new StackTrace();
        var sf = st.GetFrame(0);
        var currentMethodName = sf.GetMethod();
        throw new Exception("The method name is: " + currentMethodName); //You can see that the method has evoked and you can even see its new name
    }
}
person g_m    schedule 11.12.2018