• Java逆向系列-基础指令:常量入栈指令


                                      常量入栈指令

    Java程序的反编译工具已经十分成熟了,相对于x86平台更底层指令的反编译技术来说,面向VM的 bytecode更容易反编译。这主要是因为:

    1. 字节码含有更为丰富的数据类型信息。
    2. JVM内存模型更严格,因此字节码分析起来更为有章可循。
    3. Java编译器不做任何优化工作(而 JVM JIT在运行时会做优化工作),因此在反编译字节码之后,我们基本可以直接理解Java类文件里的原始指令。

    反编译有什么用途呢?

    1. 无需重新编译反汇编的结果,而能给类文件做应急补丁
    2. 分析混淆代码。
    3. 需要编写自己的代码混淆器。
    4. 创建面向JVM的、类似编译程序的代码生成工具(类似 Scala,Cloture等等)。
    5. 破解研究
       

    开启Java逆向学习系列笔记,参考网上各大神的分享,有不对的请指正。


    常量入栈指令有iconstbipushsipushldcldc2_w分别对应不同的使用场景

    八大基本类型场景表

    常量类型

    常量范围

    指令

    整型int

    -1~5

    iconst_0~ iconst_5

    iconst_m1

    -128~127

    bipush

    -32768~32767

    sipush

    -2147483648~2147483647

    #2 = Integer 12345678

    0: ldc #2 // int 12345678

    布尔型boolean

    true

    iconst_1

    false

    iconst_0

    短整型short

    -1~5

    iconst_0~ iconst_5

    iconst_m1

    -128~127

    bipush

    -32768~32767

    sipush

    字符型char

    u0000~u0005

    iconst_0~ iconst_5

    u0000~u00FF

    bipush

    u0000~uFFFF

    sipush

    字节型byte

    -1~5

    iconst_0~ iconst_5

    iconst_m1

    -128~127

    bipush

    长整型long

    -2^63~2^63-1

    #2 = Long 1234567890123456789l

    ldc2_w #2 // long 1234567890123456789l

    浮点型double

    8字节

    #2 = Double 123.456d

    ldc2_w  #2  // double 123.456d

    浮点型float

    4字节

    #2 = Float 123.456f

    ldc #2 // float 123.456f

    指令场景表

    指令

    使用场景

    iconst

    int,short,byte,int(char a)数值在-1~5之间,boolean类型,注意不包括long

    bipush

    int,short,byte,int(char a)数值在-128~127之间,注意不包括long,范围内的值在iconst之内的优先用iconst

    sipush

    int,short,int(char a)数值在-32768~32767之间,boolean类型,注意不包括long,范围内的值在bipush之内的优先用bipush

    ldc

    int的数值-2147483648~2147483647之间(范围内的值在sipush之内的优先用sipush),float类型

    ldc2_w

    long类型,double类型


    以下是简单的例子

    整型常量0的例子iconst

    public class ret
    {
    public static int main(String[] args)
    {
    return 0;
    }
    }

    编译

    javac ret.java

    Java标准反编译

    javap -c -verbose ret.class
    ...
    major version: 52
    ...
    public static int main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: iconst_0
    1: ireturn
    LineNumberTable:
    line 5: 0

    注意其中的0: iconst_0即可

    整型常量123的例子bipush

    public class ret
    {
    public static int main(String[] args)
    {
    return 123;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static int main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: bipush        123
    2: ireturn
    LineNumberTable:
    line 5: 0

    注意其中的0: bipush        123

    整型常量1234的例子sipush

    public class ret
    {
    public static int main(String[] args)
    {
    return 1234;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static int main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: sipush        1234
    3: ireturn
    LineNumberTable:
    line 5: 0

    注意其中的 0: sipush        1234

    整型常量12345678的例子ldc

    public class ret
    {
    public static int main(String[] args)
    {
    return 12345678;
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Integer            12345678
    ...
    public static int main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: ldc           #2                  // int 12345678
    2: ireturn
    LineNumberTable:
    line 5: 0

    布尔型true例子iconst

    public class ret
    {
    public static boolean main(String[] args)
    {
    return true;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static boolean main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)Z
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: iconst_1
    1: ireturn
    LineNumberTable:
    line 5: 0

    注意0: iconst_1即ture用常量1表示

    短整型short例子

    public class ret
    {
    public static short main(String[] args)
    {
    return 1234;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static short main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)S
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: sipush        1234
    3: ireturn
    LineNumberTable:
    line 5: 0

    注意0: sipush        1234

    字符型A例子

    public class ret
    {
    public static char main(String[] args)
    {
    return 'A';
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static char main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)C
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: bipush        65
    2: ireturn
    LineNumberTable:
    line 5: 0

    注意0: bipush        65

    字符型中例子

    public class ret
    {
    public static char main(String[] args)
    {
    return '中';
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static char main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)C
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: sipush        20013
    3: ireturn
    LineNumberTable:
    line 5: 0

    注意0: sipush        20013

    byte类型123列子

    public class ret
    {
    public static byte main(String[] args)
    {
    return 123;
    }
    }

    反编译

    ...
    major version: 52
    ...
    public static byte main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)B
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: bipush        123
    2: ireturn
    LineNumberTable:
    line 5: 0

    注意 0: bipush        123

    long类型1234567890123456789L例子

    public class ret
    {
    public static long main(String[] args)
    {
    return 1234567890123456789l;
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Long               1234567890123456789l
    ...
    public static long main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)J
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=1, args_size=1
    0: ldc2_w        #2                  // long 1234567890123456789l
    3: lreturn
    LineNumberTable:
    line 5: 0

    注意0: ldc2_w        #2                  // long 1234567890123456789l

    浮点类型123.456d的例子

    public class ret
    {
    public static double main(String[] args)
    {
    return 123.456d;
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Double             123.456d
    ...
    public static double main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)D
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=1, args_size=1
    0: ldc2_w        #2                  // double 123.456d
    3: dreturn
    LineNumberTable:
    line 5: 0

    注意0: ldc2_w        #2                  // double 123.456d

    浮点类型123.456f的例子

    public class ret
    {
    public static float main(String[] args)
    {
    return 123.456f;
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Float              123.456f
    ...
    public static float main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)F
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: ldc           #2                  // float 123.456f
    2: freturn
    LineNumberTable:
    line 5: 0

    注意0: ldc           #2                  // float 123.456f

    本文参考:逆向工程权威指南.下册.pdf 和http://blog.51cto.com/7317859/2105269

  • 相关阅读:
    C++
    复盘-2018.6.8~2020.6.8
    C++
    C++
    C++
    C++
    Python学习笔记(十)- 面向对象(一)
    SSHException: Error reading SSH protocol banner
    docker 安装mysql
    docker 安装部署
  • 原文地址:https://www.cnblogs.com/llhl/p/9648613.html
Copyright © 2020-2023  润新知