.NetJIT的骚操作DNGuardHVM原理简析

前言

DNGuard HVM的牛掰之处在于,就算知道了它的原理,但是你依然无法很优雅的去破解它。本篇来看下。友情提示,看本篇前,可先预热下前一篇:DNGuard HVM是如何加密.Net的

创新互联建站拥有十载的建站服务经验,在此期间,我们发现较多的客户在挑选建站服务商前都非常的犹豫。主要问题集中:在无法预知自己的网站呈现的效果是什么样的?也无法判断选择的服务商设计出来的网页效果自己是否会满意?创新互联建站业务涵盖了互联网平台网站建设、移动平台网站制作、网络推广、定制网站设计等服务。创新互联建站网站开发公司本着不拘一格的网站视觉设计和网站开发技术相结合,为企业做网站提供成熟的网站设计方案。

概括

1.MSIL保存

DNGuard HVM类库模式编译第一步就是把MSIL的原字节码(你需要加密的托管DLL)二进制代码保存在HVMRun64.dll里面以汇编的形式呈现。注意这里保存的是原字节码二进制代码,而不是保存字节码编译之后的汇编代码。如果是保存的MSIL编译后的汇编代码,可以通过逆向汇编。但保存的字节码的二进制代码还需要通过CLR+JIT编译成机器码之后进行即时运行,RunHVM函数随时可以Hook JIT或者CLR的某个地方或者几个地方,对它进行篡改。逆向的难度呈几何指数的增加。这里的MSIL的二进制代码可以参考文章:罕见的技术:MSIL的机器码简析举个例子以下C#代码:

static void Main(string[] args)
{
  Console.ReadLine();
  Console.WriteLine("Call Main");
}

它的MSIL二进制代码是:

00 28 0e 00 00 0a 26 72 01 00 00 70 28 0f 00 00 0a 00 2a 00 af 93 65 6c 00 13 00 80 00 00 00 00 00 00 00 00  //后面省略

这种二进制代码,DNGuard会把它保存在HVMRun64.dll里面。

2.MSIL加密

当它保存好了原MSIL之后,就着手加密托管的DLL里面的MSIL,把它变成了

Dnspy/ILSpy/Dotpeek这种工具无法修改的MSIL。比如以上C#代码被加密成了如下:

[NullableContext(1)]
[MethodImpl(MethodImplOptions.NoInlining)]
private static void Main(string[] args)
{
    throw new Exception("Error, DNGuard Runtime library not loaded!");
}

实际上就算是没有加密MSIL,因为它是hook jit,也无法通过修改MSIL来变更源码。

3.hook JIT

当运行被DNGuard修改的托管DLL的时候,RunHVM函数就会调用HVMRun64.dll里面的代码hook即时.Net编译器JIT里面的invokeCompileMethod函数,因为JIT会按照预定的顺序编译MSIL,而原有的MSIL被保存到了HVMRun64.dll里面去。被JIT执行的托管DLL里的MSIL则是被DNGuard加密过的是个错误的数据或者一堆乱数据。它hook这个函数的目的就是修改这个函数的参数里面保存的被DNGuard修改过了的MSIL二进制代码的起始地址,它把这个起始地址Hook成上面第一步存放的MSIL二进制代码的起始地址。此后JIT就会用Hook出来的地址,逐个编译里面的MSIL二进制代码,把它编译成机器码,然后运行。这样就完成了完整的整个执行。以下是HVMRun64.dll对托管主函数Main进行Hook调用地址的顺序,按照堆栈顺序从下往调用。

0000000180497AB8 4C 89 5F 10          mov         qword ptr [rdi+10h],r11
00000001804839DF FF 1A                call        fword ptr [rdx]
0000000180015759 E8 A2 61 FF FF       call        000000018000B900
0000000180040918 E8 43 4B FD FF       call        0000000180015460

这四个地址里面的地址:00000001804839DF进行了四字节位移运行。这种加固静态逆向的难度。

4.难点

这个过程的难点在于,DNGuard是以何种方式把原MSIL保存到HVMRun64.dll,然后又通过何种方式取出来。MSIL的二进制代码存放在HVMRun64.dll的哪个地方?只要找到了存储的位置,即可轻松破解DNGuard的加密。难点一:逆向调试DNGuard的时候,发现HVMRun64.dll里面的数据无法调试,只要下了断点或者调试器进去就会导致数据更改,更改后的数据要么是空的那么就全是0xCCCC这种东西,然后报异常。下断点导致数据更改,这跟.Net7里面的内存映射有点相似,这点还待研究。难点二:DNGuard在Hook JIT的时候,它会进行字节位移。比如本来的地址如下:

00000001804839DB: E8 1C F9 DD FF   call   00000001802632FC
00000001804839E0: 1A E8            sbb    ch,al

00000001804839DB这个地址看着没问题,但是实际上它是个伪装地址,在运行的过程中,会把这个地址加上4字节,也就是到了地址00000001804839DF这个地址,然后再运行。这样导致了机器码也跟着改变,静态逆向完全无法展开,而动态逆向则坑爹的一笔,最新的DNGuard近5M大小,里面的汇编代码高达153万多行。基本上属于无法逆向的存在。

5.破除按照以上原理认知,以下是个人认为 可行的理论上的破解之法

如下代码:

0000000180497AB8 4C 89 5F 10   mov   qword ptr [rdi+10h],r11

r11里面就是存储是HVMRun64.dll里面的MSIL二进制代码,rdi寄存器是JIT函数invokeCompileMethod参数methodInfo的地址,加上0x10为methodInfo.ILCode也即是混淆的MSIL二进制代码的起始地址,把从HVMRun64.dll里面取出来的MSIL二进制代码起始地址替换掉这个被混淆的MSIL二进制代码的地址,然后运行完整流程。

破一:根据RunHVM函数的原理,它hook JIT的函数,这里就hook这个JIT函数后面的一个函数,照样获取ILCode,修改后返回运行。这里是照猫画虎,RunHVM怎么玩JIT,这里就怎么玩RunHVM。

破二:这里还有个破绽,因为0000000180497AB8这个地址则写死在了HVMRun64.dll里面,再者[rdi+10h]这个地址是否能够替换成别的地址,获取MSIL的二进制起始地址,进行修改然后,也是可以从这里入手的。

可以看到即使知道了RunHVM原理,要想破除它依然有一定的难度。真正的实现可能比较不优雅的方式。

注:以上用于学习用途,其它用途均跟本人完全无关。

网站标题:.NetJIT的骚操作DNGuardHVM原理简析
本文地址:http://www.gawzjz.com/qtweb/news21/180171.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联