logo资料库

java代码保护,防止反编译.doc

第1页 / 共16页
第2页 / 共16页
第3页 / 共16页
第4页 / 共16页
第5页 / 共16页
第6页 / 共16页
第7页 / 共16页
第8页 / 共16页
资料共16页,剩余部分请下载后查看
陕西职业技术学院计算机科学系学生毕业论文 1 Java 程序的保护 摘要 由于 Java 语言面向对象和编译成中间代码执行的特点,其在抗反编译和反盗版方 面显得尤其脆弱。本文针对 Java 软件的特点,运用多种方法,综合设计出一个保护 Java 类 文件的方法。Java 是一种跨平台的、解释型语言。Java 源代码编译中间“字节码”存 储于 class 文件中。Class 文件是一种字节码形式的中间代码,该字节码中包括了很多源 代码的信息,例如变量名、方法名 等。因此,Java 中间代码的反编译就变得非常容易。 目前市场上有许多免费的、商用的反编译软件,都能够生成高质量的反编译后的源代码。 所以,对开发人员 来说,如何保护 Java 程序就变成了一个非常重要的挑战。本文首先 讨论了保护 Java 程序的基本方法,然后对代码混淆问题进行深入研究,最后结合一个实 际 的应用程序,分析如何在实践中保护 Java 程序。 关 键 词: Class;加密;密钥;代码混淆 目前,Java 编程语言的应用在全世界范围正流行,它广泛的应用在 Internet 的数据 库、 多媒体、CGI 及动态网页的制作方面。1999 年在美国对 Java 程序员的需求量首 次超过 C++。 经调查统计,Java 语言应用在软件领域占领着举足轻重的地位,为人类 科技文明进步奠定了 重要基础。然而,Java 语言却存在着巨大的安全隐患。Java 是一 种跨平台的、解释型语言。 第一,Java 源代码编译中间“字节码”存储于 Class 文件中。 Class 文件是一种字节码形式的中 间代码,该字节码中包括了很多源代码的信息,例如 变量名、方法名等;第二,由于跨平台 的需求,Java 的指令集比较简单通用,较容易 得出程序的语义信息;第三,Java 编译器将每 一个类编译成一个单独的文件,这也简 化了反编译的工作;第四,Java 的 Class 文件中,仍 然保留所有的方法和变量的名称, 可以通过这些名称来访问变量和方法,这些符号往往带有 许多语义信息。因此,Java 程 序的这些特点,很容易对不经过处理的 Java 程序进行反编译。 目前,市场上有许多优 秀的 Java 反编译工具,能够反编译出非常接近源代码的程序。所以, 对开发人员来说, 如何保护 Java 程序就变成一个非常重要的任务。 1
陕西职业技术学院计算机科学系学生毕业论文 2 第一章 JAVA 类文件的安全威胁 1.1 JAVA 的编译 开发 Java 应用程序首先是使用编辑工具编写 Java 的源代码,然后使用编译器编 译成虚 拟机可执行的 Class 类文件。编译后生成的类文件是一种有格式的中间代码 ——字节码文件, 不能在本地机器上独立运行,只能在 Java 虚拟机里解释执行。Java 编译器不对变量和方法 等符号的引用转换为数值引用,也不确定程序执行过程中的内 存布局,而是将这些符号的引 用信息保留在类文件中,由解释器在运行过程中创建内 存布局,然后再通过查找表来确定一 个变量或方法所在的地址[1]。 从 Java 类文件的结构及其实际数据可知 Java 类文件保留了源代码文件的大部分信 息, 如所有的变量和方法等信息。正是由于这个特点,只要在各个平台上实现了各自 的 Java 虚 拟机,不用修改 Java 应用程序的源代码就可以在各个平台上运行,真正做 到跨平台的特性, 这也是 Java 能够迅速流行起来的重要原因。 1.2 JAVA 的反编译 反编译是一个将目标代码转换成源代码的过程[2]。而目标代码是一种用语言表示的 代 码,这种语言能通过实机或虚拟机直接执行。从本质上说,他需要根据小规模、低 层次的行 为来推断大规模、高层次的行为。因此,反编译目标代码并不容易。 在 JDK 中,有一个反编译器 javap[3],利用该工具可以对 Java 类文件进行反编译。 经过 该工具反汇编后得到的结果并不是源代码,但是使用 javap 进行反编译的 Java 类文件 可以得 到成员变量、方法、行号以及局部变量名等信息[4]。在 javap 工具的基础上, 一些反编译工 具如 Mocha,WinDis,DjDecompiler 等工具可反编译出和源代码几乎一 摸一样的代码。 第二章 JAVA 语言 Java 语言的优点主要表现在:简单、面向对象、多线程、分布性、体系结构中立、 安全性等方面 2.1 简单性 Java 与 C++语言非常相近,但 Java 比 C++简单,它抛弃了 C++中的一些不是绝对必 2
陕西职业技术学院计算机科学系学生毕业论文 3 要的功能,如头文件、预处理文件、指针、结构、运算符重载、多重继承以及自动强迫 同型。 Java 实现了自动的垃圾收集,简化了内存管理的工作。这使程序设计更加简便, 同时减少了出错的可能。 2.2 面向对象 Java 提供了简单的类机制和动态的构架模型。对象中封装了它的状态变量和方法,很好 地实现了模块化和信息隐藏;而类则提供了一类对象的原型,通过继承和重载机制,子 类可以使用或重新定义父类或超类所提供的方法,从而既实现了代码的复用,又提供了 一种动态的解决方案。 Java 是一种完全面向对象的程序设计语言,它除了数组、布尔和字符三个基本数据 类型外的其它类都是对象,它不再支持全局变量。在 Java 中,如果不创建新类就无法 创建程序,Java 程序在运行时必须先创建一个类的实例,然后才能提交运行。 Java 同样支持继承特性,Java 的类可以从其它类中继承行为,但 Java 只支持类的单重 继承,即每个类只能从一个类中继承。 Java 支持界面,界面允许程序员定义方法但又不立即实现,一个类可以实现多个界 面,利用界面可以得到多重继承的许多优点而又没有多重继承的。 2.3 多线程 多线程使应用程序可以同时进行不同的操作,处理不同的事件。在多线程机制中, 不同的线程处理不同的任务,他们之间互不干涉,不会由于一处等待其他部分,这样容 易实现网络上的实时交互操作。 Java 程序可以有多个执行线程,如可以让一个线程进行复杂的,而让另一个线程与用户 进行交互,这样用户可以在不中断计算线程的前提下与系统进行交互。多线程保证了较 高的执行效率。 2.4 分布性 Java 是面向网络的语言。通过它提供的类库可以处理 TCP/IP 协议,用户可以通过 URL 地址在网络上很方便的访问其他对象。 2.5 体系结构中立 Java 是一种网络语言,为使 Java 程序能在网络的任何地方运行,Java 解释器生成与体 系结构无关的字节码结构的文件格式。Java 为了做到结构中立,除生成机器无关的字节 码外,还制定了完全统一的语言文本,如 Java 的基本数据类型不会随目标机的变化而变 化,一个整型总是 32 位,一个长整型总是 64 位。 3
陕西职业技术学院计算机科学系学生毕业论文 4 为了使 Java 的应用程序能不依赖于具体的系统,Java 语言环境还提供了用于访问底层 操作系统功能的类组成的包,当程序使用这些包时,可以确保它能运行在各种支持 Java 的平台上。 java.lang: 一般的语言包。其中包括用于字符串处理、多线程、异常处理和数字函数等 的类,该包是实现 Java 程序运行平台的基本包 java.util: 实用工具包。其中包括哈希表、堆栈、时间和日期等 java.io: 基于流模型的输入/输出包。该包用统一的流模型实现了各种格式的输入/输出, 包括文件系统、网络和设备的输入/输出等 java.net: 网络包。该包支持 TCP/IP 协议,其中提供了 socket、URL 和 WWW 的编程接 口 java.awt: 抽象窗口工具集。其中实现了可以跨平台的图形用户界面组件,包括窗口、菜 单、滚动条和对话框等 java.applet: 支持 applet 程序设计的基本包 2.6 安全性 用于网络、分布环境下的 Java 必须要防止病毒的入侵,Java 不支持指针,一切对内存 的访问都必须通过对象的实例变量来实现,这样就防止了程序员使用欺骗手段访问对象 的私有成员,同时也避免了指针操作中容易产生的错误。 第三章 常用 JAVA 类文件的保护方法 3.1 JAVA 类文件的保护方法 由于 Java 字节码的抽象级别较高,容易被反编译,所以就有了多种防止 Java 字 节码被 反编译的方法。 隔离 Java 程序:最简单的方法就是让用户不能够访问到 Java Class 程序,这种 方法是最 根本的方法,具体实现有多种方式。 代码混淆:这种方法对 Class 文件进行重新组织和处理,使得处理前后的代码具有相 同的语义,被混淆后的代码很难被反编译。 转换成本地代码:本地代码难以被反编译,开发人员可以选择将整个应用程序或关 键模块转换成本地代码。如果仅仅转换关键模块,在使用这些模块时,需调用 JNI 技 术,这将牺牲 Java 的跨平台特性 4
陕西职业技术学院计算机科学系学生毕业论文 5 加密 Class 文件:为了防止 Class 文件被直接反编译,可以将一些关键的 Class 文 件加密 例如对密钥、加密算法、注册码、序列号管理相关的类等。在使用这些被加密的类 之前 先解密,然后再将其装载到 JVM 中。 对比上述几种方法,都存在其自身的优缺点。隔离 Java 程序只能适合网络环境的 客户 机/服务器结构或者分布式的环境,对单机运行的程序就无法隔离,而且 Java 程 序需要使用 安全机制保护服务器开放接口的使用,服务器的安全成了整个系统安全的 焦点。代码本地化, 对于不同的平台,需要维护不同版本的本地代码,这将加重软件 支持和维护的工作。对 Class 文件进行加密,在使用时再进行解密,同时将关键加密 代码部分进行代码混淆,这样经过双 重处理后,代码的安全性[6]提高了很多,该方法 也是本文研究的重点。 第四章 class 文件加密技术 Java 生成的 Class 文件大量暴露在客户端,利用现在的反编译工具可轻易的获取 源代码, 下面将讲叙如何有效的保护 Class 文件。 4.1 读取本工程的所有待加密 Class 文件,并保存到 byte 型数组中; public static byte[] symmetricEncrypt(byte[] key, byte[] classData) {…};方 法对读取到的所 有 Class 文件进行加密, key 为用来加密的密钥,classData 为所读到的待加密 Class 文件, 返回结果为加密后的 Class 文件,然后将其写回原来的 Class 中,保证结构 的完整性。 4.2 加密过的 Cl 行解密,最后将解密后的类装载到 JVM 这里我的虚拟机有默认的类加载器,但是若要它根据用户提供的密码解密代码就难 以做到, 此时需要通过自定义 ClassLoader 类来完成加密类的装载。自定义的 ClassLoader 首先找到被 加密过的类,然后进行解密,最后将解密后的类装载到 JVM 中。这里我的自定义 ClassLoader 如下: ClassLoader appLoader=new EncryptedClassLoader(EncryptedCla ssLoader.class.getClassLoader(), new File(args[1])); Thread.currentThread().setContextClassLoader(appLoader); 5
陕西职业技术学院计算机科学系学生毕业论文 6 final Class app = appLoader.loadClass(args[2]); 其中参数 args[1]传入的是方法所在的工程名,args[2]为主函数所在的类名。 在加载类后,系统的默认 findClass()并未对加载的类作任何处理,由于 Class 文件已被 加密过,此时若运用系统方法 findClass()则会抛出 ClassNotFoundException()的异 常,所以这里需要重构我自己的findClass()方法: protected Class findClass(final String name) throws ClassNotFoundException { final String classResource = name.replace('.', '/') + ".class"; final URL classURL = getResource(classResource); InputStream in = null; File file = new File(classURL.getPath()); byte[] classBytes = new byte[(int)file.length()]; FileInputStream fin = new FileInputStream(file); fin.read(classBytes); …… classBytes = decrypt(classBytes); //解密 …… return defineClass(name, classBytes, 0, classBytes.length); } 在这个函数中,我运用 decrypt(classBytes);方法对所有的加密 Class 文件进行 解密,并 在其中调用方法public static byte[] symmetricEncrypto(byte[] key, byte[] byteSource){}将解密 后的Class 文件保存直原文件处,保持文件目录级别不 变, key 为解密密钥,byteSource 为待 解密的 byte 型文件。至此,已完成对类文件的加密和解密,经过测试,功能已实现,Class 文件无法被反编译。但为进一步加强程序的安全性,我做了如下的处理。 对 包含 有 关 键 信息 的 方 法 进行 代 码 混 淆处 理 。 在上 述 内 容 中, 方法 symmetricEncrypt(byte[] key, byte[] classData) 包 含 有 加 密所 用 到 的 算 法 , 自定 义 的 ClassLoader 包含有关键信息,findClass(final String name)以及 decrypt(classBytes);中包含有解 密信息,由于它们本身不是被加密的,因此它可能成 6
陕西职业技术学院计算机科学系学生毕业论文 7 为黑客最先攻击的目标。如果相关的解密密钥和算法被攻克,那么被加密的类也很容易 被解密。所以这里我对这些关键代码进行代 码混淆。代码混淆是对代码进行重新组织和 处理,使得处理后的代码与处理前的代码完成相 同的功能,但是混淆后的代码很难被反 编译。代码混淆有符号混淆、数据混淆、控制混淆和 预防性混淆。这里我采用数据混淆 对关键代码进行处理。 public static byte[] symmetricEncrypt(byte[] key, byte[] classData) {…}; 处理如下: //rawKey,byteSource 为symmetricEncrypt(byte[], byte[])的待传入参数 byte[] tempkey = null; tempkey [0] = 0x00; for (int i = 0; i < key.length; i++) tempkey [i+1] = key[i]; tempkey [key.length + 1] = 0x11; byte[] source = null; source[0] = 0x00; for(int i = 0; i < classData.length; i++) source[i+1] = classData[i]; source[classData.length + 1] = 0x11; public static byte[] symmetricEncrypt(byte[]tempkey, byte[]source) { //取 tempkey 和 source 的除第一个和最后一个 byte 的值 ...... } 对public Class loadClass(final String tempname, final boolean resolve){}方法进 行处理: String tempname = "abcdefg" + name ; //name:loadClass 的第一个待传入参数 public Class loadClass(final String tempname, final boolean resolve){ String name = tempname.substring(11,tempname.length()); ...... } 7
陕西职业技术学院计算机科学系学生毕业论文 8 对findClass(String name){}方法进行处理: //name 为findClass(String name)待传入参数,先做如下处理 addname = name + "01357924680"; protected Class findClass(final String addname){ name = addname.substring(0,addname.length()-11); ......//fingClass 其他工作 } int len; //len = 待传文件file 的长度:file.length() byte[] classBytes = new byte[(int) len]; classBytes[len + 1] = 0x00; classBytes[len + 2] = 0x11; //classBytes 作为decrypt(byte[] classBytes)的传入参数 private static byte[] decrypt(final byte[] classBytes){ byte[] data = new byte[(int)classByte.lengt - 2]; for(int i = 0; i < data.length; i++) data[i] = classBytes[i]; ...... //解密工作 } 第五章 如何有效的保护 JAVA 程序 5.1 从头到尾保护 JAVA 目 前 关 于 JAVA 程 序 的 加 密 方 式 不 外 乎 JAVA 模 糊 处 理 ( Obfuscator ) 和 运 用 ClassLoader 方法进行加密处理这两种方式(其他的方式亦有,但大多是这两种的延伸 和变异)。这两种方式不管给 JAVA 反编译器造成多少困难, 毕竟还是有迹可寻,有机 可乘的。本文介绍的方法是对 ClassLoader 方式加密处理的一种改进,使之达到传统二 进制程序代码安全。 关于 JAVA 程序的加密方式,一直以来都是以 JAVA 模糊处理(Obfuscator)为主。 这方面的研究结果也颇多,既有模糊器(如现在大名鼎鼎的 JODE),也有针对反编译器 的"炸弹"(如针对反编译工具 Mocha 的 "炸弹" Crema 和 HoseMocha)。模糊器,从其字 8
分享到:
收藏