焦 涌 赖 娜
Java防反编译技术研究
焦 涌 赖 娜
中国电子科技集团第28研究所,江苏 南京 210000
随着互联网技术的兴起,Java编程语言发挥着越来越重要的作用,越来越多的互联网应用使用Java编程语言编写而成。但是,由于Java语言的开放性和平台无关特性,Java代码不是直接编译成二进制可执行代码,而是编译成class文件。class文件能够被轻易的反编译源代码,这样用Java编写成的程序就很容易被破解,泄漏应用逻辑或者被非法使用。首先从最一般的反编译技术谈起,分析了目前市面上流行的反编译技术,最后提出了一种新的反编译技术,能够有效防止Java程序被反编译。
Java防反编译技术;代码混淆;class文件加密
由于Java编平台的开放性,Java应用程序是由class文件组成。class文件并非是二进制机器码,而是将源码进行符号化和标记化,这种class文件很容易进行反编译还原出源码。这就带来了非常严重的问题,只要非法用户愿意,他就能够轻松的获取软件源码,从而获得一些商业信息。因此,防止反编译就成为了一个非常重要的内容。
Java程序自诞生起的一个目标就是跨平台,为了实现这个目标,Java程序选择将源码编译成平台无关的class文件,编译的过程不是直接产生机器码,而是将源码符号化和标记化,这就为反编译创造了条件。现在市面上有很多流行的反编译软件,能够轻松的将class文件反编译成源码。一旦获得了源码就等于是获得了软件的所有信息,这对于软件的开发者非常的不利。毕竟很多软件都是收费的,拥有版权信息,甚至于很多软件还包含了商业公司的重要机密,一旦软件被反编译,这就意味着软件不再拥有版权,因为窃取者能够通过修改源码轻松的破解版权保护,甚至通过阅读源码轻松的获取商业机密。因此,Java软件的防反编译就成为了一项非常重要的内容,是很多J2EE项目的基本组成部分。为了防止反编译,目前市面上主流的技术有代码混淆、class文件加密、JNI本地代码和class文件隔离[1]。
代码混淆是一种最基本的防反编译方式。前面说过,由于Java的编译过程就是将源码简单的符号化和标记化。因此代码混淆主要是将class文件中的符号进行修改,将其复杂化,这样就加大了class文件反编译的难度,同时,反编译后的源码也难以阅读。由于这种方式并没有对class文件进行加密,因此源码仍然可以获得,只不过是增加了阅读的难度而已,对于耐心的程序员这都不是问题。同时,由于对class文件进行了混淆,有可能会造成class文件无法被Java虚拟机正常执行。现在市面上有很多代码混淆软件,有免费的也有收费的。代码混淆只是初级的防反编译技术,仅仅做了最低程度的保护。如果对Java软件有着较高的安全要求,代码混淆技术无法胜任[2]。
既然明文形式形式的class文件很容易被反编译,如果将class文件进行加密,class文件以密文形式交给用户,这样非法用户就无法通过反编译class文件来窃取软件源码。这样做有一个问题就是所有的class文件都必须要交给Java虚拟机去执行,而Java虚拟机是无法识别加密的class文件的,因此在交给虚拟机执行以前,class文件必须解密。Java虚拟机通过classloader来加载class文件,因此,为了解决这个问题,通常要提供自己的classloader类,在将类最终交给Java执行之前,会将类解密。这样,class文件只会在内存中被解密,不会以明文形式存在于用户的系统中,从而保证了class文件不会被反编译。这种方式最大的问题就是用户自己实现的classloader不可能被加密,因为它是首先被Java虚拟机加载的。所以,如果用户将最初的classloader进行反编译,获得源码,就能够获得将其他类解密的方式,从而将其他的class文件解密,然后反编译,最终获得源码。因此,为了防止非法用户反编译最初的classloader文件,通常的做法是将最初的classloader文件尽可能的隐藏起来,防止用户找到。这种方式治标不治本,如果非法用户有足够的耐心,他还是能够找到那个未加密的class文件,从而窃取整个软件的源代码。
Java通过JNI方式来实现和C/C++代码的相互调用,而C/C++编译成的可执行代码是无法反编译的。这就又提供了一种方式,就是将核心重要的代码用C/C++写成,然后用Java程序调用它。这样做确实可以防止反编译,但是由于没有使用Java语言,就丧失了很多Java语言的优势,并且这样做其实本质上是用C/C++语言而不是Java语言,这里不多做研究。
class文件存储在用户系统上很容易被用户反编译,那么如果不将class文件存储在用户系统上,用户也就无法反编译了。为了做到这一点,需要客户端-服务端双层架构。所有的应用程序逻辑都存放到服务端,服务端提供访问接口,客户端通过接口访问服务端提供的服务。这种方式由于没有class文件存放在客户端,因此用户也就无法通过反编译class文件来获取应用逻辑。但是这种方式必须要求双层架构,因此适用场景有限。很多时候用户都只需要一个单独的应用程序运行在本地,没有网络访问,对于这种情形,就无法实现class文件的隔离。
上面罗列的几种防止反编译的方法都不能够有效的防止反编译,不是不彻底就是使用场景有限。下面本文将讨论一种新的防止反编译的方法。
JVMTI是JDK提供的一套用于开发JVM监控, 问题定位与性能调优工具的通用编程接口(API)。通过JVMTI,我们可以开发各式各样的Java虚拟机应用,这种应用的表现形式是一个以C/C++语言编写的动态共享库。Java虚拟机启动或运行时,动态加载一个外部基于JVM TI编写的动态模块到Java进程内,这个动态模块就是基于JVMTI编写的JAVA虚拟机应用,然后触发JVM原生线程Attach Listener来执行这个动态模块的回调函数。在回调函数体内,你可以获取各种各样的VM级信息,注册感兴趣的VM事件,甚至控制VM的行为。
JVMTI提供的接口中包含了一个加载class之前调用的回调接口,内容如下:
typedef void (JNICALL *jvmtiEventClassFileLoadHook)
(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jclass class_being_redefined,
jobject loader,
const char* name,
jobject protection_domain,
jint class_data_len,
const unsigned char* class_data,
jint* new_class_data_len,
unsigned char** new_class_data);
在Java虚拟机装载一个类之前会调用该接口,接口参数中包含了加载到Java虚拟机的原始的class文件数据,以及接口调用完毕之后新的class文件数据。当接口调用完后Java虚拟机会加载新的class数据并且运行。这就为防止反编译提供了新的思路。如果我们将class文件加密后交付给用户,然后实现一个解密动态模块,该动态模块实现了对class文件的解密。这样,当Java虚拟机加载加密的class文件之前会调用解密动态模块,解密模块将class文件数据在内存中进行解密,然后Java虚拟机会加载揭秘过后的原始的class文件数据并且运行。通过这种方式,用户系统中没有任何未加密的class文件,并且所有的应用逻辑仍然是以Java写成,应用开发者只需要编写一个通用的解密动态模块,然后将应用程序包含的所有class文件加密,将加密的应用程序和解密动态模块一起交付给用户,解密动态模块由C/C++编写而成,是二进制机器码,无法反编译,因而class文件也无法反编译,从而实现了防反编译。
[1]李林蔚.Java字节码文件保护分析与研究[J].内江职业技术学院学报,2014(3):51-52.
[2]林汉玲,方颖珏,王晓峰.密码技术在Java类文件保护技术中的新应用[J].现代电子技术,2013,36(3):102-103.
Research on Anti - Compiler Technology of JAVA
Jiao Yong Lai Na
Twenty-eighth Research Institute of China Electronic Science and technology group, Nanjing 210000, Jiangsu, China
with the rise of Internet technology, JAVA programming language is playing a more and more important role, more and more Internet applications using JAVA programming language. However, due to the open nature of the JAVA language and platform independent characteristics, JAVA code is not directly compiled into binary executable code, but compiled into class files. Class files can be easily compiled source code, so that the use of JAVA into the program is very easy to be cracked, the leak of the application logic or illegal use. This paper first from the most general anti compiler technology, analysis of the current popular anti compiler technology in the market, and finally put forward a new anti compilation technology, can effectively prevent the JAVA program is anti compiler.
JAVA anti - Anti - compiler technology; research
TP312.2
A
1009-6434(2016)10-0012-02