如何保护java程序不被反编译

Java是一种 跨平台的、解释型语言 Java 源代码编译中间“字节码”存储于class文件中。Class文件是一种字节码形式的中间代码,该字节码中包括了很多源代码的信息,例如变量名、方法名 等。因此,Java中间代码的反编译就变得非常容易。目前市场上有许多免费的、商用的反编译软件,都能够生成高质量的反编译后的源代码。所以,对开发人员 来说,如何保护Java程序就变成了一个非常重要的挑战
下面我们就结合实例讨论

保护Java程序的基本方法然后对代码混淆问题进行深入研究最后结合一个实际的应用程序,分析如何在实践中保护Java程序。
反编译成为保护Java程序的最大挑战
通常C、C++等编程语言开发的程序都被编译成目标代码,这些目标代码都是本机器的二进制
执行代码。通常所有的源文件被编译、链接成一个可执行文件。在这些可执行文件中,编译器删除了程序中的变量名称、方法名称等信息,这些信息往往是由内存地
址表示,例如如果需要使用一个变量,往往是通过这个变量的地址来访问的。因此,反编译这些本地的目标代码就是非常困难的。
Java语言的出现,使得反编译变得非常容易而有效。
原因如下:
1.由于跨平台的需求,Java的指令集比较简单而通用,较容易得出程序的语义信息;2.Java编译器将每一个类编译成一个单独的文件,这也简化了反编译的工作;3.Java 的Class文件中,仍然保留所有的方法名称、变量名称,并且通过这些名称来访问变量和方法,这些符号往往带有许多语义信息。由于Java程序自身的特点,对于不经过处理的Java程序反编译的效果非常好。
目前,市场上有许多Java的反编译工具,有免费的,也有商业使用的,还有的是开放源代码的。这些工具的反编译速度和效果都非常不错。好的反编译软件,能够反编译出非常接近源代码的程序。因此,通过反编译器,黑客能够对这些程序进行更改,或者复用其中的程序。因此,如何保护Java程序不被反编译,是非常重要的一个问题。
常用的保护技术

由于Java字节码的抽象级别较高,因此它们较容易被反编译。下面介绍几种常用的方法,用于保护Java字节码不被反编译。通常,这些方法不能够绝对防止程序被反编译,而是加大反编译的难度而已,因为这些方法都有自己的使用环境和弱点。
隔离Java程序
最简单的方法就是让用户不能够访问到Java Class程序,这种方法是最根本的方法,具体实现有多种方式。例如,开发人员可以将关键的Java Class放在服务器端,客户端通过访问服务器的相关接口来获得服务,而不是直接访问Class文件。这样黑客就没有办法反编译Class文件。目前,通过接口提供服务的标准和协议也越来越多,例如 HTTP、Web Service、RPC等。但是有很多应用都不适合这种保护方式,例如对于单机运行的程序就无法隔离Java程序。这种保护方式如下图所示。如何保护java程序不被反编译对Class文件进行加密
为了防止Class文件被直接反编译,许多开发人员将一些关键的Class文件进行加密,例如对注册码、序列号管理相关的类等。在使用这些被加密的类之前,程序首先需要对这些类进行解密,而后再将这些类装载到JVM当中。这些类的解密可以由硬件完成,也可以使用软件完成。

