Java基础——–Java反编译

Java基础——–Java反编译一 反编译的概念反编译 一般指反向编译

大家好,欢迎来到IT知识分享网。

(参考http://www.hollischuang.com/archives/58 点击打开链接,以此为模板 自己做了整理、修改) 

目录

一. 反编译的概念

1.1 编程语言

1.2 什么是编译

1.3 什么是反编译

二. 反编译的工具

2.1 javap

2.2 jad

2.3 CFR

三. eclipse安装Java反编译插件

四. 防止反编译


一. 反编译的概念

反编译,一般指反向编译。

计算机软件反向工程(Reverse engineering)也称为计算机软件还原工程,是指通过对他人软件的目标程序(比如可执行程序)进行“逆向分析、研究”工作,以推导出他人的软件产品所使用的思路、原理、结构、算法、处理过程、运行方法等设计要素,某些特定情况下可能推导出源代码反编译作为自己开发软件时的参考,或者直接用于自己的软件产品中

1.1 编程语言

在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language)。编程语言(Programming Language)分为低级语言(Low-level Language)和高级语言(High-level Language)。
机器语言(Machine Language)和汇编语言(Assembly Language)属于低级语言,直接用计算机指令编写程序。
而C、C++、JavaPython等属于高级语言,用语句(Statement)编写程序,语句是计算机指令的抽象表示。
举个例子,同样一个语句用C语言、汇编语言和机器语言分别表示如下:
计算机只能对数字做运算,符号、声音、图像在计算机内部都要用数字表示,指令也不例外,上表中的机器语言完全由十六进制数字组成。最早的程序员都是直接用机器语言编程,但是很麻烦,需要查大量的表格来确定每个数字表示什么意思,编写出来的程序很不直观,而且容易出错,于是有了汇编语言,把机器语言中一组一组的数字用助记符(Mnemonic)表示,直接用这些助记符写出汇编程序,然后让汇编器(Assembler)去查表把助记符替换成数字,也就把汇编语言翻译成了机器语言。



但是,汇编语言用起来同样比较复杂,后面,就衍生出了Java、C、C++等高级语言。

1.2 什么是编译

当我们写完一个HelloWorld.java文件后,我们可以使用javac HelloWorld.java命令来生成HelloWorld.class文件,这个class类型的文件是JVM可以识别的文件。通常我们认为这个过程叫做Java语言的编译。其实,class文件仍然不是机器能够识别的语言,因为机器只能识别机器语言,还需要JVM再将这种class文件类型字节码转换成机器可以识别的机器语言。

1.3 什么是反编译

反编译的过程与编译刚好相反,就是将已编译好的编程语言还原到未编译的状态,也就是找出程序语言的源代码。就是将机器看得懂的语言转换成程序员可以看得懂的语言。Java语言中的反编译一般指将class文件转换成java文件。

有了反编译工具,我们可以做很多事情,最主要的功能就是有了反编译工具,我们就能读得懂Java编译器生成的字节码。如果你想问读懂字节码有啥用,那么我可以很负责任的告诉你,好处大大的。比如我的博文几篇典型的原理性文章,都是通过反编译工具得到反编译后的代码分析得到的。如深入理解多线程(一)——Synchronized的实现原理、深度分析Java的枚举类型—-枚举的线程安全性及序列化问题、Java中的Switch对整型、字符型、字符串型的具体实现细节、Java的类型擦除等。我最近在GitChat写了一篇关于Java语法糖的文章,其中大部分内容都用到反编译工具来洞悉语法糖背后的原理。

二. 反编译的工具

本文主要介绍3个Java的反编译工具:javap、jad和cfr

2.1 javap

javap是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码。javap和其他两个反编译工具最大的区别是他生成的文件并不是java文件,也不像其他两个工具生成代码那样更容易理解。拿一段简单的代码举例,如我们想分析Java 7中的switch是如何支持String的,我们先有以下可以编译通过的源代码:

Java基础--------Java反编译

我个人的理解,javap并没有将字节码反编译成java文件,而是生成了一种我们可以看得懂字节码。其实javap生成的文件仍然是字节码,只是程序员可以稍微看得懂一些。如果你对字节码有所掌握,还是可以看得懂以上的代码的。其实就是把String转成hashcode,然后进行比较。

个人认为,一般情况下我们会用到javap命令的时候不多,一般只有在真的需要看字节码的时候才会用到。但是字节码中间暴露的东西是最全的,你肯定有机会用到,比如我在分析synchronized的原理的时候就有是用到javap。通过javap生成的字节码,我发现synchronized底层依赖了ACC_SYNCHRONIZED标记和monitorenter、monitorexit两个指令来实现同步。

2.2 jad

Java基础--------Java反编译

2.3 CFR

Java基础--------Java反编译

CFR还有很多其他参数,均用于不同场景,读者可以使用java -jar cfr_0_125.jar –help进行了解。这里不逐一介绍了。

