概述:
CFR(Class File Reader) 可以支持 Java 9、Java 12、Java 14 以及其他的最新版 Java 代码的反编译工作。而且 CFR 本身的代码是由 Java 6 编写,所以基本可以使用 CFR 在任何版本的 Java 程序中。值得一提的是,使用 CFR 甚至可以将使用其他语言编写的的 JVM 类文件反编译回 Java 文件。
demo :
Main.main(new String[] {
clazzPath,
"--outputdir",
SystemInfo.WORK_SPACE
});
反编译Class文件
详情请看:CrfUtils
反编译lamdba 一
public class ExeLamdab {
public void run(LamdbaInterface<String, String> lamdbaInterface) throws UnmodifiableClassException {
String world = lamdbaInterface.invote("world");
final Class[] allLoadedClasses = InstrumentationUtil.INSTANCE().getAllLoadedClasses();
//输出字节码文件
ClassFileTransformer extractor = new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> cls, ProtectionDomain pd, byte[] classBytes) {
if (null != classBytes) {
try {
File tmpFile = new File(SystemInfo.WORK_SPACE + File.separator + className.replace('.', '/') + ".class");
if (!tmpFile.exists()) {
String parent = tmpFile.getParent();
File file = new File(parent);
if (!file.exists()) {
file.mkdirs();
}
tmpFile.createNewFile();
}
FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
fileOutputStream.write(classBytes);
fileOutputStream.flush();
String clazzName = className.replaceAll("/", ".");
System.out.println(String.format("[FRIDAY] dump class: %s -> %s", clazzName, tmpFile.getAbsolutePath()));
} catch (Throwable e) {
System.out.println(String.format("[FRIDAY] dump class: %s error %s", className, e.getMessage()));
}
}
return classBytes;
}
};
//添加transformer
InstrumentationUtil.INSTANCE().addTransformer(extractor, true);
for (Class clazz : allLoadedClasses) {
if(clazz.getName().equals(lamdbaInterface.getClass().getName())){
InstrumentationUtil.INSTANCE().retransformClasses(clazz);
}
}
}
}
java -jar cfr.jar --help
org.benf.cfr.reader.util.getopt.OptionsImpl
| 选项 | 描述 | (类型)默认值 |
|---|---|---|
| --aexagg | (boolean) | |
| --aexagg2 | (boolean) | |
| --aggressivedocopy | (int >= 0) default: 0 | |
| --aggressivedoextension | (boolean) | |
| --aggressiveduff | (boolean) | |
| --aggressivesizethreshold | 通过积极应用语义安全但有破坏性的转换例如删除忽略的存储来简化静态分配分析,从而更好地处理巨大的代码块 | (int >= 0) default: 13000 |
| --allowcorrecting | (boolean) default: true | |
| --allowmalformedswitch | (boolean) | |
| --analyseas | (One of [DETECT, JAR, WAR, CLASS]) | |
| --antiobf | 处理基本整数例如 /0控制流混淆 | (boolean) default: false |
| --arrayiter | 不反编译出变长参数的语法糖实现 | (boolean) default: true if class file from version 49.0 (Java 5) or greater |
| --caseinsensitivefs | (boolean) default: true | |
| --clobber | 避免覆盖文件 | (boolean) |
| --collectioniter | 不反编译出增强 for 循环的语法糖实现 | (boolean) default: true if class file from version 49.0 (Java 5) or greater |
| --commentmonitors | (boolean) default: false | |
| --comments | 输出调整 - 每个方法注释块、类注释等 | (boolean) default: true |
| --constobf | 折叠反编译的常量表达式 | (boolean) default: Value of option ‘antiobf’ |
| --decodeenumswitch | 不反编译出switch-on-enum的语法糖实现 | (boolean) default: true if class file from version 49.0 (Java 5) or greater |
| --decodefinally | 不反编译出finally的语法糖实现 | (boolean) default: true |
| --decodelambdas | 不反编译出lambda的语法糖实现 | (boolean) default: true if class file from version 52.0 (Java 8) or greater |
| --decodestringswitch | 不反编译出switch-on-string的语法糖实现 | (boolean) default: true if class file from version 51.0 (Java 7) or greater |
| --dumpclasspath | Dump class path for debugging purposes | (boolean) default: false |
| --eclipse | 允许禁用规范化 eclipse 输出的转换 | (boolean) default: true |
| --elidescala | 通过删除 serialVersionUID 和 ScalaSignature 可能对其他语言有帮助使阅读反编译的 scala 更容易 | (boolean) default: false |
| --extraclasspath | 允许搜索 helper jar 进行分析 | (string) |
| --forbidanonymousclasses | (boolean) default: false | |
| --forbidmethodscopedclasses | (boolean) default: false | |
| --forceclassfilever | (string, specifying either java version as ‘j6’, ‘j1.0’, or classfile as ‘56’, ‘56.65535’) | |
| --forcecondpropagate | (boolean) | |
| --forceexceptionprune | 积极的异常剥离 - 删除无意义的异常块以获得更清晰的代码 | (boolean) |
| --forcereturningifs | (boolean) | |
| --forcetopsort | 当代码看起来不正确时添加了一种激进的拓扑排序,改进了 dex2jar 输出 | (boolean) |
| --forcetopsortaggress | (boolean) | |
| --forcetopsortnopull | (boolean) | |
| --forloopaggcapture | 允许循环捕获多个更新 | (boolean) |
| --hidebridgemethods | (boolean) default: Value of option ‘obfattr’ | |
| --hidelangimports | 隐藏 java.lang 导入 | (boolean) default: true |
| --hidelongstrings | (boolean) default: false | |
| --hideutf | 解码 unicode 文字 Hide UTF8 characters - quote them instead of showing the raw characters | (boolean) default: true |
| --ignoreexceptions | 忽略异常当异常表非常混乱以至于无法检索到任何有意义的内容时,这很有用 | (boolean) default: false |
| --ignoreexceptionsalways | (boolean) default: false | |
| --importfilter | (string) | |
| --innerclasses | 反编译内部类 | (boolean) default: true |
| --instanceofpattern | 反编译instanceof 模板 | (boolean) default: true if class file from version 60.0 (Java 16) or greater, or experimental in 58.0 (Java 14), 59.0 (Java 15) |
| --j14classobj | 不反编译出类常量的初始化 | (boolean) default: false if class file from version 49.0 (Java 5) or greater |
| --jarfilter | 允许 jar 处理采用正则表达式提取哪些类 | (string) |
| --labelledblocks | (boolean) default: true | |
| --lenient | 允许对奇怪排序的异常处理程序进行排序 | (boolean) default: false |
| --liftconstructorinit | 不反编译出类变量的初始化 | (boolean) default: true |
| --lomem | (boolean) default: false | |
| --methodname | Name of method to analyse | (string) |
| --obfattr | (boolean) default: Value of option ‘antiobf’ | |
| --obfcontrol | (boolean) default: Value of option ‘antiobf’ | |
| --obfuscationpath | 支持反混淆映射文件 | (string) |
| --outputdir | Decompile to files in [directory] (= options 'outputpath' + 'clobber') (historic compatibility) | (string) |
| --outputencoding | (string) | |
| --outputpath | (string) | |
| --override | 生成 @Override 注释 | (boolean) default: true if class file from version 50.0 (Java 6) or greater |
| --previewfeatures | (boolean) default: true | |
| --pullcodecase | (boolean) default: false | |
| --recordtypes | 不反编译出record的语法糖实现 | (boolean) default: true if class file from version 60.0 (Java 16) or greater, or experimental in 58.0 (Java 14), 59.0 (Java 15) |
| --recover | 在反编译失败的情况下停止任何使用额外选项覆盖的尝试 | (boolean) default: true |
| --recovertypeclash | (boolean) | |
| --recovertypehints | (boolean) | |
| --reducecondscope | (boolean) | |
| --relinkconst | (boolean) default: true | |
| --relinkconststring | 用猜测的源静态最终替换字符串常量 | (boolean) default: Value of option ‘relinkconst’ |
| --removebadgenerics | 不反编译出泛型的语法糖实现 | (boolean) default: true |
| --removeboilerplate | 不反编译出序列化时 lambda的语法糖实现 | (boolean) default: true |
| --removedeadconditionals | (boolean) | |
| --removedeadmethods | (boolean) default: true | |
| --removeinnerclasssynthetics | 不反编译出内部类的语法糖实现 | (boolean) default: true |
| --rename | (boolean) default: false | |
| --renamedupmembers | (boolean) default: Value of option ‘rename’ | |
| --renameenumidents | (boolean) default: Value of option ‘rename’ | |
| --renameillegalidents | (boolean) default: Value of option ‘rename’ | |
| --renamesmallmembers | (int >= 0) default: 0 | |
| --sealed | 支持密封类 | (boolean) default: true if class file from version 62.0 (Java 18) or greater, or experimental in 60.0 (Java 16), 61.0 (Java 17) |
| --showinferrable | (boolean) default: false if class file from version 51.0 (Java 7) or greater | |
| --showversion | (boolean) default: true | |
| --silent | (boolean) default: false | |
| --skipbatchinnerclasses | When processing many files, skip inner classes, as they will be processed as part of outer classes anyway. If false, you will see inner classes as separate entities also. | (boolean) default: true |
| --staticinitreturn | (boolean) default: true | |
| --stringbuffer | 反编译出【JDK 5-】 + 的语法糖实现 | (boolean) default: false if class file from version 49.0 (Java 5) or greater |
| --stringbuilder | 不反编译出【JDK 8-】 + 的语法糖实现 | (boolean) default: true if class file from version 49.0 (Java 5) or greater |
| --stringconcat | 不反编译出【JDK 9+】 + 的语法糖实现 | (boolean) default: true if class file from version 53.0 (Java 9) or greater |
| --sugarasserts | 不反编译出断言的语法糖实现 | (boolean) default: true |
| --sugarboxing | 不反编译出自动装箱/拆箱的语法糖实现 | (boolean) default: true |
| --sugarenums | 不反编译出枚举的语法糖实现 | (boolean) default: true if class file from version 49.0 (Java 5) or greater |
| --sugarretrolambda | (boolean) default: false | |
| --switchexpression | 反编译switch 表达式 | (boolean) default: true if class file from version 58.0 (Java 14) or greater, or experimental in 56.0 (Java 12), 57.0 (Java 13) |
| --tidymonitors | (boolean) default: true | |
| --trackbytecodeloc | Propagate bytecode location info. | (boolean) default: false |
| --tryresources | 不反编译出try-with-resources的语法糖实现 | (boolean) default: true if class file from version 51.0 (Java 7) or greater |
| --usenametable | (boolean) default: true | |
| --usesignatures | (boolean) default: true | |
| --version | CFR 的版本号 | (boolean) default: true |
| --help | 帮助 | (string) |
参考:
github地址:github.com/leibnitz27/…
官网地址:www.benf.org/other/cfr/j…
反编译方案对比:www.wdbyte.com/2021/05/jav…