posts - 4, comments - 117, trackbacks - 0, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
今天有机会继续跟踪瑞克的软件了。上次分析结果请参见

初步研究 DNGuard HVM 2007 软件

当IL进行即时编译的时候,会执行0x60008B00处代码,可能由于是试用版的缘故,代码没有做过多限制。
一路跟下来最终明白了DNGuard HVM 2007 的执行过程。具体如下:

此过程也可以作为dotNet软件保护的基本框架:

1.软件加载运行
2.安装解密代码运行环境。即HVMRuntm.dll
3.DotNet框架加载即时编译器,即mscorjit.dll
4.mscorjit.dll中通过调用 getJit() 导出函数,可以得到即时编译对象FJitCompiler的地址为 0x790AF170, 通过该地址,找到该对象的虚函数表地址,并替换第一个字节为你的解密函数地址(注意你的函数应该符合compileMethod函数的形参表),另外要保存原来的编译地址。
5.当框架需要编译函数时,会根据即时编译对象的虚函数表调用你替换的函数。
6.进行解密
7.解密完后调用原有编译对象实现的函数,这里我直接给出地址0x7906E7F4
8.即时编译器进行编译。
9.执行编译代码

大多数Jit层保护程序都是按照这种流程进行。
并且可以破解 DNGuard HVM 2007 , MaxToCode 等等软件的保护。

下面我给出一些实现源码进行说明。

typedef DWORD (*pfGetJit)();
DWORD dwCompilerObjAddr = NULL;
DWORD dwCompileMethodAddr = NULL;

class MyCompilerObject :
        public ICorJitCompiler {
public:
        virtual CorJitResult __stdcall compileMethod (
                         ICorJitInfo                                                  *comp,                           /* IN */
                         struct CORINFO_METHOD_INFO         *info,                              /* IN */
                         unsigned                                                      flags,                              /* IN */
                         BYTE                                                         **nativeEntry,                /* OUT */
                         ULONG                                                     *nativeSizeOfCode        /* OUT */
             );

       void DecodeMethod(CORINFO_METHOD_INFO *info);
       void EncodeMethod(CORINFO_METHOD_INFO *info);
              
};

// 自己实现的编译函数
CorJitResult MyCompilerObject::compileMethod (
                         ICorJitInfo                                                  *comp,                           /* IN */
                         struct CORINFO_METHOD_INFO         *info,                              /* IN */
                         unsigned                                                      flags,                              /* IN */
                         BYTE                                                         **nativeEntry,                /* OUT */
                         ULONG                                                     *nativeSizeOfCode        /* OUT */
             ) {
         // 每当框架需要编译IL代码的时候会调用这个函数
        
        // 解密函数
        DecodeMethod(info);

        // 如果在这里安装一个钩子就可以获得解密后的源代码了
        // 这里就是DNGuard HVM 2007 的缺陷
        // MaxToCode早期版本不是Jit层解密,所以也可以钩住并获取解密后的代码
        HookCompileMethod(info);

        // 调用原本的编译函数,对已经解码的IL进行编译
        (*dwCompileMethodAddr)( comp, info, flags, nativeEntry, nativeSizeOfCode );
        // 再次加密解密的函数
        EncodeMethod(info);
}

void InstallDecodeProc()
{
        HMODULE hModule = LoadLibrary(TEXT("mscorjit.dll"))
        pfGetJit pf = (pfGetJit)GetProcAddress( hModule, "getJit" );
        
         // 获取编译对象地址
        dwCompilerObjAddr = (*pf)();
        // 获取虚函数compileMethod地址
        dwCompileMethodAddr = *(((DWORD*)(*((DWORD*)dwCompilerObjAddr))));
        // 获取虚函数表
        DWORD* pVTable = (DWORD*)(*((DWORD*)dwCompilerObjAddr));
        // 设置你自己的解密编译函数地址到原有的虚函数表中
        *pVTable = &MyCompilerObject::compileMethod;
}

上面的代码会有问题并不能通过编译,但是大体流程就是这样的,不过这样做不安全,比如我们在原有编译对象实现的编译函数0x7906E7F4这个地址进行HOOK(应用程序mscorjit.dll模块,在0x7906E7F4下断点),就可以得到解密后的IL代码,按照这个方法就可以动态脱壳了,而且这并不需要编写解密函数,因为运行时HVMRuntm.dll已经帮我们解密了,这也是DNGuard HVM 2007软件的缺陷。

