美文网首页
Android 逆向开发指令(1)

Android 逆向开发指令(1)

作者: googleKing | 来源:发表于2019-06-24 17:45 被阅读0次

最近逆向了一个工程,其中有一个init() 方法 如下:


// Byte code:

//  0: ldc com/aa/notice/network/OkHttpManager

//  2: monitorenter

//  3: getstatic com/aa/notice/network/OkHttpManager.serverTask : Lcom/aa/notice/network/OkHttpManager;

//  6: ifnonnull -> 20

//  9: new com/aa/notice/network/OkHttpManager

//  12: dup

//  13: aload_0

//  14: invokespecial : (Landroid/content/Context;)V

//  17: putstatic com/aa/notice/network/OkHttpManager.serverTask : Lcom/aa/notice/network/OkHttpManager;

//  20: ldc com/aa/notice/network/OkHttpManager

//  22: monitorexit

//  23: return

//  24: astore_0

//  25: ldc com/aa/notice/network/OkHttpManager

//  27: monitorexit

//  28: aload_0

//  29: athrow

// Exception table:

//  from  to target type

//  3 20 24 finally }


遇到了一些指令,大致解释如下:

ldc: 该系列命令负责把数值常量或String常量从常量池推送至栈顶。 该命令后面需要给一个常量在常量池中位置(编号)的参数,哪些常量是放在常量池呢?比如:final static int id = 32768; final static float double = 6.5. 对于const系列命令和push系列命令操作范围之外的数值类型常量,都放在常量池中。所有不是通过new创建的String都是放在常量池中的。

0x12          ldc                  将int, float或String型常量值从常量池中推送至栈顶

0x13          ldc_w              将int, float或String型常量值从常量池中推送至栈顶(宽索引)

0x14          ldc2_w            将long或double型常量值从常量池中推送至栈顶(宽索引)


monitorenter 和 monitorexit 是同步指令  相当于java中的synchronized。


getstatic、putstatic:遇到 new、 getstatic、 putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化, 则需要先触发其初始化, 生成这4条指令的最常见的 Java代码场景是:

(1)、使用 new关键字实例化对象的时候;

(2)、读取或设置一个类的静态字段的时候(即在字节码中,执行getstalic或putstatic指令时),被final修饰、已在编译期把结果放入常量池的静态字段除外;

(3)、调用一个类的静态方法的时候(即在字节码中执行invokestatic指令时)。


dup:其作用就是复制之前分配的空间的引用并压入栈顶。

invokespecial:只能调用三类方法:<init>方法;private方法;super.method()。因为这三类方法的调用对象在编译时就可以确定。

invokevirtual:是一种动态分派的调用指令:也就是引用的类型并不能决定方法属于哪个类型。

这里可以看到其中main方法主要做的

    0  new jvm.study.Test [1]

    3  dup

    4  invokespecial jvm.study.Test() [16]

    7  astore_1 [t]

    8  return

这里有个dup指令。其作用就是复制之前分配的jvm.study.Test空间的引用并压入栈顶。那么这里为什么需要这样么做呢?因为invokespecial指令通过[16]这个常量池入口寻找到了jvm.study.Test()构造方法,构造方法虽然找到了。但是必须还得知道是谁的构造方法,所以要将之前分配的空间的应用压入栈顶让invokespecial命令应用才知道原来这个构造方法是刚才创建的那个引用的,调用完成之后将栈顶的值弹出。之后调用astore_1将此时的栈顶值弹出存入局部变量中去。


load系列A:该系列命令负责把本地变量送到栈顶。这里的本地变量不仅可以是数值类型,还可以是引用类型。

load系列B:该系列命令负责把数组的某项送到栈顶。该命令根据栈里内容来确定对数组的某项进行操作。

store系列A:该系列命令负责把栈顶的值存入本地变量。这里的本地变量不仅可以是数值类型,还可以是引用类型

store系列B:该系列命令负责把栈顶项的值存到数组。该命令根据栈里内容来确定对哪个数组的哪项进行操作。


JVM指令详解

JVM指令大全

invokespecial和invokevirtual两种指令

java字节码构造对象为什么需要dup命令

Java类加载的过程

Smali-Dalvik虚拟机指令语言

相关文章

网友评论

      本文标题:Android 逆向开发指令(1)

      本文链接:https://www.haomeiwen.com/subject/awnoqctx.html