[Android]Smali语法

1. Smali介绍

Smali,Baksmali分别是指Android的Dalvik虚拟机所使用的一种.dex格式文件的汇编器,反汇编器。语法是以一种宽松式的Jasmin/dedexen语法,实现了.dex格式的所有功能

2. 生成Smali

使用apktool工具可以将apk生成为smali文件。也可以使用apktook将smali打包成apk文件。

3. Smali语法

Dalvik字节码中,寄存器是32位的,能够支持任何类型,64位使用两个寄存器表示。

3.1 确定函数使用的寄存器个数

有两种方法可以确定函数使用的寄存器个数:
1) .registers伪指令指示了函数使用的寄存器个数
2) .locals伪指令指示了函数使用的非参数寄存器个数(不用做保存参数的寄存器个数,也就是一般说的corrupted register)

3.2 传参方式(ABI)

当进行函数调用的时候,参数总是保存在最后的n个寄存器中。如果一个函数又两个参数,并且使用5个寄存器(v0-v4),那么参数
将保存到v3和v4中。非static函数的第一个参数总是一个object对象(this)。假如某个非static函数:foo(int i, int j),使用5个寄存器(v0-v4)调用该函数时,this对象将保存在v2,i保存在v3,j保存在v4。对于static函数来说,情况和非static类似,就是不用传递this罢了。

3.3 寄存器名

寄存器有两个名字,一个是v,另一个是p。p的意思是parameter,即参数。我们继续foo(int i, int j)这个例子,仍假设该函数
使用5个寄存器,那么寄存器情况如下:

v0  ----- the first local register
v1  ----- the second local register
v2/p0 ----- the first parameter register
v3/p1----- the second parameter register
v4/p2----- the third parameter reigster

函数中我们可以使用v名称来指代寄存器,也可以使用p名称。

3.4 添加p名称寄存器的意义

如果函数使用n名称:假设某个函数使用了若干个寄存器,而黑客想注入一些别的代码到该函数中,黑客发现他必须额外添加
函数使用的寄存器个数来达到目的。添加寄存器数量意味着函数内所有的参数寄存器都将无效,因为函数调用使用的是最后几
个寄存器作为传参寄存器的。

如果函数采用p名称:此时如果要修改函数,仅需要添加寄存器个数即可。

可以使用-p或-no-parameter-registers来强制生成使用n寄存器名来完成函数。默认使用p寄存器。

3.5 Long/double

Long和double在smali中皆为64位,使用2个寄存器。假设我们调用一个非static函数void bar(long a1, double a2)
假设该函数使用5个寄存器,该函数的寄存器使用情况如下:

p0 ------ this
p1/p2 ------ a1
p3/p4   ------ a2

3.6 类型

dalvik的类型比较像JNI。主要分为两个类型:原生类型和引用类型。引用类型主要指objects和arrays,其他类型都是原生类型。
原生类型如下:

V------ void - only be used for return types
Z------ boolean
B------ byte
S------ short
C------ char
I------ int
J------ long(64bits)
F------ float
D------ double(64bits)

引用类型如下:

Objects:

形如L包名/类名;,比如Lpackage/name/ObjectName; 注意结尾必须要有;符号。对应Java为package.name.ObjectName。比如String:
Ljava/lang/String;

Arrays:

形如[type-。比如int[]就是[I。如果是多维数组,则采用多个[号,比如:

int    [][] ------ [[I
double [][][][]------ [[[[D
String []------ [Ljava/lang/String;

3.7 函数

函数形如:
Lpackage/name/ObjectName;->MethodName(III)Z
这个函数的意思是,该函数位于package/name/ObjectName,该函数有三个参数,都是int,返回值为Z,意思是void。
再举个例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
这个函数是:
String method(int , int[][], String, Object[])

Lpackage/name/ObjectName;->为字段,字段的表示方式如下:
Lpackage/name/ObjectName;->FiledName:Ljava/lang/String;
这意思是,Lpackage/name/ObjectName下的FiledName,该字段类型为String。



你可能感兴趣的:(Android)