Android逆向之dalvik指令集

104 阅读4分钟

一、Dalvik寄存器

  • Dalvik虚拟机是Google用于移动设备的Android平台的一个主要部分。虚拟机可运行Java平台应用程序,这些应用程序被转换成紧凑的Dalvik可执行格式(.dex),该格式适合内存和处理器速度受限的系统。
  • Dalvik虚拟机是基于寄存器架构的,数据的访问经过寄存器单间直接传递。
  • Dalvik中用到的寄存器都是32位的,支持任何类型,64位类型用2个相邻的寄存器表示。
  • v命名法与p命名法:假设一个函数使用到了M个寄存器,而且该函数有N个参数,根据Dalvik虚拟机参数传递方式中的规定:参数使用最后N个寄存器,局部变量使用v0开始的前M-N个寄存器。 image.png

二、Dalvik字节码的类型

  • Dalvik字节码只有两种类型,基本类型与引用类型,Dalvik使用这两种类型来表示Java语言的所有类型,除了对象和数组属于引用类型,其余Java类型都是基本类型。 image.png
  • 根据字节码的大小与类型不一样,一些字节码添加了名称后缀以消除歧义。
    • 32位常规类型的字节码未添加任何后缀
    • 64位常规类型的字节码添加-wide后缀(例如:long和double类型)

三、const指令

  • const指令是定义程序中用到的常量、字符串、类等数据,也叫数据定义指令。

image.png

四、move指令

  • move指令是将源寄存器的值赋值给目的寄存器,也叫数据操作指令。

image.png

五、invoke指令

  • invoke指令是负责调用类实例的方法,也叫方法调用指令。
    • invoke-super:调用实例的父类方法。
    • invoke-virtual:调用实例的虚方法。
    • invoke-direct:调用实例的直接方法。
    • invoke-static:调用实例的静态方法。
      • 使用此方法调用指令的返回值必须使用 move-result* 指令来获取。
          invoke-static {v2}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; 
          move-result-object v2
      
    • invoke-interface:调用实例的接口方法。

六、return指令

  • return指令是函数结尾时运行的最后一条指令。
    • return-void:返回一个void。
    • return vAA:返回一个32位非对象类型的值,返回寄存器为8位。
    • return-wide vAA:返回一个64位非对象类型的值,返回寄存器为8位。
    • return-object vAA:返回一个对象类型,返回寄存器为8位。

七、代码示例

  • java代码
package com.company;

public class Main {

    public static void main(String[] args) {

        // 数据类型
        // 1.基本数据类型 int(整形) (float、double )浮点数
        // 2.引用数据类型 String(字符串)  类、数组、接口

        boolean bool = true;
        boolean bool2 = false;

        byte A = -128;

        char B = 12111;
        short sh = 13123;

        int a = 111111111;
        int b = 0;
        int c = 20;

        long l = 1212121323;

        float num = 3.14f;
        double num2 = 4.12;

        String name;
        name = "Hello World";
    }
}
  • smali代码
.class public Lcom/company/Main;
.super Ljava/lang/Object;
.source "Main.java"


# direct methods
.method public constructor <init>()V
    .registers 1

    .prologue
    .line 3
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

.method public static main([Ljava/lang/String;)V
    .registers 15
    .param p0, "args"    # [Ljava/lang/String;

    .prologue
    .line 12
    const/4 v4, 0x1  # 0x表示十六进制;在smali代码里面true1表示 false0表示

    .line 13
    .local v4, "bool":Z
    const/4 v5, 0x0

    .line 15
    .local v5, "bool2":Z
    const/16 v0, -0x80

    .line 17
    .local v0, "A":B
    const/16 v1, 0x2f4f

    .line 18
    .local v1, "B":C
    const/16 v11, 0x3343

    .line 20
    .local v11, "sh":S
    const v2, 0x69f6bc7

    .line 21
    .local v2, "a":I
    const/4 v3, 0x0

    .line 22
    .local v3, "b":I
    const/16 v6, 0x14

    .line 24
    .local v6, "c":I
    const-wide/32 v8, 0x483f80eb # 实际上是用v8、v9两个寄存器来存储long类型值,long类型存储空间是64位。

    .line 26
    .local v8, "l":J
    const v10, 0x4048f5c3    # 3.14f

    .line 27
    .local v10, "num":F
    const-wide v12, 0x40107ae147ae147bL    # 4.12

    .line 30
    .local v12, "num2":D
    const-string v7, "Hello World"

    .line 33
    .local v7, "name":Ljava/lang/String;
    return-void
.end method

八、参考链接