中文站

VMP加固的原理及如何实现?

本文主要介绍VMP加固的原理和具体实现方法。

VMP加固的核心原理是基于 Dalvik 的解释器实现自己定义的指令。

比如 要对 MainActivity onCreate 进行 VMP 加壳保护, 从实现过程讲要解决两个关键问题:

1. 让系统执行 onCreate 时,进入到加固壳代码执行;

2. 壳代码得到运行时机后,如何解释原来的 onCreate。

对于问题1, 各家的实现也是不一样的,比如有厂商把 onCreate 变为 native 函数,在壳SO中动态注册 onCreate ,或者生成 Java_xxx_onCreate 形式的 native 函数:


有厂商更改 onCreate 的方法体:


无论是哪种方式,都是为了当系统执行到 onCreate 时,壳代码可以替代系统执行 onCreate 指令。

对于问题2, 在 Dex 文件中对于每一个函数,都会有一个 CodeItem 字段,里面保存了这个函数的各种信息,其中就包括函数的指令。在加固时,会将这些指令抽取出来保存,并且删除 Dex 中的指令。当然在保存指令之前,各家厂商会对指令做一些变换,以适应自己的虚拟机。

当壳代码需要执行 onCreate 时,会从之前保存的指令中取出属于 onCreate 的指令,解析出指令的 opcode / operand ,通过一个巨大的 switch case (如下图)找到处理对应 opcode 的函数,然后执行。

这个执行的过程一般都是模防 Dalvik 虚拟机。稍微具体一点,对于一般的逻辑运算指令,如加、减、乘、除等,可以直接执行;对于像 invoke-direct / invoke-virtual / iget 等需要与系统交互的指令,就需要调用 JNI 接口来实现, 这也是 VMP 可能存在效率问题的原因之一。 

相关阅读:

如何防止Unity手游代码被反编译?

怎么做Android代码混淆?

为什么说SO加固+无源码VMP是最佳的Android手游安全保护方案?