导读:VMP 是一种用于软件保护的软件,对软件进行加壳,加固厂商都有自己的 VMP 方案,但值得注意的是,native 层的 VMP 方案并不成熟,兼容性只是其中一个影响因素,性能更是导致该方案无法普及的重要原因之一。
文 | 吴政
网易易盾
1.前言
随着智能手机的兴起,Android 应用逐渐普及,而破解、二次打包等恶意行为在 Android 端屡见不鲜,移动应用安全越来越受到大家的重视。为了解决应用安全问题,各大加固厂商对外提供安卓加固服务,在一定程度上对抗掉一部分黑灰产行为,以保障应用开发商的权益。
但随着 xposed、magisk、frida、unidbg 等工具的普及,对抗难度日益增加,开发者近年来逐渐将重要代码转到 native 层开发,让逆向分析的难度加大。
VMP 是一种用于软件保护的软件,对软件进行加壳,通过这个软件保护的代码部分在虚拟机上执行,能最大程度保护代码不被分析和破解。当前,加固厂商都有自己的 VMP 方案。但值得注意的是,native 层的 VMP 方案并不成熟,兼容性只是其中一个影响因素,性能更是导致该方案无法普及的重要原因之一。
2.强度分析
从保护强度的角度来看,native+VMP 是目前最强的代码保护策略。然而,目前商用的 native 层 VMP,几乎都是基于 llvm 实现 ir VMP,且针对源码,无法直接作用于 SO。而让外部相对熟悉的二进制 VMP 保护方案是 Windows 平台的 VMProtect。网络上更有不少针对 VMPortect 的分析文章,甚至有一些低版本的脱壳教程,但因为加壳软件的定期更新,低版本“脱壳”黑产工具的可用性几乎为零,加壳的强度得到保证,让大量逆向工程失效。
3.性能分析
从性能的角度看,dex VMP 对性能的损耗在十几倍左右,而 ir VMP 要比 dex VMP 性能损耗高达几十倍。而这些损耗都是在自定义解释器在解析执行虚拟机代码造成的。如直接对汇编指令虚拟化,性能损耗可达成百上千倍。
下面是基于已知的加固方案进行的测试,且针对特定的代码逻辑构造的性能测试对比数据。
可以看出基于汇编的 VMP 方案,因每条指令都需要进行解析执行,性能损耗极高。但因测试代码本身的构造方式具有特殊性,构造了将近 10 亿次循环,并在循环内做运算和函数的调用。因此此类几乎属于极端情况。
如果受保护的代码只执行一次,即使增量上百倍,总增量只是增加一个固定值。如果保护代码是在循环体中执行,那执行时间将成倍增加。由此可知,无论选取哪一种保护方案,都不建议保护高频调用的函数。
4.方案优化
上述方法在强度和兼容性上难以两全,带来一定损失。有人要问,是否有一种方法既可提高保护强度,又能兼顾效率呢?
答案是有的。从另一个角度来讲,VMP 是一种高强度的混淆,只不过混淆规则是指令格式,最终均需要执行指令的语义,保证程序的正确运行。VMP 本身遵循一种规律执行代码,但从代码保护的角度,只使用一种高强度保护策略,其本身不如多种随机化的保护方案来得有效。即使 VMP 做得很强,如果一成不变,最终还是有被修复的可能,只是时间成本不同。.
易盾在研究二进制加固的过程中,提出一种指令混淆的方案,结合 VMP,最大程度的保护代码强度,同时兼顾代码的运行效率。
当然,混淆之后的代码也降低了代码的易读性,建议接入该功能的开发者,对保护的函数做好充分的单元测试,避免因自身代码崩溃导致无法正常排查。同时,单元测试也可以更好地验证加固后代码执行的正确性。
5.保护效果对比
只做 SO 加固,能对抗静态分析,动态 dump 出来的 SO,即使有缺陷,还是可以分析指令。
混淆后,从被保护的函数可见代码已被抽空加密,且跳转地址处的指令被混淆,能够分析指令执行流程,在没有获取和还原所有混淆代码前,无法知道原函数真实的调用逻辑。
VMP 后,被保护的函数可以看出代码已被抽空,跳转地址是虚拟机逻辑,除非破解虚拟机逻辑,否则函数逻辑无法还原。
易盾 native 层代码保护基于无源码方案进行实现,客户只需要提供需要保护的函数列表就能直接对函数进行保护。另外,如果 SO 是 release 版本,可以提供编译过程中生成的带符号版本的 SO,方便定位受保护的函数范围。功能选择可以遵循以下两大原则:
○ 重要函数可进行 VMP 或混淆。
○ 高频调用函数尽可能使用混淆。
因保护方式基于指令,理论上 SO VMP 的混淆和 VMP 不仅仅适用于 Android,只要架构相同,对应的 linux 环境下的可执行文件和 SO 文件都可以使用该加固方案进行保护。
最后,没有绝对的安全,任何应用软件都有被破解的风险,但可以肯定的是,加壳以后肯定比不加壳要更安全,软件加壳后破解难度会增加。如果应用软件发布到市场上,那些想从你应用上获取漏洞点的黑灰产们,肯定要分析应用的代码,进行包括内购破解,加广告在内的恶意行为,损害用户使用体验的同时,致使开发商遭受商业损失。此外,开发者有核心的算法不想被友商分析,这个时候代码保护就比较重要,当然代码保护手段很多,加壳是其中一项。Android 系统和 PC 端的攻防是动态的对抗,技术一直在进步,易盾也将持续跟进。