java编译混淆.docx

上传人:b****5 文档编号:12189363 上传时间:2023-04-17 格式:DOCX 页数:19 大小:136.68KB
下载 相关 举报
java编译混淆.docx_第1页
第1页 / 共19页
java编译混淆.docx_第2页
第2页 / 共19页
java编译混淆.docx_第3页
第3页 / 共19页
java编译混淆.docx_第4页
第4页 / 共19页
java编译混淆.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

java编译混淆.docx

《java编译混淆.docx》由会员分享,可在线阅读,更多相关《java编译混淆.docx(19页珍藏版)》请在冰豆网上搜索。

java编译混淆.docx

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程序

  最简单的方法就是让用户不能够访问到JavaClass程序,这种方法是最根本的方法,具体实现有多种方式。

例如,开发人员可以将关键的JavaClass放在服务器端,客户端通过访问服务器的相关接口来获得服务,而不是直接访问Class文件。

这样黑客就没有办法反编译Class文件。

目前,通过接口提供服务的标准和协议也越来越多,例如HTTP、WebService、RPC等。

但是有很多应用都不适合这种保护方式,例如对于单机运行的程序就无法隔离Java程序。

这种保护方式见图1所示。

  图1隔离Java程序示意图

  对Class文件进行加密

  为了防止Class文件被直接反编译,许多开发人员将一些关键的Class文件进行加密,例如对注册码、序列号管理相关的类等。

在使用这些被加密的类之前,程序首先需要对这些类进行解密,而后再将这些类装载到JVM当中。

这些类的解密可以由硬件完成,也可以使用软件完成。

  在实现时,开发人员往往通过自定义ClassLoader类来完成加密类的装载(注意由于安全性的原因,Applet不能够支持自定义的ClassLoader)。

自定义的ClassLoader首先找到加密的类,而后进行解密,最后将解密后的类装载到JVM当中。

在这种保护方式中,自定义的ClassLoader是非常关键的类。

由于它本身不是被加密的,因此它可能成为黑客最先攻击的目标。

如果相关的解密密钥和算法被攻克,那么被加密的类也很容易被解密。

这种保护方式示意图见图2。

  图2对Class文件进行加密示意图

  转换成本地代码

  将程序转换成本地代码也是一种防止反编译的有效方法。

因为本地代码往往难以被反编译。

开发人员可以选择将整个应用程序转换成本地代码,也可以选择关键模块转换。

如果仅仅转换关键部分模块,Java程序在使用这些模块时,需要使用JNI技术进行调用。

  当然,在使用这种技术保护Java程序的同时,也牺牲了Java的跨平台特性。

对于不同的平台,我们需要维护不同版本的本地代码,这将加重软件支持和维护的工作。

不过对于一些关键的模块,有时这种方案往往是必要的。

  为了保证这些本地代码不被修改和替代,通常需要对这些代码进行数字签名。

在使用这些本地代码之前,往往需要对这些本地代码进行认证,确保这些代码没有被黑客更改。

如果签名检查通过,则调用相关JNI方法。

这种保护方式示意图见图3。

  代码混淆

  图3转换成本地代码示意图

  代码混淆是对Class文件进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能(语义)。

但是混淆后的代码很难被反编译,即反编译后得出的代码是非常难懂、晦涩的,因此反编译人员很难得出程序的真正语义。

从理论上来说,黑客如果有足够的时间,被混淆的代码仍然可能被破解,甚至目前有些人正在研制反混淆的工具。

但是从实际情况来看,由于混淆技术的多元化发展,混淆理论的成熟,经过混淆的Java代码还是能够很好地防止反编译。

下面我们会详细介绍混淆技术,因为混淆是一种保护Java程序的重要技术。

图4是代码混淆的示意图。

  图4代码混淆示意图

  几种技术的总结

  以上几种技术都有不同的应用环境,各自都有自己的弱点,表1是相关特点的比较。

  混淆技术介绍

  表1不同保护技术比较表

  到目前为止,对于Java程序的保护,混淆技术还是最基本的保护方法。

