欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > DOC文档下载  

    毕业论文Java程序的保护.doc

    • 资源ID:4859072       资源大小:106.53KB        全文页数:17页
    • 资源格式: DOC        下载积分:10金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要10金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    毕业论文Java程序的保护.doc

    陕西职业技术学院计算机科学系学生毕业论文17 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 程序就变成一个非常重要的任务。第一章 JAVA类文件的安全威胁1.1 JAVA的编译 开发 Java 应用程序首先是使用编辑工具编写 Java 的源代码,然后使用编译器编译成虚 拟机可执行的 Class 类文件。编译后生成的类文件是一种有格式的中间代码字节码文件, 不能在本地机器上独立运行,只能在 Java 虚拟机里解释执行。Java 编译器不对变量和方法 等符号的引用转换为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号的引 用信息保留在类文件中,由解释器在运行过程中创建内存布局,然后再通过查找表来确定一 个变量或方法所在的地址1。 从 Java 类文件的结构及其实际数据可知 Java 类文件保留了源代码文件的大部分信息, 如所有的变量和方法等信息。正是由于这个特点,只要在各个平台上实现了各自的 Java 虚 拟机,不用修改 Java 应用程序的源代码就可以在各个平台上运行,真正做到跨平台的特性, 这也是 Java 能够迅速流行起来的重要原因。1.2 JAVA的反编译 反编译是一个将目标代码转换成源代码的过程2。而目标代码是一种用语言表示的代 码,这种语言能通过实机或虚拟机直接执行。从本质上说,他需要根据小规模、低层次的行 为来推断大规模、高层次的行为。因此,反编译目标代码并不容易。 在 JDK 中,有一个反编译器 javap3,利用该工具可以对 Java 类文件进行反编译。经过 该工具反汇编后得到的结果并不是源代码,但是使用javap进行反编译的 Java 类文件可以得 到成员变量、方法、行号以及局部变量名等信息4。在 javap 工具的基础上,一些反编译工 具如 Mocha,WinDis,DjDecompiler 等工具可反编译出和源代码几乎一摸一样的代码。第二章 JAVA语言 Java语言的优点主要表现在:简单、面向对象、多线程、分布性、体系结构中立、安全性等方面2.1简单性 Java与C+语言非常相近,但Java比C+简单,它抛弃了C+中的一些不是绝对必要的功能,如头文件、预处理文件、指针、结构、运算符重载、多重继承以及自动强迫同型。 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位。为了使Java的应用程序能不依赖于具体的系统,Java语言环境还提供了用于访问底层操作系统功能的类组成的包,当程序使用这些包时,可以确保它能运行在各种支持Java的平台上。 java.lang: 一般的语言包。其中包括用于字符串处理、多线程、异常处理和数字函数等的类,该包是实现Java程序运行平台的基本包java.util: 实用工具包。其中包括哈希表、堆栈、时间和日期等java.io: 基于流模型的输入/输出包。该包用统一的流模型实现了各种格式的输入/输出,包括文件系统、网络和设备的输入/输出等: 网络包。该包支持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 的跨平台特性 加密 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(EncryptedClassLoader.class.getClassLoader(), new File(args1); Thread.currentThread().setContextClassLoader(appLoader); final Class app = appLoader.loadClass(args2); 其中参数 args1传入的是方法所在的工程名,args2为主函数所在的类名。 在加载类后,系统的默认 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);中包含有解 密信息,由于它们本身不是被加密的,因此它可能成为黑客最先攻击的目标。如果相关的解密密钥和算法被攻克,那么被加密的类也很容易被解密。所以这里我对这些关键代码进行代 码混淆。代码混淆是对代码进行重新组织和处理,使得处理后的代码与处理前的代码完成相 同的功能,但是混淆后的代码很难被反编译。代码混淆有符号混淆、数据混淆、控制混淆和 预防性混淆。这里我采用数据混淆对关键代码进行处理。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 = keyi;tempkey key.length + 1 = 0x11;byte source = null;source0 = 0x00;for(int i = 0; i < classData.length; i+) sourcei+1 = classDatai; sourceclassData.length + 1 = 0x11;public static byte symmetricEncrypt(bytetempkey, bytesource) /取 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();.对 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; classByteslen + 1 = 0x00; classByteslen + 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+)datai = classBytesi;./解密工作第五章 如何有效的保护JAVA程序5.1从头到尾保护JAVA 目前关于JAVA程序的加密方式不外乎JAVA模糊处理(Obfuscator)和运用ClassLoader方法进行加密处理这两种方式(其他的方式亦有,但大多是这两种的延伸和变异)。这两种方式不管给JAVA反编译器造成多少困难, 毕竟还是有迹可寻,有机可乘的。本文介绍的方法是对ClassLoader方式加密处理的一种改进,使之达到传统二进制程序代码安全。 关于JAVA程序的加密方式,一直以来都是以JAVA模糊处理(Obfuscator)为主。这方面的研究结果也颇多,既有模糊器(如现在大名鼎鼎的JODE),也有针对反编译器的"炸弹"(如针对反编译工具Mocha的 "炸弹" Crema和HoseMocha)。模糊器,从其字面上,我们就可以知道它是通过模糊处理JAVA代码,具体的说,就是更换变量名,函数名,甚至类名等方法使其反编译出来的代码变得不可理解。举个例子来说吧。先将将下面源代码编译成class文件。 public class testint sortway;void sort(Vector a)void setSortWay(int way)void sort(Vector a, int way)后通过JODE进行模糊处理后,反编译过来后, 可能变成下列代码。 public class OoOoooOo0Oo0Oint OoOo0oOo0Oo0O;void OoO0ooOo0Oo0O (Vector OoOoo0Oo0OoOO)void OoOo00oOoOo0O (int Oo0oooOo0Oo0O)void OoO0ooOo0Oo0O (Vector OoOoo0Oo0OoOO, int Oo0oooOo0Oo0O)OoOo00oOoOo0O (Oo0oooOo0Oo0O);OoO0ooOo0Oo0O (OoOoo0Oo0OoOO); 其实这只是做到了视觉上的处理,其业务逻辑却依然不变,加以耐心,仍是可以攻破的,如果用在用户身份验证等目的上,完全可以找到身份验证算法而加以突破限制。 而所谓的"炸弹"是针对反编译工具本身的缺陷,这种方法对于特定的反编译工具是非常有效的,然而到目前为止,还没有一个全能型的,对每一种反编译工具皆有效,其局限性是明显的! 另一种方法是采用ClassLoader加密。JAVA虚拟机通过一个称为ClassLoader的对象装来载类文件的字节码,而ClassLoader是可以由JAVA程序自己来定制的。ClassLoader是如何装载类的呢?ClassLoader根据类名在jar包中找到该类的文件,读取文件,并把它转换成一个Class对象。该方法的原理就是,对需加密的类文件我们先行采用一定的方法(可以是PGP, RSA, MD5等方法)进行加密处理,我们可以在读取文件之后,进行解密后,再转换成一个Class对象。 有没有发现,该方法并未解决ClassLoader本身的安全性? 显然,只要反编译了该ClassLoader类,就可以顺藤摸瓜找到其它的类了。可见ClassLoader本身"明码"方式仍然造成一定的不安全性,然而,如果该方法解决了ClassLoader本身的安全性,其不失为一个比较好安全方案。5.2 ClassLoader加密方式改进 JAVA程序是通过java.exe/javaw.exe来启动的,要对ClassLoader进行解密处理,只能从java.exe/javaw.exe身上着手。 我们先来考察一下JDK的发布路径, 发现JDK的每一个版本都提供了src.jar,用winzip打开看看, 可以看到一个launcher的路径,里面包含的就是java.exe/javaw.exe的程序代码。哈哈, 这下我们可以随心所欲了。:)打开java.c看看,里面有一段, 如下:jstring mainClassName = GetMainClassName(env, jarfile);if (*env)->ExceptionOccurred(env) (*env)->ExceptionDescribe(env); goto leave;if (mainClassName = NULL) fprintf(stderr, "Failed to load Main-Class manifest attribute " "fromn%sn", jarfile); goto leave;classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);if (classname = NULL) (*env)->ExceptionDescribe(env); goto leave;mainClass = LoadClass(env, classname);(*env)->ReleaseStringUTFChars(env, mainClassName, classname); else mainClass = LoadClass(env, classname); if (mainClass = NULL) (*env)->ExceptionDescribe(env); status = 4;goto leave; 其中,函数LoadClass见下:static jclassLoadClass(JNIEnv *env, char *name) char *buf = MemAlloc(strlen(name) + 1); char *s = buf, *t = name, c; jclass cls; jlong start, end; if (debug)start = CounterGet(); do c = *t+;*s+ = (c = '.') ? '/' : c; while (c != '0'); cls = (*env)->FindClass(env, buf); free(buf); if (debug) end = CounterGet();printf("%ld micro seconds to load main classn", (jint)Counter2Micros(end-start);printf("-_JAVA_LAUNCHER_DEBUG-n"); return cls;分析上面的程序,我们可以看到env中的函数FindClass根据类名直接得到mainClass对象的。如果我们要装载已加密过的JAVA程序, 显然直接调用FindClass函数是不行的,那么,我们有没有办法自己读取文件,然后将之转换成一个mainClass对象呢?我们来看看JNIEnv里面还有什么?打开JDK路径includejni.h, 在里面我们查到下列定义:#ifdef _cplusplustypedef JNIEnv_ JNIEnv;#elsetypedef const struct JNINativeInterface_ *JNIEnv;#endif而在JNINativeInterface_的定义中:struct JNINativeInterface_ jclass (JNICALL *DefineClass) (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len);对了,DefineClass就是我们要找的,它可以将一个缓冲区(class字节码)转换成一个类实例!下面就是一个实现如何装载加密Class:static jclassLoadClass(JNIEnv *env, char *name)FILE *in; long length, i;char *cc;int x; char javaloader MAXPATHLEN, javapathMAXPATHLEN; char *buf = MemAlloc(strlen(name) + 1); char *s = buf, *t = name, c; jclass cls; jlong start, end; if (debug)start = CounterGet(); do c = *t+;*s+ = (c = '.') ? '/' : c; while (c != '0');/*如果装载的类是MyLoader*/if(strcmp(buf,"MyLoader")=0) if (GetApplicationHome(javapath, sizeof(javapath)sprintf(javaloader, "%sMyLoader.class", javapath);if (in = fopen(javaloader, "rb") = NULL)fprintf(stderr, "Cannot open input file.n");return (jclass)0x0f;/*读出加密的class文件*/fseek(in, 0L, SEEK_END);length = ftell(in);fseek(in, 0, SEEK_SET);cc = MemAlloc(length);fread(void*)cc,length,1,in);fclose(in);/*解密算法*/*将解密后的class字节码转换成class*/cls = (*env)->DefineClass(env, buf, 0, cc, length-1); free(cc);elsecls = (*env)->FindClass(env, buf); free(buf); if (debug) end = CounterGet();printf("%ld micro seconds to load main classn", (jint)Counter2Micros(end-start);printf("-_JAVA_LAUNCHER_DEBUG-n"); return cls;5.3应用范围由于解密需要一定的时间,如果不加区分的全部进行加密处理,势必会影响到程序的速度和响应。所以应该在需要加密的地方才加密,比方说,用户密码验证,专利算法,或者是数据库密码等等,这样的才不会导致系统的性能下降。要达到以上目的, ClassLoader必须对class加以判断,非加密的class调用JVM系统ClassLoader的LoadClass函数, 而对加密的才加以解密处理。建议:ClassLoader最好可配置!第六章 结 论 本文介绍了我针对 Java 类文件设计的保护方法,在众多方法中,我选择了对 Class 文件 进行加密这一思想,加密之后又对包含重要信息的方法进行代码混淆处理,这样就对文件起 到了双重保护的作用。经过在 Windows 平台上测试,效果良好,难以反编译,起到了很好 的保护作用。谢 辞首先,感谢我的毕业论文指导教师张丽老师。在选题和在论文完成的整个过程中,张老师都给予了悉心的指导,对论文提出了很多意见和建议,使得论文可以进一步完善,在这个过程中,我学习到了专业相关的知识,也学到了做设计的方法和做一个设计类工作者应该具备的各方面的素质。再者,感谢我的同学,在论文完成的过程中,多次与我讨论论文相关内容,对论文的进展提出很多建议,也多次为我提供相关数据和文献,给了我很大的帮助。参考文献1刘劼,JAVA反编译技术和代码安全J,现代电子技术,2004,27(10):22-23.2冀振燕,java编译程序技术与Java性能J,软件学报,2000,11(02):173-178.3陈晗、赵轶群、缪亚波,Java字节码的水印嵌入J,计算机应用,2003,23(9):96-99.4张敦华、刘建,Java动态类加载机制及其应用J,计算机工程与设 计,2004,25(3):432-435.5飞天诚信,软件加密原理与应用M,北京:电子工业出版社,2004.6陈刚,基于封装包的Java源代码安全保护J,电子信息对抗技术,2006,21(3):45-48.7施霞萍等编著.Java程序设计教程 第2版.北京:机械工业出版社,20068宛延闿等编著.实用Java程序设计教程.北京:机械工业出版社,20069陈国君等编著.Java2程序设计基础.北京:清华大学出版社,200617;18;17

    注意事项

    本文(毕业论文Java程序的保护.doc)为本站会员(sccc)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开