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。