• Java逆向系列-基础指令:函数


    例子1,方法名的定义

    public class HalfRandom
    {
    public static double f()
    {
    return Math.random()/2;
    }
    }

    编译

    javac HalfRandom.java

    反编译

    javap -c -verbose HalfRandom.class
    ...
    major version: 52
    ...
    #2 = Methodref          #16.#17        // java/lang/Math.random:()D
    #3 = Double             2.0d
    ...
    #12 = Utf8               ()D
    ...
    #16 = Class              #20            // java/lang/Math
    #17 = NameAndType        #21:#12        // random:()D
    #18 = Utf8               HalfRandom
    #19 = Utf8               java/lang/Object
    #20 = Utf8               java/lang/Math
    #21 = Utf8               random
    ...
    public static double f();
    descriptor: ()D
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=4, locals=0, args_size=0
    0: invokestatic  #2                  // Method java/lang/Math.random:()D
    3: ldc2_w        #3                  // double 2.0d
    6: ddiv
    7: dreturn
    LineNumberTable:
    line 5: 0

    invokestatic  #2  调用常量#2定义的函数

    函数名定义在常量池的Methodref中,它定义类,方法名,方法返回类型

    常量#2中,可以看到它是由#16.#17拼接,#16定义了类名 java/lang/Math,#17是方法名和返回类型名random:()D

    常量#17中,它是由#21:#12拼接,#21定义了方法名random,#12定义了返回类型名()D

    ()D的解释 ,括号内没有东西表示括号内无参数,D表示返回类型为double,如果是V则为void

    这种方式

    1)JVM可以检查数据类型的正确性:

    2)java反编译器可以从被编译的类文件中修改数据类型。

    再看"hello,world!"的例子

    public class HelloWorld
    {
    public static void main(String[] args)
    {
    System.out.println("Hello, World");
    }
    }

    反编译

    ...
    major version: 52
    ...
    #2 = Fieldref           #16.#17        // java/lang/System.out:Ljava/io/PrintStream;
    #3 = String             #18            // Hello, World
    #4 = Methodref          #19.#20        // java/io/PrintStream.println:(Ljava/lang/String;)V
    ...
    #16 = Class              #23            // java/lang/System
    #17 = NameAndType        #24:#25        // out:Ljava/io/PrintStream;
    #18 = Utf8               Hello, World
    #19 = Class              #26            // java/io/PrintStream
    #20 = NameAndType        #27:#28        // println:(Ljava/lang/String;)V
    ...
    #23 = Utf8               java/lang/System
    #24 = Utf8               out
    #25 = Utf8               Ljava/io/PrintStream;
    #26 = Utf8               java/io/PrintStream
    #27 = Utf8               println
    #28 = Utf8               (Ljava/lang/String;)V
    ...
    public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=1, args_size=1
    0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    3: ldc           #3                  // String Hello, World
    5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    8: return
    LineNumberTable:
    line 5: 0
    line 6: 8

    getstatic  #2 获取System.out的引用入栈

    ldc  #3 将字符串Hello, World入栈

    invokevirtual #4 调用println()方法,这里需要传两个参数,参数从栈中获取,1先将Hello, World出栈传入(Ljava/lang/String;),2将System.out的引用出栈传入java/io/PrintStream的引用

    再看beep的函数调用(输出计算机报警的蜂鸣声)

    public class bee
    {
    public static void main(String[] args)
    	{
    		java.awt.Toolkit.getDefaultToolkit().beep();
    	}
    }

    反编译

    ...
    major version: 52
    ...
    public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=1, locals=1, args_size=1
    0: invokestatic  #2                  // Method java/awt/Toolkit.getDefaultToolkit:()Ljava/awt/Toolkit;
    3: invokevirtual #3                  // Method java/awt/Toolkit.beep:()V
    6: return
    LineNumberTable:
    line 5: 0
    line 6: 6

    invokestatic  #2 调用java.awt.Toolkit.getDefaultToolkit()方法并将返回结果的引用压入栈顶

    invokevirtual #3 调用beep()函数,其中需要传引用,把objectref从栈顶弹出传入java/awt/Toolkit

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

  • 相关阅读:
    批量编译当前目录下4gl文件
    oracle数据库查看表
    Oracle中授权(grant)和同义词(synonym)
    Oracle中的instr()函数 详解及应用
    T100的程序错误提示方法
    六种 主流ETL 工具的比较
    oracle恢复数据到某个时间点
    Oracle统计一个小时内,一天内、一个星期内、一个月内、一年内的数据
    Linux top命令的用法详细详解
    Win10操作系统无法访问局域网共享文件夹的问题
  • 原文地址:https://www.cnblogs.com/llhl/p/9648611.html
Copyright © 2020-2023  润新知