实现时,开发人员往往通过自定义ClassLoader类来完成加密类的装载(注意由于安全性的原因,Applet不能够支持自定义的
ClassLoader)。自定义的ClassLoader首先找到加密的类,而后进行解密,最后将解密后的类装载到JVM当中。在这种保护方式中,自定
义的ClassLoader是非常关键的类。由于它本身不是被加密的,因此它可能成为黑客最先攻击的目标。如果相关的解密密钥和算法被攻克,那么被加密的类也很容易被解密。这种保护方式示意图见下图。如何保护java程序不被反编译转换成本地代码
将程序转换成本地代码也是一种防止反编译的有效方法。因为本地代码往往难以被反编译。开发人员可以选择将整个应用程序转换成本地代码,也可以选择关键模块转换。如果仅仅转换关键部分模块,Java程序在使用这些模块时,需要使用JNI技术进行调用。
当然,在使用这种技术保护Java程序的同时,牺牲了Java的跨平台特性。对于不同的平台,我们需要维护不同版本的本地代码,这将加重软件支持和维护的工作。不过对于一些关键的模块,有时这种方案往往是必要的。
为了保证这些本地代码不被修改和替代,通常需要对这些代码进行数字签名。在使用这些本地代码之前,往往需要对这些本地代码进行认证,确保这些代码没有被黑客更改。如果签名检查通过,则调用相关JNI方法。这种保护方式示见下图
代码混淆 如何保护java程序不被反编译 转换成本地代码示意图

码混淆是对Class文件进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能(语义)。但是混淆后的代码很难被反编译,即反编译后得出的代
码是非常难懂、晦涩的,因此反编译人员很难得出程序的真正语义。从理论上来说,黑客如果有足够的时间,被混淆的代码仍然可能被破解,甚至目前有些人正在研
制反混淆的工具。但是从实际情况来看,由于混淆技术的多元化发展,混淆理论的成熟,经过混淆的Java代码还是能够很好地防止反编译。下面我们会详细介绍
混淆技术,因为混淆是一种保护Java程序的重要技术。代码混淆示意图
以上几种技术都有不同的应用环境,各自都有自己的弱点,表1是相关特点的比较。
混淆技术介绍
表1 不同保护技术比较表 如何保护java程序不被反编译
到目前为止,对于Java程序的保护,混淆技术还是最基本的保护方法。Java混淆工具也非常多,包括商业的、免费的、开放源代码的。Sun
公司也提供了自己的混淆工具。它们大多都是对Class文件进行混淆处理,也有少量工具首先对源代码进行处理,然后再对Class进行处理,这样加大了混
淆处理的力度。目前,商业上比较成功的混淆工具包括JProof公司的1stBarrier系列、Eastridge公司的JShrink和
4thpass.com的SourceGuard等。主要的混淆技术按照混淆目标可以进行如下分类,它们分别为符号混淆(Lexical Obfuscation)、数据混淆(Data Obfuscation)、控制混淆(Control Obfuscation)、预防性混淆(Prevent Transformation)。

案例分析
在实践当中,保护一个大型Java程序经常需要综合使用这些方法,而不是单一使用某一种方法。这是因为每种方法都有其弱点和应用环境。综合使用这些方法使得Java程序的保护更加有效。另外,我们经常还需要使用其它的相关安全术,例如安全认证、数字签名、PKI等。
现在我们要分析的是一个Java应用程序,它是一个SCJP(Sun Certificate Java Programmer)的模拟考试软件。该应用程序带有大量的模拟题目,所有的题目都被加密后存储在文件中。由于它所带的题库是该软件的核心部分,所以关于题库的存取和访问就成为非常核心的类。一旦这些相关的类被反编译,则所有的题库将被破解。现在,我们来考虑如何保护这些题库及相关的类。
在这个例子中,我们考虑使用综合保护技术,其中包括本地代码和混淆技术。因为该软件主要发布在Windows上,因此转换成本地代码后,仅仅需要维护一个版本的本地代码。另外,混淆对Java程序也是非常有效的,适用于这种独立发布的应用系统。
在具体的方案中,我们将程序分为两个部分,一个是由本地代码编写的题库访问的模块,另外一个是由Java开发的其它模块。这样可以更高程度地保护题目管理模块不被反编译。对于Java开发的模块,我们仍然要使用混淆技术。
该方案的示意图如下:
如何保护java程序不被反编译

上一篇:如何有效的保护 JAVA 程序


下一篇:运用加密技术保护Java源代码(转)