基于第一届长城杯Java-Patch学习
前言
基于第一届长城杯中AWD部分的DocToolKit题目研究,反编译jar包之后发现存在shiro组件
META-INF/maven/com.example/DocToolkit/pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.13.0</version>
</dependency>

查找shiro配置文件
com.example.doctoolkit.shiro.ShiroConfig
@Bean
RememberMeManager cookieRememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCipherKey(Base64.getDecoder().decode("QZIysgMYhG7/CzIJlVpR1g=="));
return cookieRememberMeManager;
}
存在shirokey,接下来就是patch来修改这个jar包中的shirokey
利用Jar文件冷补丁的方法来进行Patch,具体步骤如下
环境说明
查看JAVA_HOME
┌──(kali㉿kali)-[~/桌面]
└─$ echo $JAVA_HOME
┌──(kali㉿kali)-[~/桌面]
└─$ java -version
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
openjdk version "17.0.9-ea" 2023-10-17
OpenJDK Runtime Environment (build 17.0.9-ea+6-Debian-1)
OpenJDK 64-Bit Server VM (build 17.0.9-ea+6-Debian-1, mixed mode, sharing)
┌──(kali㉿kali)-[~/桌面]
└─$ which java
/usr/bin/java
┌──(kali㉿kali)-[~/桌面]
└─$ ls -lrt /usr/bin/java
lrwxrwxrwx 1 root root 22 2022年 3月27日 /usr/bin/java -> /etc/alternatives/java
┌──(kali㉿kali)-[~/桌面]
└─$ ls -lrt /etc/alternatives/java
lrwxrwxrwx 1 root root 43 2023年 7月22日 /etc/alternatives/java -> /usr/lib/jvm/java-17-openjdk-amd64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
decompile.sh脚本,用于class转换成java文件,内容如下
#!/bin/bash
# 设置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文件
/usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar $CFR_JAR "$class_file" > "$class_dir/$class_name.java"
done
patch详细步骤
先解压jar文件到example目录
unzip web.jar -d example
可以看到都是class文件,第二步就是反编译
创建文件夹,并且复制class相关文件到目录中
mkdir -p src/main/java
cp -r example/BOOT-INF/classes/* src/main/java/
ls src/main/java/
bash decompile.sh
结果类似如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ bash decompile.sh
ShiroConfig
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
UserRealm
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ResourceConfiguration
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ExifParser
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
PDFParser
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Crypt
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ZipUtils
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
TestController
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
AdminController
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
PDFController
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
IndexController
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
ImageController
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
DocToolkitApplication
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
查看目录下,成功反编译
find src/main/java
结果如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ find src/main/java
src/main/java
src/main/java/static
src/main/java/static/images
src/main/java/static/images/banner.jpg
src/main/java/static/css
src/main/java/static/css/style_2.css
src/main/java/static/css/style.css
src/main/java/static/css/font-awesome.css
src/main/java/static/fonts
src/main/java/static/fonts/fontawesome-webfont.woff
src/main/java/static/fonts/fontawesome-webfont.svg
src/main/java/static/fonts/fontawesome-webfont.woff2
src/main/java/static/fonts/fontawesome-webfont.ttf
src/main/java/static/fonts/fontawesome-webfont.eot
src/main/java/static/fonts/FontAwesome.otf
src/main/java/com
src/main/java/com/example
src/main/java/com/example/doctoolkit
src/main/java/com/example/doctoolkit/shiro
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.class
src/main/java/com/example/doctoolkit/shiro/UserRealm.class
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java
src/main/java/com/example/doctoolkit/shiro/UserRealm.java
src/main/java/com/example/doctoolkit/ResourceConfiguration.class
src/main/java/com/example/doctoolkit/ResourceConfiguration.java
src/main/java/com/example/doctoolkit/parser
src/main/java/com/example/doctoolkit/parser/PDFParser.java
src/main/java/com/example/doctoolkit/parser/ExifParser.class
src/main/java/com/example/doctoolkit/parser/PDFParser.class
src/main/java/com/example/doctoolkit/parser/ExifParser.java
src/main/java/com/example/doctoolkit/utils
src/main/java/com/example/doctoolkit/utils/Crypt.java
src/main/java/com/example/doctoolkit/utils/ZipUtils.java
src/main/java/com/example/doctoolkit/utils/Crypt.class
src/main/java/com/example/doctoolkit/utils/ZipUtils.class
src/main/java/com/example/doctoolkit/DocToolkitApplication.java
src/main/java/com/example/doctoolkit/controller
src/main/java/com/example/doctoolkit/controller/test
src/main/java/com/example/doctoolkit/controller/test/TestController.java
src/main/java/com/example/doctoolkit/controller/test/TestController.class
src/main/java/com/example/doctoolkit/controller/admin
src/main/java/com/example/doctoolkit/controller/admin/AdminController.class
src/main/java/com/example/doctoolkit/controller/admin/AdminController.java
src/main/java/com/example/doctoolkit/controller/user
src/main/java/com/example/doctoolkit/controller/user/PDFController.class
src/main/java/com/example/doctoolkit/controller/user/IndexController.java
src/main/java/com/example/doctoolkit/controller/user/ImageController.java
src/main/java/com/example/doctoolkit/controller/user/IndexController.class
src/main/java/com/example/doctoolkit/controller/user/ImageController.class
src/main/java/com/example/doctoolkit/controller/user/PDFController.java
src/main/java/com/example/doctoolkit/DocToolkitApplication.class
src/main/java/templates
src/main/java/templates/select.html
src/main/java/templates/upload.html
src/main/java/templates/login.html
src/main/java/templates/admin.html
src/main/java/templates/display.html
src/main/java/templates/loginFailed.html
src/main/java/application.properties
找到shirokey的java文件
└─$ cat src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java
/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* org.apache.shiro.mgt.RememberMeManager
* org.apache.shiro.mgt.SecurityManager
* org.apache.shiro.realm.Realm
* org.apache.shiro.spring.web.ShiroFilterFactoryBean
* org.apache.shiro.web.mgt.CookieRememberMeManager
* org.apache.shiro.web.mgt.DefaultWebSecurityManager
* org.springframework.context.annotation.Bean
* org.springframework.context.annotation.Configuration
*/
package com.example.doctoolkit.shiro;
import com.example.doctoolkit.shiro.UserRealm;
import java.util.Base64;
import java.util.LinkedHashMap;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ShiroConfig {
@Bean
public UserRealm getRealm() {
return new UserRealm();
}
@Bean
RememberMeManager cookieRememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCipherKey(Base64.getDecoder().decode("QZIysgMYhG7/CzIJlVpR1g=="));
return cookieRememberMeManager;
}
@Bean
SecurityManager securityManager(UserRealm userRealm, RememberMeManager cookieRememberMeManager) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm((Realm)userRealm);
manager.setRememberMeManager(cookieRememberMeManager);
return manager;
}
@Bean
public ShiroFilterFactoryBean ShiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/admin/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/admin/loginFailed");
LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
filterMap.put("/admin/login", "anon");
filterMap.put("/admin/doLogin", "anon");
filterMap.put("/admin/loginFailed", "anon");
filterMap.put("/admin/home", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
}
找到依赖目录
find example/BOOT-INF/lib
结果如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ find example/BOOT-INF/lib
example/BOOT-INF/lib
example/BOOT-INF/lib/tomcat-embed-el-9.0.68.jar
example/BOOT-INF/lib/thymeleaf-spring5-3.0.15.RELEASE.jar
example/BOOT-INF/lib/log4j-api-2.17.2.jar
example/BOOT-INF/lib/commons-collections-3.2.2.jar
example/BOOT-INF/lib/shiro-event-1.13.0.jar
example/BOOT-INF/lib/shiro-crypto-core-1.13.0.jar
example/BOOT-INF/lib/spring-boot-jarmode-layertools-2.6.13.jar
example/BOOT-INF/lib/logback-core-1.2.11.jar
example/BOOT-INF/lib/spring-context-5.3.23.jar
example/BOOT-INF/lib/pdfbox-2.0.30.jar
example/BOOT-INF/lib/encoder-1.2.3.jar
example/BOOT-INF/lib/metadata-extractor-2.19.0.jar
example/BOOT-INF/lib/shiro-web-1.13.0.jar
example/BOOT-INF/lib/tomcat-embed-websocket-9.0.68.jar
example/BOOT-INF/lib/spring-aop-5.3.23.jar
example/BOOT-INF/lib/spring-jcl-5.3.23.jar
example/BOOT-INF/lib/jackson-annotations-2.13.4.jar
example/BOOT-INF/lib/xmpcore-6.1.11.jar
example/BOOT-INF/lib/jul-to-slf4j-1.7.36.jar
example/BOOT-INF/lib/spring-expression-5.3.23.jar
example/BOOT-INF/lib/shiro-lang-1.13.0.jar
example/BOOT-INF/lib/jackson-core-2.13.4.jar
example/BOOT-INF/lib/tomcat-embed-core-9.0.68.jar
example/BOOT-INF/lib/shiro-config-ogdl-1.13.0.jar
example/BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar
example/BOOT-INF/lib/spring-web-5.3.23.jar
example/BOOT-INF/lib/thymeleaf-extras-java8time-3.0.4.RELEASE.jar
example/BOOT-INF/lib/spring-webmvc-5.3.23.jar
example/BOOT-INF/lib/attoparser-2.0.5.RELEASE.jar
example/BOOT-INF/lib/commons-beanutils-1.9.4.jar
example/BOOT-INF/lib/shiro-crypto-hash-1.13.0.jar
example/BOOT-INF/lib/shiro-config-core-1.13.0.jar
example/BOOT-INF/lib/log4j-to-slf4j-2.17.2.jar
example/BOOT-INF/lib/shiro-spring-1.13.0.jar
example/BOOT-INF/lib/fontbox-2.0.30.jar
example/BOOT-INF/lib/slf4j-api-1.7.36.jar
example/BOOT-INF/lib/spring-core-5.3.23.jar
example/BOOT-INF/lib/shiro-crypto-cipher-1.13.0.jar
example/BOOT-INF/lib/thymeleaf-3.0.15.RELEASE.jar
example/BOOT-INF/lib/spring-boot-autoconfigure-2.6.13.jar
example/BOOT-INF/lib/shiro-core-1.13.0.jar
example/BOOT-INF/lib/snakeyaml-1.29.jar
example/BOOT-INF/lib/jackson-datatype-jsr310-2.13.4.jar
example/BOOT-INF/lib/logback-classic-1.2.11.jar
example/BOOT-INF/lib/jackson-datatype-jdk8-2.13.4.jar
example/BOOT-INF/lib/unbescape-1.1.6.RELEASE.jar
example/BOOT-INF/lib/jackson-databind-2.13.4.2.jar
example/BOOT-INF/lib/commons-logging-1.2.jar
example/BOOT-INF/lib/spring-beans-5.3.23.jar
example/BOOT-INF/lib/jackson-module-parameter-names-2.13.4.jar
example/BOOT-INF/lib/spring-boot-2.6.13.jar
example/BOOT-INF/lib/shiro-cache-1.13.0.jar
现在修改java文件中的shirokey值
vim src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java
然后打包
CLASS_LIB=$(find example/BOOT-INF/lib/ -name "*.jar" | tr '\n' ':');
/usr/lib/jvm/java-17-openjdk-amd64/bin/javac -cp ".:${CLASS_LIB%:}" src/main/java/com/yeqifu/sys/controller/FileController.java
src/main/java/com/yeqifu/sys/common/AppFileUtils.java
执行结果如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ /usr/lib/jvm/java-17-openjdk-amd64/bin/javac -cp ".:${CLASS_LIB%:}" src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java:16: 错误: 找不到符号
import com.example.doctoolkit.shiro.UserRealm;
^
符号: 类 UserRealm
位置: 程序包 com.example.doctoolkit.shiro
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java:31: 错误: 找不到符号
public UserRealm getRealm() {
^
符号: 类 UserRealm
位置: 类 ShiroConfig
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java:43: 错误: 找不到符号
SecurityManager securityManager(UserRealm userRealm, RememberMeManager cookieRememberMeManager) {
^
符号: 类 UserRealm
位置: 类 ShiroConfig
src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java:32: 错误: 找不到符号
return new UserRealm();
^
符号: 类 UserRealm
位置: 类 ShiroConfig
4 个错误
发生报错,把报错的这几个文件也一块打包编译
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ /usr/lib/jvm/java-17-openjdk-amd64/bin/javac -cp ".:${CLASS_LIB%:}" src/main/java/com/example/doctoolkit/shiro/ShiroConfig.java src/main/java/com/example/doctoolkit/shiro/UserRealm.java
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
src/main/java/com/example/doctoolkit/shiro/UserRealm.java:20: 错误: 程序包com.example.doctoolkit.controller.admin不存在
import com.example.doctoolkit.controller.admin.AdminController;
^
src/main/java/com/example/doctoolkit/shiro/UserRealm.java:41: 错误: 找不到符号
private static final Logger LOGGER = Logger.getLogger(AdminController.class.getName());
^
符号: 类 AdminController
位置: 类 UserRealm
2 个错误
再拉过来,一块
/usr/lib/jvm/java-17-openjdk-amd64/bin/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
/usr/lib/jvm/java-17-openjdk-amd64/bin/javac -cp ".:${CLASS_LIB%:}" /home/kali/桌面/Patch/src/main/java/com/example/ezjava/controller/LoginController.java /home/kali/桌面/Patch/src/main/java/com/example/ezjava/model/NoSQLDatabase.java
/home/kali/桌面/Patch/src/main/java/com/example/ezjava/util/getFlag.java
执行结果如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ /usr/lib/jvm/java-17-openjdk-amd64/bin/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
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
此时已经class文件生成了,可以看到修改时间,是一致的,因为对应的UserRealm、AdminController文件也会生成class文件。
ls -lsa src/main/java/com/example/doctoolkit/shiro/
执行结果如下
┌──(kali㉿kali)-[~/桌面/Patch]
└─$ ls -lsa src/main/java/com/example/ezjava/util/
总计 24
4 drwxr-xr-x 2 kali kali 4096 6月16日 11:31 .
4 drwxr-xr-x 6 kali kali 4096 6月16日 11:26 ..
4 -rw-r--r-- 1 kali kali 2187 6月16日 11:36 ShiroConfig.class
4 -rw-r--r-- 1 kali kali 2567 6月16日 11:31 ShiroConfig.java
4 -rw-r--r-- 1 kali kali 3896 6月16日 11:36 UserRealm.class
4 -rw-r--r-- 1 kali kali 3887 6月16日 11:26 UserRealm.java
重新打包,首先替换原有的class文件
cp ls -lsa src/main/java/com/example/ezjava/util/getFlag.class example/BOOT-INF/classes/com/example/ezjava/util/getFlag.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
然后开始正式打包,解压每一个嵌套的JAR文件到单独的目录中。
cd example
cd BOOT-INF/lib
for jar in *.jar; do
mkdir -p "../lib_unpacked/$jar"
cd "../lib_unpacked/$jar"
/usr/lib/jvm/java-17-openjdk-amd64/bin/jar -xvf "../../lib/$jar"
cd ../../lib
done
输出结果很长,就不粘贴截图了
重新打包嵌套的JAR文件
cd ../lib_unpacked
for dir in *; do
/usr/lib/jvm/java-17-openjdk-amd64/bin/jar -cvfM0 "../lib/$dir.jar" -C "$dir" .
done
输出结果很长,就不粘贴截图了
重新打包主JAR文件
cd ..
cd ..
jar -cvfM0 ../example_repacked.jar -C . .
执行结果如下
┌──(kali㉿kali)-[~/…/Patch/example/BOOT-INF/lib_unpacked]
└─$ cd ../../&&pwd
/home/kali/桌面/Patch/example
jar -cvfM0 ../example_repacked.jar -C . .
输出结果很长,就不粘贴截图了
修改完成,反编译之后可以看到可以正常启动服务,并且shirokey已经发生变化

结束
至此,java题目patch的方法就是这样,对于jar包patch,这样基本可以最快时间的修复好,对于tar包,更简单,直接java修好再打包成tar包即可。