为了账号安全,请及时绑定邮箱和手机立即绑定

Java逆向基础之函数

标签:
Java


本文提到的函数(function)和方法(method)为同一个意思


例子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: ()Dflags: ACC_PUBLIC, ACC_STATICCode:stack=4, locals=0, args_size=00: invokestatic  #2                  // Method java/lang/Math.random:()D3: ldc2_w        #3                  // double 2.0d6: ddiv7: dreturnLineNumberTable: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;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #3                  // String Hello, World5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 5: 0line 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;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=1, args_size=10: invokestatic  #2                  // Method java/awt/Toolkit.getDefaultToolkit:()Ljava/awt/Toolkit;3: invokevirtual #3                  // Method java/awt/Toolkit.beep:()V6: returnLineNumberTable:line 5: 0line 6: 6

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

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消