前几天发现有个坛友跟风发了一个通达信64位的脱壳笔记,然后竟然让它篇了一篇精华,我来论坛这么久了都没混到一篇。心里很是不平和嫉妒。
心默念了好多遍都是浮云才将波澜的心绪抹平,奈何有个 强迫症坛友 @快速登录 让我也一步步的写一下,这下可没有理由阻止我篇精华的脚步了。搞起~
按照帖子:
https://www.55188.com/thread-21673078-1-1.html
中介绍的步骤,将工具搞齐,然后下载64位通达信,源地址已经不能用了,新版本的64位下载地址为: https://data.tdx.com.cn/test/new_tdx_test0816.exe
下载安装后,确定能正常运行,然后就开始我们的脱壳之旅。在正式开始之前,我们先整理一下我们的脱壳思路,一般来说,软件的脱壳分成如下几步:
1. 看程序是否有检测,pass掉壳的保护,确保程序能正常调试。
2. 查找程序原始的入口点 也就是找OEP。
3. 将程序从内存中dump出来,然后开始对程序的PE头进行各种修复,比如 修复程序的导入表,导出表,资源表等等。
然后,也有一些壳的加密级别比较高,dump出来之后再修复就会比较困难,所以一些大神会公开一些脱壳辅助程序或者脚本,让我们在dump之前,找到合适的时机进行修复,修复完之后再dump可以降低数据解密的难度。
不过值得庆幸的是,由于通达信的`交易模块`中存在 `MalwareScout[332.3.X].dll` 和 `NodeGuardC.dll` 两个检测组件,这两个检测组件不仅检测电脑的运行环境,HOOK信息,还把 TdxW.Exe、Tc.dll 等程序的 代码段、资源段(主要是图标资源),IAT表 等信息也会提取出来加密作为校验的样本。这就使得 通达信的程序,虽然是使用了令人闻风丧胆的VMP3的壳来保护自己,但是保护强度也只是个银样镴枪头,整个脱壳的工作也就简单的很多,现记录如下:
1. 过掉VMP的反调试保护
这个不用多说,上面引用的帖子中有讲如何配置对应的调试器和插件,为了节省篇幅,略过。
2. 找到程序的OEP
所有程序找OEP的思路是差不多的,一个带壳程序的运行,总得先运行壳代码,等壳代码加载好,被保护的原始代码被解密完之后,壳代码总得将程序的运行权限交给原始程序,让程序正常启动起来的。
有了这个思路,找OEP的方法就有很多了,由于上面我说的交易模块中检测组件的原因,通达信的保护强度不高,我们可以直接再数据段或者资源段下写入断点,确保原始程序的资源都释放的差不多了,再在代码段下访问或者执行断点,就可以直接到达OEP附近。
这个64位的通达信启动之后有个警告弹窗,这样让我们找OEP就更容易了。
用调试器加载64位的通达信,直接运行起来,来到如下截图的位置:
这样,我们直接在调试器中暂停程序的运行,然后查看调用堆栈,如下图:
按照图片中的文字操作,来到下图的位置:
向上翻动鼠标滚轮,查看当前函数的函数头,如下图:
至此,我们就找到OEP了,可以在OEP的位置下断点,我比较推荐硬件断点,在一定程度上可以防止检测:
断点下完之后,重新载入程序,直接运行,此时程序就断在OEP的位置了,如下图:
当然,如果你嫌每次脱壳都要像上面这样定位一遍OEP,太麻烦,我们可以选一段代码作为特征码:
- 0000000140763682 | 6548:8B0425 30000000 | mov rax, qword ptr gs:[0x30] | 特征码开始
- 000000014076368B | 48:8B58 08 | mov rbx, qword ptr ds:[rax + 0x8] |
- 000000014076368F | 33FF | xor edi, edi |
- 0000000140763691 | 33C0 | xor eax, eax | 特征码结束
`65 48 8B 04 25 30 00 00 00 48 8B 58 08 33 FF 33 C0`
这样,以后我们可以通过这个特征码,直接定位到 OEP的周围,当然也不排除以后软件更新,特征码失效的问题,为了避免失效,我们可以多留几个特征码。
当然,我们一定要清楚,这个特征码只是让我们少折腾的手段,并不是我们折腾的主要目标。 @和合66
3. dump并修复程序。
用Scylla选中 TdxW.exe 的进程,填入OEP地址,开始自动搜索IAT,如下图:
我嘞个去,导入了四万八千多个API?还有四万六千多个无效的API?这很明显自动搜索的出问题了。一般情况下,我们直接清理掉无效的即可,为了防止是VMP壳捣乱破快了IAT表,我们需要确认一下正常的IAT大小。
我们再回到调试器中,来到OEP的所在位置,随便找一个系统API的调用,如下图:
然后,在 内存窗格中向上找到所有API的开头位置,然后跟 Scylla 找到的IAT表进行对比,如下图:
由此,我们可以确定,Scylla找的IAT表头是没问题的,我们向下定位一下IAT的结尾:
由此,我们知道,我们的IAT大小 = 1407C9B70 - 1407C6000 = 3B70。由此我们重新启动 Scylla 填写OEP 不要使用IAT的自动搜索功能,填写上IAT和VA地址和 Size数据,然后直接点击 Get Imports 按钮,如下图:
至此,IAT的定位环节已经搞定了,点击 Scylla 右侧的 dump将程序从内存中打包成文件镜像,然后点击 Fix Dump按钮,修复刚dump出来程序的IAT表。
此时,我们脱壳的程序已经可以正常运行了。
4. 优化程序大小
尽管我们脱壳的程序能正常运行了,但是壳的代码仍然还在我们的程序中。我们上面做的工作,只是让程序启动的时候,绕过壳代码,直接从原始程序的入口点直接运行。但是壳的代码仍然在程序中,这样我们的程序就会比较大,比如我刚dump出来的程序,就比较大:
接下来,我们要做的工作,就是将壳的代码剥离掉,减少程序的体积.
我们找一个PE编辑器,如: `CFF Explorer`, 用它打开 tdxw.exe 查看一下数据目录,如下图:
再打开我们刚 脱壳的程序,如下图:
我们可以看到,Import Directory的数据原本是再 .VMP1 区段中的,经过我们用 Scylla 的修复,已经将它移动到了新的区段(我在 Scylla中自定义了区段名称,你们的应该叫 SCY之类的名字),而其它的比如 Export Directory, Exception Directory 之类的数据 还继续存放在 .vmp0 和 .vmp1目录中。
我们要做的就是将这些数据从 .vmpX 区段中转移到我们自己的区段中,这样 .vmpX 这些区段就可以删除了。
我们我们多少了解一些PE文件头的知识,我们可以知道, 我们脱壳的是EXE程序,只有DLL程序才存在 Export Directory、 Relocation Directory之类的数据。而 导入表我们已经将它移动到了 DTCHN 区段,这时,我们可以直接删除 .VMP0区段,只需要单独处理一下 .VMP1 区段的数据即可。
累了,先写到这里,休息,先休息一下,等吃完晚饭,我们继续。