Android Smali语法及插桩

Dalvik虚拟机给自己搞了一套指令集,并制定了自己的指令格式和调用规则。这些指令的集合就组成了Dalvik汇编代码。

Smali文件中保存的就是.dex文件经反编译得到的Dalvik汇编代码。

下面就通过一段Smali代码,掌握阅读方法。

# virtual methods 
.method public foo(II)I #int foo(int, int);
    .registers 5 #使用5个寄存器
    .parameter #参数
    .parameter
    .prologue #代码开始
    .line3
    add-int v0, p1, p2 #将p1,p2相加,存入v0
    sub-int v1, p1, p2
    mul-int/2addr v0, v1
    return v0
.end method

有几个注意点:

1..registers指令指定函数用到寄存器的个数,其中参数3个p0,p1和p2,局部变量使用2个v0和v1。函数中没有体现p0,因为p0代表的是非静态方法中的this。

2.在ARM架构中,部分寄存器被映射到ARM寄存器,部分使用调用栈进行模拟。

上面是粗略的认识,下面讲系统的方法论。

Dalvik汇编代码由类型、方法、字段和指令集构成。

1.类型

语法                 含义
V                    void,只用于返回值类型
Z                    boolean
B                    byte
S                    short
C                    char
I                    int
J                    long
F                    float
D                    double
L                    Java类类型
[                    数组类型

注1,像J,D等64位类型,使用2个相邻寄存器保存,如v2,v3

注2,[I表示一个整形一维数组,n维数组等等递推

注3,Ljava/lang/String 表示Java字符串类型,以此类比

2.方法

方法格式:Lpackage/name/ObjectName;->MethodName(III)Z

举个栗子

method(I[[IILjava/lang/String; [Ljava/lang/Object; )Ljava/lang/String;

翻译成Java代码就是

String method(int, int[][], int, String, Object[])

3.字段

字段由类型(Lpackage/name/ObjectName)、字段名(FieldName)和字段类型(Ljava/lang/String)组成:

Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

4.指令集

Dalvik指令集按功能可划分为:空操作指令(nop)、数据操作指令(move vA, vB)、返回指令(return-void)、数据定义指令(const/16 vA, #+BBBB)、锁指令(mointor-enter vAA)、实例操作指令(new-instance vAA, type@BBBB)、数组操作指令(array-length vA, vB)、异常指令(thow vAA)、跳转指令(if-eqz)、比较指令(cmpl-double)、字段操作指令(sget-object)、方法调用指令(invoke-static)、数据转换指令(int-to-byte)、数据运算指令(mul-type)

具体的指令集信息,搜索 “dalvik opcodes” 可得到。

有时候apk逆向过程中,我们需要验证一下自己的想法,或跟踪程序执行流程,需要在smali代码中插桩。下面分别插入log,toast和加载so库的代码。

Log额外使用2个寄存器:

.method protected onCreate(Landroid/os/Bundle;)V
    .locals 5 #因为用到v3\v4两个额外寄存器,locals数+2
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;
 
    .prologue
    .line 23
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
 
    #### inject begin #####
    const-string v3, "logInfo"  #标签
    const-string v4, "Hello ezreal."  #日志内容
 
    invoke-static {v3, v4}, Landroid/util/Log;->w(Ljava/lang/String;Ljava/lang/String;)I   #调用Log.w()
    #### inject end ####
 
    .line 24
    const/4 v2, 0x1

toast额外使用2个寄存器:

const-string v5, "你好我是一个toast"
 
const/4 v6, 0x1
 
invoke-static {p0, v5, v6}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
move-result-object v5
 
invoke-virtual {v5}, Landroid/widget/Toast;->show()V

加载so库,额外使用1个寄存器:

const-string v7, "libcrackme.so"    #so库名称

invoke-static {v7}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V



你可能感兴趣的:(Android Smali语法及插桩)