支持C# 5.0的async语法的反编译器出来了

以前我在文章《异步函数带来的另一好处—不用混淆代码了?》里提到过:对于新的语法糖async,当前反编译器都无法还原,而async语法糖生成的函数有一定复杂度,相当于有一定的自混淆的功能。

今天看到了Telerik这个出控件的公司出了一款支持async语法糖的反编译器JustDecompile,便下载试用了一下,确实能反编译async语法,非常强大。

首先以一个最简单的异步函数为例:

    static async Task AsyncTest()
    {
        await Task.Delay(100);
        Console.WriteLine("hello world");
    }

对于这个函数,Reflector的反编译结果如下(其它不支持async的反编译器基本上也是这个结果):

    [AsyncStateMachine(typeof(<AsyncTest>d__0)), DebuggerStepThrough]
    private static Task AsyncTest()
    {
        <AsyncTest>d__0 d__;
        d__.<>t__builder = AsyncTaskMethodBuilder.Create();
        d__.<>1__state = -1;
        d__.<>t__builder.Start<<AsyncTest>d__0>(ref d__);
        return d__.<>t__builder.Task;
    }

但对于JustDecompile来说,其反编译结果如下:

    private static async Task AsyncTest()
    {
        await Task.Delay(100);
        Console.WriteLine("hello world");
    }

基本上完美的还原了async的语法糖,效果非常好。

那么,对于JustDecompile这类反编译工具,我们该如何保护自己的代码呢?还是得靠混淆,我用VisualStudio自带的混淆工具重命名了一下程序集,这次JustDecompile的反编译结果如下:

    private static async Task a()
    {
        a.a variable.b = AsyncTaskMethodBuilder.Create();
        variable.a = -1;
        AsyncTaskMethodBuilder asyncTaskMethodBuilder = variable.b;
        asyncTaskMethodBuilder.Start<a.a>(ref variable);
        Task task = variable.b.Task;
        return task;
    }

程序集重命名后JustDecompile就失去了还原async语法糖的功能,和Reflector反编译的结果基本一致。

为什么仅重命名程序集能阻止async的还原呢?原理也很简单:混淆后async语法糖产生的函数被重命名了,和C#编译器生成的规则不一样了,JustDecompile按照C#编译器的规则无法还原这个语法糖,只好输出IL码的直接反编译的效果了。

当然,反编译器也能针对混淆工具的混淆算法进行分析,从而还原混淆后的async语法糖,不过感觉这样的难度和工作量都较大,并且意义不大,应该不会去做这种事的。

你可能感兴趣的:(async)