前言
Dnguard是通过Hook JIT编译器,跳转到HVMRun64.dll里面的RunHVM函数,通过还原IL代码来对IL代码进行重新编辑,然后导入到JIT进行正规化的编译。这样就可以避免一些中低端的破解,本篇来看下这个过程.
概括
1.举例
比如以下代码:
static void Main(string[] args){Console.ReadLine();Console.WriteLine("Call Main");}
经过Dnguard加密之后他变成了
[NullableContext(1)][MethodImpl(MethodImplOptions.NoInlining)]private static void Main(string[] args){throw new Exception("Error, DNGuard Runtime library not loaded!");}
它变成了这种代码之后,无法通过修改MSIL这种简单的方法来破解或者篡改程序集了,从而修改结果。
2.加密
经过Dnguard加密的.Net DLL里面生成了高达几十个方法,这些方法对于混淆托管DLL以及JIT的编译流程起了作用。它自己生成了另外两个非托管DLL(实质部分方法也被托管调用)HVMRun64.dll和HVMRuntm.dll,前者用于64位,后者32位。其中有几个比较重要的函数分别为:
<Module>虚拟模块的cotr
ZXYDNGuarder模块的Startup
ZXYDNGuarder模块的CheckRuntime64
ZXYDNGuarder模块的RunHVM
.ctor里面调用虚拟机修改程序的入口Startup运行,然后里面调用CheckRuntime64运行RunHVM函数hook JIT。
其中RunHVM把.Net JIT的compileMethod函数修改为HVMRun64.dll里面不知名的函数进行MSIL还原,也就是把加密的MSIL还原成正确的MSIL。
Dnguard保护程序入口的代码逆向如下:
void Startup(){bool ZYXDNGuarder.a;if(a!=0){return;}try{bool l=ZYXDNGuarder.RunHVM();bool ZYXDNGuarder.a;}catch(Exception ex){try{int A=ZYXDNGuarder.a;int B= System.IntPtr.get_Size();if(a<=b){ZYXDNGuarder.CheckRuntime64();try{ZYXDNGuarder.$MD$F();ZYXDNGuarder.a;}catch{string str="*=Load DNGuard Runtime library failed, runtime lib";System.Exception ex =new System.Exception();throw;}}catch{}}}
它主要的Hook JIT代码是在RunHVM函数里面,这个函数在HVMRun64.dll里面,而这个DLL是个汇编非托管,行数高达153万多行。后面再看看。