一、ConfuserEx惹的祸
最近在试用ConfuserEx2的功能,当选择了packer功能时(如下图),加密后的文件无法运行。
二、分析了一下原因
于是,浏览了一下ConfuserEx的相关文档和源码,同时借助dnspy,弄明白了packer的基本过程:ConfuserEx会将要加密的目标文件进行加密压缩后,放入到一个数组中,并在套上一个壳(重新生成一个Main入口函数)。加密后的应用程运行时,将数组中的数据解密、解压,并用反射方式(用Assembly)将被加密的程序加载到内存中,然后执行被加密程序的入口函数(Main)。其实,ConfuserEx加壳时有两个Main函数可选择。这里主要看一下,其中的非歉容模式(compat)的Main函数。(另一种模式的Main函数中的流程是大同小异的)
如下图
正常情况下,到第5步是,被加密程序就运行起来了,但是我的测试程序无法运行。
三、探索过程 :
决定自己写一个demo,从内存中加载.net程序的。后来用dnspy调试,并查询了些资料,经过一段时间折腾。找到一个很有价值的资料
How to use and debug assembly unloadability in .NET - .NET | Microsoft Learn
从这里能看到一个重要信息:.net core 与.net framework 动态加载程序是有一些差异的地方,也有一些相同的地方。而我的测试程是在net core 3.1的。现在想来,ConfuserEx加密后不运行, 应该是和net core 有关。
四、小试牛刀
参考上面链接写了一个与文章中近乎一模一样的Demo,很顺利运行成功了。于是乎,我以为成功了。按照这种方式,将开始用ConfuserEx加密的那个测试程序加载起来。结果,一瓢冷水泼来,收到一个异常,无法加载“MainWindow.xaml”文件。
五、再次使用搜索大法 :
找到了第二个有价值的资料
.net - Load WPF application from the memory - Stack Overflow
在这里提到了不能加载“MainWindow.xaml”的情况,并在回答中提到了两种方案。第一种是“Load the exe in the separate AppDomain.”但是net core的进程中只能存在一个AppDomain,也只能有一个Application。所以这种方法应该是行不通的。第二种是:“Use reflection trickery to change default ResourceAssembly”,即用反射的方式,更换程序集的资源。采取第二种方式后,最终的Demo新鲜出炉。源码可以看github:GitHub - zhouw123/DynamicallyLoadDemo: In netcoe3.1, dynamically load the wpf window program from memory
下一步,将ConfuserEx源码改写一下,加入对.netcore 的这种方式加载。
有问题的地方,欢迎拍砖!