发新帖

安卓逆向系列教程——Dalvik 指令集

[复制链接]
7441 0
  • 寄存器
    Dalvik 指令集完全基于寄存器,也就是说,没有栈。
    所有寄存器都是 32 位,无类型的。也就是说,虽然编译器会为每个局部变量分配一个寄存器,但是理论上一个寄存器中可以存放一个int,之后存放一个String(的引用),之后再存放一个别的东西。
    如果要处理 64 位的值,需要连续的两个寄存器,但是代码中仍然只写一个寄存器。这种情况下,你在代码中看到的vx实际上是指vx和vx + 1。
    寄存器有两种命名方法。v命名法简单直接。假设一共分配了 10 个寄存器,那么我们可以用v0到v9来命名它们。

https://wx3.sinaimg.cn/large/0060lm7Tly1g1iq3sdfsjj30co03lmxk.jpg

除此之外,还可以用p命名法来命名参数所用的寄存器,参数会占用后面的几个寄存器。假如上面那个方法是共有两个参数的静态方法,那么,我们就可以使用p0p1取代v8v9。如果是实例方法,那么可以用p0 ~ p2取代v7 ~ v9,其中p0this引用。


https://wx4.sinaimg.cn/large/0060lm7Tly1g1iq4dut9bj30bn03w74p.jpg

但在实际的代码中,一般不会声明所有寄存器的数量,而是直接声明局部变量所用的寄存器(后面会看到)。也就是说局部变量和参数的寄存器是分开声明的。我们无需关心vx是不是py,只需知道所有寄存器的数量是局部变量与参数数量的和。


数据类型
Dalvik 拥有独特的数据类型表示方法,并且和 Java 类型一一对应:
其中对象类型由L<包名>/<类名>;(完全限定名称)表示,要注意末尾有个分号,比如String表示为Ljava/lang/String;。
数组类型是[加上元素类型,比如int[]表示为[I。左方括号的个数也就是数组的维数,比如int[][]表示为[[I。
类定义
一个 smali 文件中存放一个类,文件开头保存类的各种信息。类的定义是这样的。
.class <权限修饰符> <非权限修饰符> <完全限定名称>.super <超类的完全限定名称>.source <源文件名>
比如这是某个MainActivity:
.class public Lnet/flygon/myapplication/MainActivity;.super Landroid/app/Activity;.source "MainActivity.java"
我们可以看到该类是public的,完整名称是net.flygon.myapplication.MainActivity,继承了android.app.Activity,在源码中是MainActivity.java。如果类是abstract或者final的,会在public/private/protected后面表示。
类可以实现接口,如果类实现了接口,那么这三条语句下面会出现.implements <接口的完全限定名称>。比如通常用于回调的匿名类中会出现.implements Landroid/view/View$OnClickListener;。
类还可以拥有注解,同样,这三条语句下方出现这样的代码:
.annotation <完全限定名称>    键 = 值    ....end annotation
这些语句下面就是类拥有的字段和方法。
字段定义
字段定义如下:
.field <权限修饰符> <非权限修饰符> <名称>:<类型>
其中非权限修饰符可以为final或者abstract。
比如我在MainActivity中定义一个按钮:
.field private button1:Landroid/widget/Button;方法定义
方法定义如下:
.method <权限修饰符> <非权限修饰符> <名称>(<参数类型>)<返回值类型>    ....end method
要注意如果有多个参数,参数之间是紧密挨着的,没有逗号也没有空格。如果某个方法的参数是int, int, String,那么应该表示为IILjava/lang/String;。
.locals
方法里面可以包含很多很多东西,可以说是反编译的重点。首先,方法开头处可能会含有局部变量个数声明和参数声明。.locals <个数>可以用于变量个数声明,比如声明了.locals 10之后,我们就可以直接使用v0到v9的寄存器。
.param
另外,参数虽然也占用寄存器,但是声明是不在一起的。.param px,"<名称>"用于声明参数。不知道是不是必需的。
.prologue
之后.prologue的下面是方法中的代码。代码是接下来要讲的东西。
.line
代码之间可能会出现.line <行号>,用来标识 Java 代码中对应的行,不过这个是非强制性的,修改之后对应不上也无所谓。
.local
还可能出现局部变量声明,.local vx, "<名称>":<类型>。这个也是非强制性的,只是为了让你清楚哪些是具名变量,哪些是临时变量。临时变量没有这种声明,照样正常工作。甚至你把它改成不匹配的类型(int改成Object),也可以正常运行。
数据定义https://wx3.sinaimg.cn/large/0060lm7Tly1g1iq69zoosj30ld0c7jsd.jpg





举报 使用道具

回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表