首页
壁纸
直播
Search
1
欢迎来到本站
12 阅读
2
.Net JIT二进制骚操DHVM破解篇
2 阅读
3
EXCEL表格中的数字,为什么每次打开会自动变成日期?
1 阅读
4
容易读错的字
1 阅读
默认分类
电脑技术
登录
Search
i-kan
累计撰写
4
篇文章
累计收到
1
条评论
首页
栏目
默认分类
电脑技术
页面
壁纸
直播
搜索到
1
篇与
的结果
2024-10-09
.Net JIT二进制骚操DHVM破解篇
前言经研究,号称最强.Net加密软件DNGuard HVM(以下简称DHVM),五行代码基本上可以优雅的破解它,本篇看下。友情提示,以下全是二进制汇编骚操,慎入。概括示例:非常简单的示例 static void ABC() { Console.WriteLine("Call ABC"); } static void DEF() { Console.WriteLine("Call DEF"); } static void Main(string[] args) { Console.WriteLine("Call Main"); ABC(); DEF(); Console.ReadLine(); }修改调用ABC函数的逻辑为调用DEF函数,Main函数的MSIL二进制代码如下: 00 72 25 00 00 70 28 0e 00 00 0a 00 28 06 00 00 06 00 28 07 00 00 06 00 28 0f 00 00 0a 26 2a这里的MSIL二进制代码可以参考:罕见的技术:MSIL的机器码简析1.难点因为Hook JIT,简单的MSIL修改已经不起作用。DHVM的各种反调试,比如VS调试器无法进入某些内存地址。一进入就会报异常。它静态地址在运行的时候动态偏移,它进行了PE的IAT(导入表)的Name字段验证,当IAT的Name不为0的时候,就会报异常等。这些东西叠加在一起,无法调试,无法通过输入表注入DLL等。2.蛛丝马迹避开这些反调试手段,魔高一尺道高一丈嘛,蛛丝马迹即是破绽。当我们通过一些可以调试的地址进入发现一些有趣的东西,比如以下代码: 0000000180497AB2: E9 A1 73 00 00 jmp 0000000180497AB8 0000000180497AB7: F8 clc 0000000180497AB8: 4C 89 5F 10 mov qword ptr [rdi+10h],r11这一段汇编代码是关键点,它通过jmp指令跳到地址0000000180497AB8。然后执行指令 mov qword ptr [rdi+10h],r11这里的r11寄存器保存的是通过DHVM加密后的托管DLL的真实的MSIL二进制代码。rdi寄存器是DHVM Hook的JIT的函数invokeCompileMethod的参数methodInfo地址,rdi+0x10即是methodInfo的成员变量IL_Code地址。这个IL_Code里面的值会被JIT编译器编译成机器码,然后运行。那么这段指令的意思很明显,也就是说把DHVM加密后把保存的托管DLL的真实MSIL二进制代码赋值给IL_Code。它这么做的目的就是屏蔽掉原有托管DLL里面的MSIL,而用DHVM自己加密之后保存的MSIL。无论你怎么修改原有的托管DLL,都不会影响JIT的执行。3.预破既然探查到了以上蛛丝马迹,下面着手解决掉DHVM。这里的思路是,因为jmp是个跳转指令,所以可以让它跳转到自己的地址。这个自己的地址因为无法通过IAT注入DLL构建,上面说了DHVM会搜寻IAT的Name字段是否为0。因为Win11超强的PatchGuard,所以这里不考虑DLL注入了。直接在HVMRun64.dll内部构建。通过dumpbin,把HVMRun64.dll的汇编代码导出到记事本。HVMRun64.dll的最后的汇编地址如下: 000000018049EE53: 00 74 56 01 add byte ptr [rsi+rdx*2+1],dh 000000018049EE57: 00它这个地址对应的是把HVMRun64二进制的地址如下: 00499253:00 74 56 01 00从00499258地址开始后面全都是0,类似如下: 00499258:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00可以从这里为零的数据开始构建。在构建数据之前还需要做一件事情,我们上面蛛丝马迹里面jmp指令 0000000180497AB2: E9 A1 01 00 00 jmp 0000000180497AB8需要让它跳转到00499258这个地址来,然后在这个为零地址里面做自己想要做的事情。如何跳转呢?可以把jmp地址改成如下: //jmp跳转地址减去jmp所在地址减去5等E9后面的数值,E9是jmp机器码 0000000180497AB2: E9 A1 73 00 00 jmp 000000018049EE58这里的000000018049EE58地址指向的即是00499258所在全部是零的地址处。当它跳转到0区之后如下代码:首先在00499258地址处写入二进制代码:4D 89 DF,这三个十六进制代表的汇编是mov r15,r11,上面说了r11保存的是MSIL需要编译的二进制代码,通过跟踪发现如果直接更改r11寄存器,则会导致异常。跟踪也发现r15寄存器为零,所以这里把r11赋值给r15。然后把蛛丝马迹里面的代码 0000000180497AB8: 4C 89 5F 10 mov qword ptr [rdi+10h],r11也就是这里的r11替换成r15,让它称为最后编译的MSIL我们需要做的就是在r15里面修改MSIL二进制即可。如何把r11替换成r15呢?看它的代码: 0000000180497AB8: 4C 89 5F 10 mov qword ptr [rdi+10h],r11修改成如下: 0000000180497AB8 4C 89 7F 10 mov qword ptr [rdi+10h],r15 把机器码5F改成7F即可。以上所有准备好了,我们开始替换MSIL代码,也即是r15寄存器修改。4.破解上面把十六进制的4D 89 DF写入了00499258地址,也即是000000018049EE58所指向的地址。因为4D89DF占3个字节,所以下面的地址 0x000000018049EE58+0x3==000000018049EE5B.000000018049EE5B这个地址写入如下: 0049925B:49 C6 47 0D 07转换成汇编也即是如下: 000000018049EE5B 49 C6 47 0D 07 mov ptr byte [r15+D],07这里是把07这个数值赋值给r15偏移的0xD的位置处。这里修改r15偏移的0xD位置的数值,实际上是把示例里面的调用的ABC函数修改成调用DEF函数,也就是改变函数逻辑。示例的结果是: Call Main Call ABC Call DEF我们通过hook DHVM之后的结果是 Call Main Call DEF Call DEF示例里面的MSIL二进制代码是: 00 72 25 00 00 70 28 0e 00 00 0a 00 28 06 00 00 06 00 28 07 00 00 06调用ABC函数的MSIL二进制代码是: 28 06 00 00 06调用DEF函数的二进制代码是: 28 07 00 00 06可以看到ABC和DEF函数的MSIL二进制代码,只是基本上相同,上面偏移的0x1的位置一个是06,一个是07。如果想要把调用ABC改成调用DEF,这里只需要把06改成07即可,也就是这段汇编代码的意义 ` ` 000000018049EE5B 49 C6 47 0D 07 mov ptr byte [r15+D],07这里改了之后,还得跳回去,因为上面的汇编占了五个字节,所以这里下一个地址是: 0x000000018049EE5B+0x5==0x000000018049EE60在地址0x000000018049EE60里面跳转到原来的jmp需要跳转的地址也即是 00499260:E9 53 8C FF FF 000000018049EE60 E9 53 8C FF FF jmp 0000000180497AB8这样就完成了整个闭环的操作,在Hook DHVM里面这里只是简单的修改了一个字节数值,当然可以修改更多以满足自己的需求。本篇用的是:.Net JIT的骚操作DNGuard HVM原理简析。里面提到的第二种方法也即是破二。第一种方法也可,而且能够做的更多。但是规模和成本上去了。个人比较喜欢简洁,所以选择了第二种。5.整体那么整体的代码是:DHVM跳转代码和r11替换成r15 0000000180497AB2: E9 A1 73 00 00 jmp 000000018049EE58 0000000180497AB8 4C 89 7F 10 mov qword ptr [rdi+10h],r15hook代码: 000000018049EE58 4D 89 DF mov r15,r11 000000018049EE5B 49 C6 47 0D 07 mov ptr byte [r15+D],07 000000018049EE60 E9 53 8C FF FF jmp 0000000180497AB8可以看到,真正的代码,也就那么几行,甚至也就是修改一个字节。所谓返璞归真,即是这个道理。以上DHVM的整体过程,仅用于学习用途。
2024年10月09日
2 阅读
0 评论
0 点赞