背景
有时候需要研究某个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)
直观方便地编辑字节码
编辑最大操作栈大小、本地变量表大小、异常表
缺点:
未开源
不支持反编译
字节码保存后未自动更新StackMapTable,会出现VerifyError
只能修改class文件,不能打开jar文件
反编译逆向思路
如果想修改jar中的某个部分的逻辑,可以有很多方法:
已确定修改位置:
- 反编译jar包,修改方法,重新编辑jar
- 直接定位到方法的字节码,修改字节码,导出jar
不确定修改位置:
- 构造数据调用外部方法,触发异常,根据异常堆栈确定修改位置
- 反编译后,搜索关键字符串,定位修改位置
- 反编译后,根据入口函数逐步分析逻辑,定位关键位置(如果有混淆则比较困难)
重新打包为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命令