背景


有时候需要研究某个jar类库某个功能的实现逻辑,或者在没有源码的情况下,紧急修复某个bug的时候,需要对jar进行反编译修改。


 


反编译基础知识


Kindle书:Java虚拟机字节码:从入门到实战


GitHub教程: https://github.com/Col-E/Recaf/blob/master/PRIMER.md


字节码指令介绍: http://www.blogjava.net/DLevin/archive/2011/09/13/358497.html


 


反编译工具

Recaf【推荐:5星】


github: https://github.com/Col-E/Recaf


Recaf是易于使用的现代Java字节码编辑器,支持三种反编译器,可直接编辑字节码,并对反编译的代码重新编译。


支持Jar或class


编辑字节码后自动更新StackMapTable


Tips:字节码编辑后,有时候需要按多次Ctrl+S才会保存。


 


JD-Gui(Java Decompiler)


github:  https://github.com/java-decompiler/jd-gui


快速反编译,点击函数或变量转到定义。


支持Jar或class


缺点:


不支持字节码编辑


 


JByteMod


github: https://github.com/GraxCode/JByteMod-Beta


支持三种反编译器


支持字节码有限编辑(不能自由编辑)


编辑最大操作栈大小、本地变量表大小、异常表


可以生成函数调用逻辑图


缺点:


反编译后的代码不支持转到定义


字节码编辑使用不太方便


 


JBE(Java Bytecode Editor)


网站: https://set.ee/jbe/


直观方便地编辑字节码


编辑最大操作栈大小、本地变量表大小、异常表


缺点:


未开源


不支持反编译


字节码保存后未自动更新StackMapTable,会出现VerifyError


只能修改class文件,不能打开jar文件


 


反编译逆向思路


如果想修改jar中的某个部分的逻辑,可以有很多方法:


已确定修改位置:


  1. 反编译jar包,修改方法,重新编辑jar
  2. 直接定位到方法的字节码,修改字节码,导出jar

不确定修改位置:


  1. 构造数据调用外部方法,触发异常,根据异常堆栈确定修改位置
  2. 反编译后,搜索关键字符串,定位修改位置
  3. 反编译后,根据入口函数逐步分析逻辑,定位关键位置(如果有混淆则比较困难)

重新打包为jar


如果将jar解压后修改的class文件,可执行下面命令重新打包为jar:(直接用工具编辑jar不需要执行此步骤)


jar cvfM  name-2.4.1.jar ./

jar命令格式:jar {c t x u f }[ v m e 0 M i ][-C 目录]文件名...
其中{ctxu}这四个参数必须选选其一。[v f m e 0 M i ]是可选参数,文件名也是必须的。
 
-c  创建一个jar包
-t 显示jar中的内容列表
-x 解压jar包
-u 添加文件到jar包中
-f 指定jar包的文件名
-v  生成详细的报造,并输出至标准设备
-m 指定manifest.mf文件.(manifest.mf文件中可以对jar包及其中的内容作一些一设置)
-0 产生jar包时不对其中的内容进行压缩处理
-M 不产生所有文件的清单文件(Manifest.mf)。这个参数与忽略掉-m参数的设置
-i    为指定的jar文件创建索引文件
-C 表示转到相应的目录下执行jar命令,相当于cd到那个目录,然后不带-C执行jar命令