Java混淆工具也非常多,包括商业的、免费的、开放源代码的。

Sun公司也提供了自己的混淆工具。

它们大多都是对Class文件进行混淆处理,也有少量工具首先对源代码进行处理,然后再对Class进行处理,这样加大了混淆处理的力度。

目前,商业上比较成功的混淆工具包括JProof公司的1stBarrier系列、Eastridge公司的JShrink和的SourceGuard等。

主要的混淆技术按照混淆目标可以进行如下分类,它们分别为符号混淆(LexicalObfuscation)、数据混淆(DataObfuscation)、控制混淆(ControlObfuscation)、预防性混淆(PreventTransformation)。

  符号混淆

  在Class中存在许多与程序执行本身无关的信息,例如方法名称、变量名称,这些符号的名称往往带有一定的含义。

例如某个方法名为getKeyLength(),那么这个方法很可能就是用来返回Key的长度。

符号混淆就是将这些信息打乱,把这些信息变成无任何意义的表示,例如将所有的变量从vairant_001开始编号;对于所有的方法从method_001开始编号。

这将对反编译带来一定的困难。

对于私有函数、局部变量,通常可以改变它们的符号,而不影响程序的运行。

但是对于一些接口名称、公有函数、成员变量,如果有其它外部模块需要引用这些符号,我们往往需要保留这些名称,否则外部模块找不到这些名称的方法和变量。

因此,多数的混淆工具对于符号混淆,都提供了丰富的选项,让用户选择是否、如何进行符号混淆。

  数据混淆

  图5改变数据访问

  数据混淆是对程序使用的数据进行混淆。

混淆的方法也有多种,主要可以分为改变数据存储及编码(StoreandEncodeTransform)、改变数据访问(AccessTransform)。

  改变数据存储和编码可以打乱程序使用的数据存储方式。

例如将一个有10个成员的数组,拆开为10个变量,并且打乱这些变量的名字;将一个两维数组转化为一个一维数组等。

对于一些复杂的数据结构,我们将打乱它的数据结构,例如用多个类代替一个复杂的类等。

  另外一种方式是改变数据访问。

例如访问数组的下标时,我们可以进行一定的计算,图5就是一个例子。

  在实践混淆处理中,这两种方法通常是综合使用的,在打乱数据存储的同时,也打乱数据访问的方式。

经过对数据混淆,程序的语义变得复杂了,这样增大了反编译的难度。

  控制混淆

  控制混淆就是对程序的控制流进行混淆,使得程序的控制流更加难以反编译,通常控制流的改变需要增加一些额外的计算和控制流,因此在性能上会给程序带来一定的负面影响。

有时,需要在程序的性能和混淆程度之间进行权衡。

控制混淆的技术最为复杂,技巧也最多。

这些技术可以分为如下几类:

  增加混淆控制通过增加额外的、复杂的控制流,可以将程序原来的语义隐藏起来。

例如,对于按次序执行的两个语句A、B,我们可以增加一个控制条件,以决定B的执行。

通过这种方式加大反汇编的难度。

但是所有的干扰控制都不应该影响B的执行。

图6就给出三种方式,为这个例子增加混淆控制。

  图6增加混淆控制的三种方式

  控制流重组重组控制流也是重要的混淆方法。

例如,程序调用一个方法,在混淆后,可以将该方法代码嵌入到调用程序当中。

反过来,程序中的一段代码也可以转变为一个函数调用。

另外,对于一个循环的控制流,为可以拆分多个循环的控制流,或者将循环转化成一个递归过程。

这种方法最为复杂,研究的人员也非常多。

  预防性混淆

  这种混淆通常是针对一些专用的反编译器而设计的,一般来说,这些技术利用反编译器的弱点或者Bug来设计混淆方案。

例如,有些反编译器对于Return后面的指令不进行反编译,而有些混淆方案恰恰将代码放在Return语句后面。

