提高反编译难度的几种方式:

对于软件安全来说,有攻就要有防才对。不然,Android整个产业链就会被这样的Crack给毁掉。

第一种办法:将核心代码用JNI写进so库中。由于so库的反编译和破解的难度加大,所以这种方式防止反编译效果不错。关键代码使用jni调用本地代码,用c或c++编写,相对于class文件,so相对比较难于反编译。缺点是,对于Java层的代码没有保护作用,同样可以被篡改。很多搞java的程序员不太熟悉如何写c或c++代码,同时本地代码很难调试。出错容易导致整个虚拟机死掉,用户感受不好。


第二种办法:在线签名比较。在程序初始化时,联网将运行的程序的签名与服务器上的官方标准签名进行比较,从而达到让反编译后的程序无法正常运行的效果。缺点是,如果此部分联网检验的代码被篡改跳过,则整套机制失效。

第三种办法:代码混淆。为了加大反编译后代码分析的难度,对代码进行混淆。混淆是不改变代码逻辑的情况下,增加无用代码,或者重命名,使反编译后的源代码难于看懂。缺点是,治标不治本,同样可以修改(甚至据说还有反混淆工具,没用过,不多做评论)。

这三种办法都有各自的缺点,所以单单靠某一项要实现完美的软件保护都是不可能的。不过,我们可以采用联合几种办法的方式,来增强软件保护的力度。曾经反编译过Android版的卡巴斯基,它的保护思路似乎是这样的:

代码混淆,那是必须的,不过不指望它能有很好的效果。在程序初始化时,就直接通过JNI的so库初始化程序。程序激活部分也是通过JNI联网下载文件,然后在JNI层读文件并做相应激活与否的判断的。

卡巴斯基是将大部分功能模块都放在JNI层来实现的,如果我们的程序都这样处理,耗费的精力必然很大。所以,我们只是借鉴它的思路而已。具体操作思路如下:

代码混淆。

初始化时JNI层联网验证签名。

验证失败则直接在JNI层退出程序。

值得注意的是需要保证如果绕过JNI层的初始化,则程序无法正常启动。这点不保证的话,破解还是很容易……