三. eclipse安装Java反编译插件

在实际的开发中几乎都会使用到一些框架来辅助项目的开发工作,对于一些框架的代码我们总怀有一些好奇之心,想一探究竟,有源码当然更好了,对于有些JAR包中的代码我们就需要利用反编译工具来看一下了,下面是我常使用的一种安装Java反编译工具的方法,操作比较简单。

1) Eclipse的版本信息

Java基础--------Java反编译

2) Help——Eclipse Marketplace

Java基础--------Java反编译

3-1) 输入 Decompiler 搜索并安装此插件

Java基础--------Java反编译

3-2) 输入 反编译 搜索并安装此插件(有好多好玩的插件,不妨尝试玩一玩)

Java基础--------Java反编译

4) 这里有几种不同的反编译插件工具的选择,可以先都选上,然后尝试一下,看看那个更好玩

Java基础--------Java反编译

5) 没得选,不接受,就不能继续玩了

Java基础--------Java反编译

6) 当然要继续了

Java基础--------Java反编译

7) 好啦!反编译插件安装完成了,重启Eclipse之后就能玩了,那就Yes吧!

Java基础--------Java反编译

8) 想看一下反编译插件安装后的设置选项 Window——Preferences

Java基础--------Java反编译

9) 下图为Eclipse Class Decompiler的首选项页面,可以选择缺省的反编译器工具,并进行反编译器的基本设置。

缺省的反编译工具为JD-Core,JD-Core更为先进一些,支持泛型、Enum、注解等JDK1.5以后才有的新语法。

Java基础--------Java反编译

       方法三:常按住Ctrl键,然后点击 类 || 接口 || 方法 名,即可进入源码。(我比较喜欢这种操作方式)

11) 插件提供了系统菜单,工具栏,当打开了插件提供的类反编译查看器后,会激活菜单和工具栏选项,可以方便的进行首选项配置,切换反编译工具重新反编译,以及导出反编译结果。

Java基础--------Java反编译

四. 防止反编译

如何防止反编译?我们都知道Java是一种解析型语言,这就决定Java文件编译后不是机器码,而是一个字节码文件,也就是CLASS文件。而这样的文件是存在规律的,经过反编译工具是可以还原回来的。

由于我们有工具可以对Class文件进行反编译,所以,对开发人员来说,如何保护Java程序就变成了一个非常重要的挑战。但是,魔高一尺、道高一丈。当然有对应的技术可以应对反编译咯。但是,这里还是要说明一点,和网络安全的防护一样,无论做出多少努力,其实都只是提高攻击者的成本而已。无法彻底防治。

典型的应对策略有以下几种:

        隔离Java程序
        让用户接触不到你的Class文件
        对Class文件进行加密
        提到激活成功教程难度
        代码混淆
        将代码转换成功能上等价,但是难于阅读和理解的形式




下面是《Nokia中Short数组转换算法》 类中Main函数的ByteCode:

其源代码是:short [] pixels = parseImage(“/ef1s.png”);

1,首先要添加一个参数为Exception类型的函数,例如这样。

 public static void Fake(Exception e) { e.toString(); }

一定要有e.toString();,因为要防止你的混淆器把无用的代码过滤。

2,然后在每个类中调用这个函数,放在try…catch(Exception e)..中的catch里面,例如:

 try { ... } catch (Exception e) { Fake(e); }

1,同样的,我们定义一个类,这个类叫做AntiCrack.。名字好像有点大。。。代码如下:

public class AntiCrack { private AntiCrack() { } public static Throwable Fake(Throwable throwable, Throwable throwable1) { try { throwable.getClass().getMethod("initCause", new Class[] { java.lang.Throwable.class }).invoke(throwable, new Object[] { throwable1 }); } catch(Exception exception) { } return throwable; } }

2,同样的,我们在catch里面调用该函数。例如如下。

 try { //your code here } catch(IOException ioexception) { IllegalArgumentException illegalargumentexception = new IllegalArgumentException(ioexception.toString()); AntiCrack.fake(illegalargumentexception, ioexception); throw illegalargumentexception; }

或者也可以这样

public class AntiException extends Exception { public AntiException() { } public AntiException(String s) { super(s); } public AntiException(String s, Throwable throwable) { super(s); AntiCrack.fake(this, throwable); } }

然后在你的程序里面

try { } catch(IoException e) { throw new AntiException(ioexception.toString(), ioexception); }

当采用以上方式后,任何类只要调用了该函数,生成的class反编译后出错,得不到结果。
Decafe、FrontEnd和YingJAD,反编译时都有exception,然后无法进行下去。大家可以多测试变得反编译工具。建议推荐用第二个方法。

—————————————————————— 我是低调的分隔线  ———————————————————————-

Java基础--------Java反编译

                                                                                                                             吾欲之南海,一瓶一钵足矣…

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112166.html

(0)
上一篇 2026-01-20 11:01
下一篇 2026-01-20 11:16

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信