Java打补丁修改Jar包

前言

当时打长城杯复赛的时候不会修Jar包,解压开了后面就不会弄了,导致虽然知道怎么改代码,但是后面让人一直被打扣分,正巧这几天看到了一个相关的教程,就学习一下。这里从长城杯复赛的jar文件测试(DocToolKit)。

冷补丁修改jar包-方法一

准备反编译所需要的jar文件:

然后使用decompile.sh脚本,批量转换class文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
# WSL运行
# 设置CFR JAR文件的路径
CFR_JAR="cfr-0.152.jar"
# 设置class文件的根目录
CLASS_ROOT="src/main/java"
# 查找所有的class文件并反编译为java文件
find $CLASS_ROOT -name "*.class" | while read class_file; do
# 获取class文件的目录和文件名
class_dir=$(dirname "$class_file")
class_name=$(basename "$class_file" .class)
echo $class_name
# 反编译class文件并将输出重定向到.java文件
java -jar $CFR_JAR "$class_file" > "$class_dir/$class_name.java"
done

先将jar文件解压到example目录中:

1
unzip DocToolkit-0.0.1-SNAPSHOT.jar -d example

再将class文件放入相关目录中:

1
2
mkdir -p src/main/java
cp -r example/BOOT-INF/classes/* src/main/java/

后面我们需要对src中的class文件修改,再移回example中。
我们根据硬编码进代码中的key测试一下。
image.png
正常其中的硬编码key是可以用的。
因此我们先需要修改它的key。

修改默认Key

先使用工具随便生成一个key:RGVq/DPil3pzwOkSngTz4g==
image.png
然后修改源码中的硬编码key值:src\main\java\com\example\doctoolkit\shiro\ShiroConfig.java
image.png
修改之后进行打包:

1
2
CLASS_LIB=$(find example/BOOT-INF/lib/ -name "*.jar" | tr '\n' ':');
javac -cp ".:${CLASS_LIB%:}" src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java

image.png
报错是需要对其他java文件一起编译:

1
javac -cp ".:${CLASS_LIB%:}" src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java src/main/java/com/example/doctoolkit/shiro/UserRealm.java src/main/java/com/example/doctoolkit/controller/admin/AdminController.java

image.png
这时就能看到新生成的class文件了。(注意时间)
image.png

重新打包

首先先替换原有的class文件:

1
2
3
cp src/main/java/com/example/doctoolkit/shiro/ShiroConfig.class example/BOOT-INF/classes/com/example/doctoolkit/shiro/ShiroConfig.class
cp src/main/java/com/example/doctoolkit/shiro/UserRealm.class example/BOOT-INF/classes/com/example/doctoolkit/shiro/UserRealm.class
cp src/main/java/com/example/doctoolkit/controller/admin/AdminController.class example/BOOT-INF/classes/com/example/doctoolkit/controller/admin/AdminController.class

然后打包,对lib中的每一个JAR文件都解压到目录中:

1
2
3
4
5
6
7
cd example/BOOT-INF/lib
for jar in *.jar; do
mkdir -p "../lib_unpacked/$jar"
cd "../lib_unpacked/$jar"
jar -xvf "../../lib/$jar"
cd ../../lib
done

image.png
然后再重新打包lib中Jar文件

1
2
3
4
cd ../lib_unpacked
for dir in *; do
jar -cvfM0 "../lib/$dir.jar" -C "$dir" .
done

再打包主jar文件

1
2
3
cd ..
cd ..
jar -cvfM0 ../example_repacked.jar -C . .

运行测试新jar文件:
image.png
再测试新的key:RGVq/DPil3pzwOkSngTz4g==
image.png
新的key成功被检测出来。

冷补丁修改jar包-方法二

前面那个流程浪费了很长时间在解压和压缩jar包上。
这里用一点点简单的方法来缩短时间。

按照要求,先配置使用配置:config.py
java的绝对路径、jar包的位置。

1
2
3
javaPath = r"D:\Workstation\Env\Java\jdk-17.0.1\bin\java.exe" #请填写java绝对路径 
jarPath = "DocToolkit-0.0.1-SNAPSHOT.jar" #如果使用的是war包请先将后缀改为jar
copyConfig=True #是否将IDEA配置进行复制

然后记得运行这个jar包Java8是不行的,我这里用Java17能运行。而且要在工作目录下创建一个target文件夹,否则会报错。下面这样就是正常运行的结果:
image.png
然后运行main.py即可。运行之后就生成了一个project文件夹,下面就是工作文件夹。
然后在idea中打开即可,但是这样并没有完全结束,需要进行手动配置:

  • 先是配置SDK和class导出位置(项目结构-项目):SDK选择你需要的SDK,然后将输出结果设置在out文件夹下。(这个我的打开idea会自动操作)

image.png

  • 设置项目代码(项目结构-模块):将src/main/java标记为源代码,如果没有当前模块,新建导入即可,然后按照图示将标记:

image.png

  • 设置依赖库(项目结构-库):如果已经存在也不要管直接再按照下面导入就行,然后选择目标目录下的lib文件夹。

image.png

  • 设置Jar包(项目结构-工件):添加jar包

image.png
image.png
主类选择时如果前面正常导入了的话,这里应该正常显示启动类,然后下面选择META-INF文件目录。然后就会自动提取出jar文件:
image.png
记得应用保存,然后修改对应java文件。
还是修改shiro的key:
image.png
然后Ctrl + F9构建项目。就发现根目录下设定好的out文件夹。
image.png
image.png
然后将编译好的class文件:ShiroConfig.class文件覆盖进jar包对应位置中。
image.png
image.png
修改时间变了就是已经覆盖成功。
然后运行测试一下:
image.png
key已经被成功修改。

热补丁修改jar包

这个据说用java-agent,但是现在还不会,没找到我能看懂的教程,后面再研究研究。