本文仅限于技术讨论,不得用于非法途径,后果自负。这是萌新第一次逆向vmp,主要是分享分析过程,这里借鉴了金罡大佬的文章https://bbs.kanxue.com/thread-282300.htm,vmp的内存布局和context 在我选用的这个版本差别并不大。选用的TT 中libEncryptor.so 中被vm 的jnionload。用ida打开so 定位到AF8 ,看一下cfg
下面这一排就是handle的实现了
不过handle太多了 我只会还原被执行的指令集。从下面两张图可以看出vm指令集4字节对齐和arm一致 ,在后面的逆向中发现开发者并没有实现指令集或者说指令集就是arm64
还原指令的第一步就是解析出指令中携带的信息,一般来说,有这几个信息
1.指令类型
2.寄存器信息
3.立即数
可以看到在虚拟机循环的开头就是虚拟机取出指令各个信息的过程
可以看到 指令类型 sourceREG destREG opcode 这几个关键的信息可以理解为虚拟机使用的寄存器 堆栈 等信息
这里可以参考金罡大佬的文章https://bbs.kanxue.com/thread-282300.htm 这个版本没什么变化,唯一注意的是我并不是通过汇编而是f5代码来确定coutext的结构的,而开发者为了对抗,这个context结构体是负指针寻址的 所以需要自己patch代码
比如 STP X3, X20, [X19,#-0x100]=>STP X3, X20, [X19,#0x100]
这个方法中只需要patch 所有有关x19的指针操作即可
效果图
这个可能是最头疼的一点,明明开发者写的就是一个while switch 可是被编译器优化后代码复用,各种跳转比如
可能你找handle的时间都比逆向handle的时间长
这里,我使用了一个实验性质的方法
利用trace在剔除控制流指令后重新patch
效果图
可以看到 所有handle都被打印出来了
指令缩短 变成单次打印单个handle
这样我觉得是提高了我的分析效率这个是我觉得最繁琐的地方,我看了我还原出来的指令和金罡大佬的还原,还是细节不够
对比可以看到mov少了个z,这就是细节不够,另外还有对arm指令集不够熟悉一些偏门指令如果不知道那就完犊子了 这是我还原最后一个handle看出来的 原先我以为是cmp 但是不对劲,简而言之就是每一次call 后会检查返回值 如果返回值对 vm_pc+2 结合br指令集 lr = pc+2 刚好四字节对齐,如果不对 哦吼 pc +2 指令集对齐直接挂 随机崩溃
br handle
// unsigned int code
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-284883.htm