Java 字节码逆向(CFR / JD-GUI / javap)
SkillFiles & storageLets your agent reverse engineer Java bytecode, unpack jar files, and decompile class files with CFR or JD-GUI.
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Java 字节码逆向(CFR / JD-GUI / javap) skill
About this skill
Java bytecode reverse engineering: CFR/JD-GUI, jar unpacking, Java hardening. Trigger words: Java, jar, bytecode, JD-GUI, CFR, class files
What this skill tells your AI
The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-java/SKILL.md and read by ahel’s review.
何时使用 / 何时不用
- 用:jar/war/class 样本还原 Java 逻辑;定位注册码/密钥/网络逻辑;处理 ProGuard/Allatori 混淆与 Java 加固
- 用:恶意 Java 样本([[re-malware]] → [[re-managed]] 路径)静态还原
- 不用:Android DEX 直接分析([[re-apk]];转成 jar 后可回本技能)
- 不用:非 Java(.NET 走 [[re-dotnet]]、脚本走 [[re-script-deob]]、native 走 [[re-binary-core]])
- 注意:动态步骤默认沙箱([[re-analyze/platform-tips]] 最高原则);解包产物先备份
工具准备
参考 [[re-analyze/platform-tips]]——反编译/解包为静态步骤,免沙箱;动态验证按最高原则进沙箱。
JDK(javap / jar / java 运行时)
- Debian/Ubuntu:
apt install openjdk-17-jdk - Fedora:
dnf install java-17-openjdk;Arch:pacman -S jdk17-openjdk - macOS:
brew install openjdk(或brew install --cask temurin) - Windows:
choco install temurin或官方安装器 - 验证:
java -version && javap -version
unzip(jar = zip 容器)
- Linux:
apt install unzip/dnf install unzip/pacman -S unzip;macOS:brew install unzip - 验证:
unzip -v
CFR(jar CLI 反编译器,零依赖)
- 下载(无依赖,只需 JRE):
curl -L -o cfr.jar https://www.benf.org/other/cfr/cfr-0.152.jar - 验证:
java -jar cfr.jar --help
JD-GUI(GUI 反编译器)
- GitHub
java-decompiler/jd-guirelease zip → 解压,Linux/macOS:java -jar jd-gui-1.6.6.jar(zip 内含各平台可执行) - 验证: GUI 启动并能
File > Open打开 jar
procyon(备选反编译器)
- Maven Central:
curl -L -o procyon-decompiler.jar https://repo1.maven.org/maven2/org/bitbucket/mstrobel/procyon-decompiler/0.6.0/procyon-decompiler-0.6.0.jar - 验证:
java -jar procyon-decompiler.jar --help
操作步骤
按顺序执行,每步记录证据(路径 + sha256,见 [[re-triage]])。
-
jar/war 解包:
jar tf app.jar # 先看清单(JDK 自带 jar 工具) unzip -o app.jar -d unpacked/ unzip -p app.jar META-INF/MANIFEST.MF # Main-Class / 加固标记- war: 类在
WEB-INF/classes/,依赖在WEB-INF/lib/ - fat jar(Spring Boot): 类在
BOOT-INF/classes/,嵌套依赖BOOT-INF/lib/*.jar需逐个解 - aar(Android): 内含
classes.jar,解出后再按本技能处理 - Multi-Release jar: 同路径多版本类在
META-INF/versions/N/(N=9/11/17…)下覆盖——运行时按 JDK 选版加载,逆向按目标 JDK 看对应层,别只看顶层
- war: 类在
-
类结构识别:
javap -c -p unpacked/com/example/Main.class # 字节码(-c)+ 私有成员(-p) javap -v unpacked/com/example/Main.class # 常量池/元数据- 找入口:MANIFEST.MF 的
Main-Class→javap -c -p <入口类>看 main 逻辑 - 混淆程序集先看类名是否可读(a/b/c → 步骤 4)
- class 文件头速查:
xxd -l 8 <类>.class→CA FE BA BE+ minor(2) + major(2);Java 版本 = major − 44(52=Java 8、55=11、61=17、65=21,实测 JDK 21 产物 major=65);javap -v首行直接打印 minor/major - 常量池:计数在 major 之后(u16,索引 0 占位),
javap -v列条目类型(String/Class/NameAndType/Methodref/Utf8 等)——字符串字面量、类名、签名全在常量池,混淆样本的明文串先在这里找
- 找入口:MANIFEST.MF 的
-
逻辑还原(CFR / JD-GUI):
java -jar cfr.jar app.jar --outputdir cfr_out/ # 整包还原为 Java 源码 java -jar cfr.jar unpacked/com/example/Main.class # 单类还原 java -jar procyon-decompiler.jar -jar app.jar -o procyon_out/ # 备选- JD-GUI:
File > Open→ 左侧树浏览 →File > Save All Sources导出 - 关键类/方法用两个反编译器交叉验证(CFR 对 lambda/现代字节码还原更好,JD-GUI 对老代码更顺)
- JD-GUI:
-
混淆识别与字符串解密:
- ProGuard: 类/方法名全变
a/b/c、javap -l无 LineNumberTable/LocalVariableTable(调试信息被剥) - Allatori: 反编译产物出现
com.allatori.*水印类、StringEncryptor调用(字符串加密) - ZKM(Zelix KlassMaster):
com.zelix.*类特征 - 检测:
grep -rn 'StringEncryptor\|decrypt(' cfr_out/ | head - 字符串加密处理:定位解密类与算法(key/变换方式)→ python3 复刻批量还原;或动态取明文(步骤 5,沙箱内)——先静态还原,静态卡住再动态
- ProGuard: 类/方法名全变
-
动态(可选;沙箱内执行 [[re-sandbox]]):
- JDB(桌面 JVM):
jdb -classpath app.jar com.example.Main > stop in com.example.Main.checkKey # 下断点 > print key # 取变量 > eval new com.example.Util().decrypt("密文") # 直接调用解密方法取明文 - Frida(Android Java 应用,转 [[re-mobile]]/[[re-apk]] 域):
Java.perform(function () { var c = Java.use("com.example.Main"); c.checkKey.implementation = function (k) { console.log("key = " + k); return this.checkKey(k); }; }); - 桌面 JVM 无 Frida Java API → 用 JDB / 自写 Java agent
- JDB(桌面 JVM):
跨域联合
- [[re-managed]]:网关工作流步骤②(反编译)③(去混淆)固定调用本技能
- [[re-malware]]:Java 恶意样本路径(re-malware → re-managed → 本技能静态还原)
- Android 侧:[[re-apk]] / [[re-mobile]](DEX 转 jar 后可回本技能);动态 [[re-frida]](Android)
- 底座 [[re-binary-core]]:初勘([[re-triage]]);native/JNI 部分
常见坑与陷阱
- ProGuard 改名后靠字符串交叉引用:现象——反编译全是
a/b/c类、a(...)方法,无法定位目标逻辑;原因——ProGuard shrink+obfuscate 重命名抹掉语义;对策——从字符串入手:grep 明文 URL/提示语 → 在反编译产物里找引用它的类(grep -rn "提示语" cfr_out/)→ 沿调用链恢复语义 - Allatori/字符串加密需先解密:现象——反编译只见
StringEncryptor.decrypt("...")调用,看不到任何明文;原因——字符串运行时才解密;对策——静态定位解密算法与 key → python3 复刻批量还原;或动态在解密调用后取明文(JDBeval/ Frida),沙箱内执行 - 反编译不完全正确:现象——CFR/JD-GUI 输出语法错误、goto/label 混乱、try-catch 结构诡异、lambda 还原失败;原因——字节码到 Java 不存在无损还原;对策——对照
javap -c -p字节码手工修正,多反编译器交叉验证 - Java 加固(如 Virbox)类似壳需先脱:现象——JD-GUI 打开报错/空白、
javap输出损坏、文件头非标准;原因——加固器加密 class 字节码、运行时才解密(本质是壳);对策——先脱加固:运行时 dump class(attach agent / 专用脱壳工具为主;-Xbootclasspath仅 JDK 8 可用,JDK 9+ 已移除该选项)→ 对脱出的标准 class 再反编译;思路同 [[re-anti-analysis]] 的"先脱壳后分析" - javap 报 unsupported class file version:现象——
javap报major version 65之类不支持;原因——class 文件版本高于本机 JDK 工具版本;对策——按 major−44 换算目标 Java 版本,装对应或更新的 JDK;只读版本与常量池可先用xxd手工看头字段,不必等工具 - Multi-Release jar 分析错层:现象——
unzip -o解出顶层类后反编译,逻辑与运行时行为不符(版本分支消失);原因——多版本类在META-INF/versions/N/,不同 JDK 加载不同层;对策——解包后检查META-INF/versions/,按目标 JDK 选层分析;顶层与 versions 层的差异就是版本条件逻辑 - lambda 反编译出现合成方法:现象——CFR/JD-GUI 输出
lambda$xxx$n方法或invokedynamic调用;原因——lambda 体编译为合成私有方法 + invokedynamic 引导;对策——javap -v -p的 BootstrapMethods 表定位 lambda 体方法(捕获变量在合成方法参数里),按普通方法分析即可
Signals
- GitHub stars
- 109
- Forks
- 16
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
re-java- Source
- github.com/dslsdzc/rev-skills