Java类编译与反编译基础

    简单的说Java源码就是未经编译的.java文件,我们可以很轻松的阅读其中的代码逻辑,而字节码.class文件则是.java文件经过编译之后产生的字节码文件,因为.class文件是编译后的二进制文件所以我们是无法直接阅读的,只能通过反编译工具将二进制文件转换成java代码或者ASM代码

    示例代码Test.java:

    Test.java编译执行流程:

    Test.java 源码、字节码

    4

    由于class文件的可读性较差,通常我们需要使用Java反编译工具来反编译代码。我们通常会使用到JD-GUI、、Bytecode-Viewer、、JAD、、JEB 等工具来反编译class。

    当然,反编译工具很多时候也不是万能的,JD-GUI经常遇到无法反编译或反编译过程中程序直接崩溃的情况,遇到这类情况我们通常可以使用IDEA反编译试试,如果IDEA也无法反编译可以使用JBE来加载class文件读取程序的字节码,如果仍无法读取类信息还可以使用JDK自带的javap命令来读取class类字节码,如果上诉所有的方法都无法反编译,那么恐怕是这个类本身就存在无法编译问题要么可能就是类文件被加密处理过。可能你会说java编译的class不是说不可以加密吗?没错,这里所说的加密其实是为了保护编译后的class代码不可反编译,通过实现自定义ClassLoaderloadClass加密后的类方式而已,这种加密方式曾在实战中也有遇到。

    通常我们在某些特殊的场景下拿到的只是jar文件,那么我们应该如何反编译整个jar包的class文件呢?

    2.1. Fernflower

    Fernflower可以很轻松的实现jar的完整反编译,执行如下命令即可: java -jar fernflower.jar jarToDecompile.jar decomp/ 其中jarToDecompile.jar是需要反编译的jar文件,decomp是反编译后的class文件所存放的目录。需要注意的是Fernflower如遇无法反编译的情况可能会生成空的java文件!

    2.2. JD-GUI

    JD-GUI是一个带GUI的反编译工具,在JD-GUI的菜单中点击File—>Save All Sources即可反编译jar。

    2.3. IDEA

    IDEA默认就支持jar包反编译,同时还支持class文件名(⇧⌘F)、类方法名称(⇧⌘O)搜索。

    2.4. Bytecode-Viewer

    FernFlower提供了GUI版本,Bytecode-Viewer提供了直接反编译的classjar、、apkdex功能,直接拖拽jar就可以直接对整个jar进行反编译了。

    2.5. Find命令

    2.6 使用Find命令和Fernflower实现批量反编译jar

    当我们只有项目war包且源码经过打包后发布到WEB-INF/lib的情况下,我们不得不去找出待审计源码的具体jar文件并反编译。遇到这种情况我们可以巧妙的使用find命令来反编译所有目标的jar包。

    这里以jcms的一个非常老版本为例,jcms最终给客户部署的war包中源码并不是在WEB-INF/classes目录下,而是将整个jcms系统按模块打包成了多个jar包放在了WEB-INF/lib目录下。我们可以通过搜索com.hanweb包名称来找出所有jar中包含了jcms的文件并通过Fernflower来反编译。

    1. java -jar /Users/yz/Desktop/javaweb-decomplier/javaweb-decomplier.jar -dgs=1 $(find /Users/yz/Desktop/jcms/WEB-INF/lib/ -type f -name "*.jar" |xargs grep "com.hanweb" |awk '{print $3}') /Users/yz/jcms-decomplier

    执行上面的命令后会在jcms-decomplier目录下看到所有的jar已经被Fernflower反编译了。

    4.2

    依赖的jar: javaweb-decomplier、。

    IntelliJ IDEA是出品的一款非常强大的Java IDE,IDEA提供了强大的代码搜索、近乎完美的反编译、动态调试等功能可以最大程度的辅助我们代码审计。

    不可以否认,与IDEA相比虽然Eclipse和Netbeans也有与之类似的功能,但是在真正的实战体验中个人更倾向于使用IDEA,虽然曾经的我也是一个重度Eclipse开发者。