最强DNGuard HVM是如何加密.Net的

前言

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万多行。后面再看看。