这种混淆的有效性对于不同反编译器的作用也不太相同的。

一个好的混淆工具,通常会综合使用这些混淆技术。

  案例分析

  在实践当中,保护一个大型Java程序经常需要综合使用这些方法,而不是单一使用某一种方法。

这是因为每种方法都有其弱点和应用环境。

综合使用这些方法使得Java程序的保护更加有效。

另外,我们经常还需要使用其它的相关安全技术,例如安全认证、数字签名、PKI等。

  本文给出的例子是一个Java应用程序,它是一个SCJP(SunCertificateJavaProgrammer)的模拟考试软件。

该应用程序带有大量的模拟题目,所有的题目都被加密后存储在文件中。

由于它所带的题库是该软件的核心部分,所以关于题库的存取和访问就成为非常核心的类。

一旦这些相关的类被反编译,则所有的题库将被破解。

现在,我们来考虑如何保护这些题库及相关的类。

  在这个例子中,我们考虑使用综合保护技术,其中包括本地代码和混淆技术。

因为该软件主要发布在Windows上,因此转换成本地代码后,仅仅需要维护一个版本的本地代码。

另外,混淆对Java程序也是非常有效的,适用于这种独立发布的应用系统。

  在具体的方案中,我们将程序分为两个部分,一个是由本地代码编写的题库访问的模块,另外一个是由Java开发的其它模块。

这样可以更高程度地保护题目管理模块不被反编译。

对于Java开发的模块,我们仍然要使用混淆技术。

该方案的示意图参见图7。

  图7SCJP保护技术方案图

  对于题目管理模块,由于程序主要在Windows下使用,所以使用C++开发题库访问模块,并且提供了一定的访问接口。

为了保护题库访问的接口,我们还增加了一个初始化接口,用于每次使用题库访问接口之前的初始化工作。

它的接口主要分为两类:

  1.初始化接口

  在使用题库模块之前,我们必须先调用初始化接口。

在调用该接口时,客户端需要提供一个随机数作为参数。

题库管理模块和客户端通过这个随机数,按一定的算法同时生成相同的SessionKey,用于加密以后输入和输出的所有数据。

通过这种方式,只有授权(有效)的客户端才能够连接正确的连接,生成正确的SessionKey,用于访问题库信息。

非法的客户很难生成正确的SessionKey,因此无法获得题库的信息。

如果需要建立更高的保密级别,也可以采用双向认证技术。

  2.数据访问接口

  认证完成之后,客户端就可以正常的访问题库数据。

但是,输入和输出的数据都是由SessionKey所加密的数据。

因此,只有正确的题库管理模块才能够使用题库管理模块。

图8时序图表示了题库管理模块和其它部分的交互过程。

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-25下午12:

05

jshrink

需要注册,并且不能对自身进行反编译。

但是都很容易破。

换个jad反编出E.java,jshink.java这两个文件,修改一下就好了。

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 1   

 0

javamonkey

发贴/文章:

136

参与分:

500

专家分:

470

来  自:

北京海淀区三里河

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-25下午12:

56

也很不错jode

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

javaone

发贴/文章:

226

参与分:

6163

专家分:

2540

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-25下午1:

22

很好啊,另外,jigsaw怎样破解啊!

愿闻其详!

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

javaone

发贴/文章:

226

参与分:

6163

专家分:

2540

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-25下午1:

43

使用DJ反编E.class后,出现了很多:

JVMINSTRmonitorenter;

可见是经过混淆了的。

请问jigsaw是怎样破解的,是否可以把你的破解方法贴出来,或者能发一个到我的信箱:

xmeet@

万分感谢!

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

javaone

发贴/文章:

226

参与分:

6163

专家分:

2540

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-25下午2:

18

下面是我申请的一个License,好像没有什么限制啊。

11/25/2002xmeet@EVALUATIONONLYBXJKSMFDPAZOUWUM

把上面这行贴到启动后主窗口中的License子窗口中即可。

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

jigsaw

发贴/文章:

23

参与分:

72

