Java反编译及工具的使用

Java反编译工具

反编译工具

javap 反编译出来的并不是我们熟知的java代码,只有特殊需要的时候才用它

jad 很久不更新了,没办法反编译JDK8的lambda表达式

cfr 语法稍复杂点,但是可以用,今天来学习使用cfr

cfr(cfr-0.151.jar)

下载地址 http://www.benf.org/other/cfr/

使用命令 java -jar cfr-0.151.jar --help 获取帮助文档

使用命令java -jar cfr-0.151.jar --help sugarboxing 查看命令的详细信息

参数一览
java -jar cfr-0.151.jar --help
CFR 0.151

   --aexagg                         (boolean)
   --aexagg2                        (boolean)
   --aggressivedocopy               (int >= 0)  default: 0
   --aggressivedoextension          (boolean)
   --aggressiveduff                 (boolean)
   --aggressivesizethreshold        (int >= 0)  default: 15000
   --allowcorrecting                (boolean)  default: true
   --allowmalformedswitch           (boolean)
   --analyseas                      (One of [DETECT, JAR, WAR, CLASS])
   --antiobf                        (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                 (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               (boolean)  default: true if class file from version 49.0 (Java 5) or greater
   --decodefinally                  (boolean)  default: true
   --decodelambdas                  (boolean)  default: true if class file from version 52.0 (Java 8) or greater
   --decodestringswitch             (boolean)  default: true if class file from version 51.0 (Java 7) or greater
   --dumpclasspath                  (boolean)  default: false
   --eclipse                        (boolean)  default: true
   --elidescala                     (boolean)  default: false
   --extraclasspath                 (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                   (boolean)
   --forcetopsortaggress            (boolean)
   --forcetopsortnopull             (boolean)
   --forloopaggcapture              (boolean)
   --hidebridgemethods              (boolean)  default: Value of option 'obfattr'
   --hidelangimports                (boolean)  default: true
   --hidelongstrings                (boolean)  default: false
   --hideutf                        (boolean)  default: true
   --ignoreexceptions               (boolean)  default: false
   --ignoreexceptionsalways         (boolean)  default: false
   --importfilter                   (string)
   --innerclasses                   (boolean)  default: true
   --instanceofpattern              (boolean)  default: true if class file from version 58.0 (Java 14) or greater, or experimental in 58.0 (Java 14)
   --j14classobj                    (boolean)  default: false if class file from version 49.0 (Java 5) or greater
   --jarfilter                      (string)
   --labelledblocks                 (boolean)  default: true
   --lenient                        (boolean)  default: false
   --liftconstructorinit            (boolean)  default: true
   --lomem                          (boolean)  default: false
   --methodname                     (string)
   --obfattr                        (boolean)  default: Value of option 'antiobf'
   --obfcontrol                     (boolean)  default: Value of option 'antiobf'
   --obfuscationpath                (string)
   --outputdir                      (string)
   --outputpath                     (string)
   --override                       (boolean)  default: true if class file from version 50.0 (Java 6) or greater
   --previewfeatures                (boolean)  default: true
   --pullcodecase                   (boolean)  default: false
   --recordtypes                    (boolean)  default: true if class file from version 58.0 (Java 14) or greater, or experimental in 58.0 (Java 14)
   --recover                        (boolean)  default: true
   --recovertypeclash               (boolean)
   --recovertypehints               (boolean)
   --reducecondscope                (boolean)
   --relinkconststring              (boolean)  default: true
   --removebadgenerics              (boolean)  default: true
   --removeboilerplate              (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
   --showinferrable                 (boolean)  default: false if class file from version 51.0 (Java 7) or greater
   --showversion                    (boolean)  default: true
   --silent                         (boolean)  default: false
   --skipbatchinnerclasses          (boolean)  default: true
   --staticinitreturn               (boolean)  default: true
   --stringbuffer                   (boolean)  default: false if class file from version 49.0 (Java 5) or greater
   --stringbuilder                  (boolean)  default: true if class file from version 49.0 (Java 5) or greater
   --stringconcat                   (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
   --switchexpression               (boolean)  default: true if class file from version 57.0 (Java 13) or greater, or experimental in 56.0 (Java 12)
   --tidymonitors                   (boolean)  default: true
   --trackbytecodeloc               (boolean)  default: false
   --tryresources                   (boolean)  default: true if class file from version 51.0 (Java 7) or greater
   --usenametable                   (boolean)  default: true
   --usesignatures                  (boolean)  default: true
   --help                           (string)

Please specify '--help optionname' for specifics, eg
   --help pullcodecase
常用的参数
–decodeenumswitch

(boolean) default: true if class file from version 49.0 (Java 5) or greater

public class Cfr {
    public void testEnumSwitch(CfrEnum p) {
        switch (p) {
            case AAA:
                System.out.println("print AAA");
                break;
            case BBB:
                System.out.println("print BBB");
                break;
            case CCC:
                System.out.println("print CCC");
                break;
            default:
                System.out.println("print nothing");
                break;
        }
    }
}

接下来,我们使用命令 java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class进行反编译

E:\>java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class
/*
 * Decompiled with CFR 0.151.
 */
public class Cfr {
    public void testEnumSwitch(CfrEnum p) {
        switch (p) {
            case AAA: {
                System.out.println("print AAA");
                break;
            }
            case BBB: {
                System.out.println("print BBB");
                break;
            }
            case CCC: {
                System.out.println("print CCC");
                break;
            }
            default: {
                System.out.println("print nothing");
            }
        }
    }
}

我们使用命令 java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class --decodeenumswitch false再试一下

E:\>java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class --decodeenumswitch false
/*
 * Decompiled with CFR 0.151.
 */
public class Cfr {
    public void testEnumSwitch(CfrEnum p) {
        switch (1.$SwitchMap$CfrEnum[p.ordinal()]) {
            case 1: {
                System.out.println("print AAA");
                break;
            }
            case 2: {
                System.out.println("print BBB");
                break;
            }
            case 3: {
                System.out.println("print CCC");
                break;
            }
            default: {
                System.out.println("print nothing");
            }
        }
    }
}

这时候会发现,switch中的枚举不见了,变成数字 1、2、3,这就是java中的语法糖

  • 后续涉及到语法糖的参数将不再用代码举例,详细情况可以参考 《Java语法糖》
–decodelambdas

(boolean) default: true if class file from version 52.0 (Java 8) or greater

解 JDK8的lambda语法糖

–decodestringswitch

(boolean) default: true if class file from version 51.0 (Java 7) or greater

解 string-switch语法糖

–innerclasses

(boolean) default: true

示例代码

public class Cfr {
    public void outMethod() {

    }
    class InnerCfr {
        public void innerMethod() {

        }
    }
}

编译后我们将得到 Cfr.class 和 Cfr$InnerCfr.class两个.class文件

接下来,我们使用命令 java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class进行反编译

java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class
/*
 * Decompiled with CFR 0.151.
 */
public class Cfr {
    public void outMethod() {
    }

    class InnerCfr {
        InnerCfr() {
        }

        public void innerMethod() {
        }
    }
}

默认执行的–innerclasses的值为true,所以我能将得到内部类及内部方法,接下来将参数值改成false

E:\>java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class --innerclasses false
/*
 * Decompiled with CFR 0.151.
 */
public class Cfr {
    public void outMethod() {
    }
}

E:\>java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr$InnerCfr.class --innerclasses false
/*
 * Decompiled with CFR 0.151.
 */
class Cfr.InnerCfr {
    Cfr.InnerCfr() {
    }

    public void innerMethod() {
    }
}

不论是Cfr.clas还是Cfr$InnerCfr.class,我们都只得到当前反编译的类

–stringbuffer

(boolean) default: false if class file from version 49.0 (Java 5) or greater

java 1.5 之后被放弃了,用stringbuilder代替

–stringbuilder

(boolean) default: true if class file from version 49.0 (Java 5) 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

解枚举语法糖

常见用法
反编译单个文件

java -jar cfr的jar包路径 .class的路径

java -jar cfr-0.151.jar workspace/test/out/production/test/Cfr.class
反编译多个文件

java -jar cfr的jar包路径 第1个 .class的路径 第2个 .class的路径

java -jar cfr-0.151.jar workspace/test/out/production/test/Sugar.class workspace/test/out/production/test/SugarEnum.class
反编译jar包

java -jar cfr的jar包路径 java包的路径 --outputdir 反编译后的文件输出地址

java -jar cfr-0.151.jar E:/demo.jar --outputdir E:/cfrSource
参考资料

https://www.hollischuang.com/archives/58

http://www.benf.org/other/cfr/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值