正如瑞克所说的话,完全可以跳过HVMRuntm.dll 的保护得到真正的IL代码,看来瑞克要重新设计设计了。

另外,看来作者真是下功夫了,竟然加了个非常强悍的壳Themida(Themida壳会产生垃圾代码,会损耗性能,可怜的DotNet代码,本身效率就不算高了外面又加了个壳),害得我搞了半天,不过还是给脱了,不易啊,不过我想瑞克应该用的是盗版的Themida,哈哈哈,在此呼吁一下“打击盗版,使用正版,我用正版我自豪”。

此外如果有机会写下一篇关于DotNet保护的文章的话,我可以以sscli 源码为例,讲解dotnet框架,运行环境的技术。



Feedback

#1楼    回复  引用  查看    

2007-08-31 18:29 by MYOOP      
!!!!

#2楼    回复  引用    

2007-08-31 18:45 by 小鬼 [未注册用户]
咱的代码从来不加保护,哈,把代码做好才是最重要的,至于别人要盗版,那就随它去吧.

#3楼    回复  引用    

2007-08-31 19:26 by Dark [未注册用户]
恩,是啊,加密最好找专门的公司来做,非专业花太多时间来做,有点浪费。。

#4楼    回复  引用  查看    

2007-09-01 13:39 by 瑞克      
这个方法只对 试用版的有效,标准版对 局部变量签名和 异常处理表做了保护,这样你只能得到IL字节码。

对于其它Jit层的加密壳,你只需要改变Hook的位置也就能,dump到IL字节码。

#5楼 [楼主]   回复  引用  查看    

2007-09-01 13:43 by Aplo      
To:瑞克

我不明白我都能得到IL字节码了,其他的保护还有什么意义?


#6楼    回复  引用  查看    

2007-09-01 13:55 by 瑞克      
对于目前的加密壳来说还没有能实现保护IL字节码的,只能得到IL字节码就无法完成脱壳过程,增加了分析的难度。局部变量签名对程序流程没有影响,应该对IL代码的分析影响较少。异常处理表会影响代码流程(如final块fault块)。

DNGuard 专业版的功能就是保护Jit层中的IL字节码,让破解者不能截获正确完整的IL字节码。

对于 DNGuard的 试用版,你目前也只是完成了被动拦截代码的功能。
你可以尝试做一个脱壳机来实现DNGuard 试用版这一类加密壳的脱壳,也许这个过程你会遇到一些问题。
如果你实现了那对你在.Net框架的认识上会有很大帮助。

#7楼 [楼主]   回复  引用  查看    

2007-09-01 14:56 by Aplo      
To:瑞克

希望有机会,我能够分析一下专业版的DNGuard,这么好的软件可否免费给我一套,哈哈哈,请勿见怪!

#8楼    回复  引用    

2007-09-01 15:10 by Richard [未注册用户]
技术才是王道,只有你不了解的技术,没有底层技术,所以大家不要被那些加密厂商忽悠啦~~~~!
那些说自己使用了Windows底层技术的话,都是骗人的!他们哪一个敢把自己的技术公布进行测试。可见他们就以自己掌握一些别人不了解技巧,忽悠别人。

再次支持搂住~~!!!希望你能把这些技术内幕都能公布出来,也让我们这种菜鸟能多学点东西~~~!

支持!!!!

#9楼    回复  引用    

2007-09-01 15:20 by 惊梦 [未注册用户]
不知道搂住能不能把本文讲的内容实现一个,提供大家使用呢?
嘻嘻嘻,如果免费就更好了。

期待好文!

#10楼 [楼主]   回复  引用  查看    

2007-09-01 15:54 by Aplo      
To:惊梦

好,有机会我也做一个保护软件,并且免费发放。哈哈哈,到时还得请你捧场啊。

#11楼    回复  引用    

2007-09-03 09:18 by 低调 [未注册用户]
好文,学习哦。

#12楼    回复  引用    

2007-09-27 16:43 by jackyped [未注册用户]
加密?不加密?这是一个问题

感觉上了微软的当,浪费n多时间在这玩意上面

#13楼    回复  引用    

2008-01-31 14:16 by 团圆节 [未注册用户]
下个啊?

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-09-07 15:42 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:

相关链接: