有哪些防止反编译 Java 类库 jar 文件的办法?

软件工程师、主攻高级编程语言虚拟机的设计与实现

88 👍 / 7 💬

问题描述

最好是加密/解密方案,而不是代码混淆方案。

从我从事JVM研发的角度看,Class文件的加密最多只能拖延,而不能防止逆向工程。回答这个问题只是想帮助题主设定一个合理的期望:只要拖延效果足够大就好了,彻底防止逆向工程是做不到的。

这里说的加密是指通用的加密算法,像是Blowfish、RSA啥的。

题主说的混淆可能主要是指名字混淆,这在阻挠普通人通过名字猜测程序的意图颇有效果;而混淆还可以对别的东西做,像控制流混淆(control-flow obfuscation)在对付一般的反编译器时也颇有效果。

加密与否,Class文件最终还是得进到一个JVM实现里去执行的,而这个JVM必须能理解Class文件的内容,也就意味着必须存在某种插件将加密的Class文件解密后传给JVM(例如前面

he wei

说的做法),或者JVM自身要带有解密功能(例如前面

Moxos Yuri

说的做法)。

只要发布给用户的是Class文件,而且要求要能够在标准的JVM上可以运行,那JVM就成为了逆向工程的切入点:所有能在HotSpot VM上运行的Class文件我都能轻松把它的非加密形态导出来。

还存在另外几种方式来实现拖延逆向工程的目的:

1、把Java Class文件静态编译(“AOT编译”)为native code,然后发布程序时并不发布Class文件,而是只发布编译好的native code。例如

Excelsior JET

、GCJ之类都可以做到这点。这样对它的逆向工程的难度就变得对一般C++写的程序一样,而且还可以进一步采取手段阻挠对native code的逆向工程,例如加壳。

2、采用定制的、特殊VM指令集的JVM实现,并且相应的转换和加密Class文件。

所谓特殊的VM指令集可以是一种混淆过的JVM指令集,例如说把原本JVM指令集里的opcode的意义打乱:把iadd的opcode从原本的96变成随便一个什么别的数字,例如123;又或者例如把原本若干条opcode的语义合并成一个新的opcode,或者反过来把一个opcode的语义拆分为几个新opcode。

当然这样处理过之后的Class文件就只能在特殊的JVM上运行了。

我没留意过有没有JVM提供这种加密,不过微软对.NET CLR有提供这种定制VM的服务,可以作为参考:

Microsoft® Software Licensing and Protection (SLP) Services White Paper

其中Code Protection through SVM Technology那段。

(现在这个SLP产品由一间从微软独立出去的公司——

Inishtech

——来维护了。原本叫做“Secure Virtual Machine(SVM)”的东西现在叫做“Secure Execution Environment(SEE)”。换汤不换药,东西还是之前在微软的时候的那套。)