专家分:

10

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-26上午9:

09

这个lic有时间限制的。

用jad反编译出的E.java和jshrink.java

修改E.java中的这一段(下面的已经修改了,就是注掉中间一大块):

/*******************************************************************/

privatefinalbooleanacceptDrag(Dd)

{

/*Bb=d.I("SourceFile");

if(b!

=null)

{

Strings=d.Z(b.Z);

if(s.length()==4&&Character.isUpperCase(s.charAt(3)))

{

if(addTreeWillExpandListener.L!

=null&&addTreeWillExpandListener.L.endsWith(s))

{

returntrue;

}else

{

getDefaultToolkit("ohno!

");

returnfalse;

//returntrue;

}

}

}*/

returntrue;

}

/*******************************************************************/

以及这一段(也已经修改过了):

/*******************************************************************/

privatefinalbooleanaddChangeListener()

{

if(getSourceActions<=0)

{

returntrue;

}

addHighlight();

getSourceActions=addTreeWillExpandListener.D();

switch(getSourceActions)

{

case-1:

case0:

//'\0'

returntrue;

case1:

//'\001'

//getDefaultToolkit("Missinglicensekey,seewww.e-fordetails");

//returnfalse;

returntrue;

case2:

//'\002'

//getDefaultToolkit("Evaluationlicensekeyhasexpired,seewww.e-fordetails");

//returnfalse;

returntrue;

case3:

//'\003'

//getDefaultToolkit("Invalidlicensekey");

//returnfalse;

returntrue;

case4:

//'\004'

//getDefaultToolkit("Internalerrorverifyinglicensekey");

//returnfalse;

returntrue;

}

//returnfalse;

returntrue;

}

/*******************************************************************/

然后再修改jshink.java中的这一段(已经修改过了):

/*******************************************************************/

publicstaticfinalvoidmain(Stringargs[])

{

CSQP=newH();

I(args);

/*if(I!

=null)

{

System.out.println("Jshrink2.18Copyright1997-2002EastridgeTechnologywww.e-");

inti=CSQP.D();

if(i>0)

{

if(i==2)

{

System.out.println("Evaluationlicensekeyhasexpired,renewatwww.e-

}else

{

System.out.println("Invalidlicensekey,renewatwww.e-["+i+"]");

}

}else

if(!

CSQP.A(I))

{

System.out.println("Errorwritingfile"+I);

}

}else*/

//{

Qq=Q.I("Jshrink2.18Copyright1997-2002EastridgeTechnologywww.e-");

E.I(CSQP);

q.dispose();

//}

}

/*******************************************************************/

修改好两个文件后,单独编译这两个文件,但是记住:

把jshrink.jar加入CLASSPATH

我记得编译的时候会报error,说有几个地方应该捕捉异常,但是不记得在哪里了,你按提示修改一下就是了。

然后再编译,这次就通过了,然后把两个class打到jshink.jar中,完毕!

goodluck

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

jigsaw

发贴/文章:

23

参与分:

72

专家分:

10

注册时间:

八月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-26上午9:

11

感觉jshrink反编译出的代码比jode的要更容易阅读。

本贴对您是否有帮助?

 投票:

是 否   投票结果:

 

 0   

 0

cherami

发贴/文章:

652

参与分:

17117

专家分:

4330

注册时间:

五月,2002

Re:

一个不错的反编译/混淆器jshrink

发表时间:

2002-11-26下午1:

24

呵呵,我刚刚用了一下,感觉不是很好,我的源代码如下:

packageorg.jr.jzj;

importjavax.swing.*;

importjavax.swing.table.*;

importjava.util.*;

importjavax.swing.event.*;

importjava.io.*;

importjava.awt.event.MouseAdapter;

importjava.awt.event.*;

publicclassJZJTableextendsJTable{

privatestaticJZJLoggerlogger=newJZJLogger(JZJTable.class);

TableColumnModelcolmodel;

publicJZJTable(TableModelmodel){

super(model);

colmodel

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1