smali 可以看成是虚拟机的汇编语言,在逆向时可以看懂smali可以提升不少效率.
Java 和 Smali 的类型对应关系和jni类似,如下所示: 基本数据类型
Smali数据类型 | Java数据类型 |
---|---|
V | void |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
对象类型
Smali数据类型 | Java数据类型 |
---|---|
Lpackage/name/ObjectName; | ObjectName |
[I | int[] |
打开smali 文件,头三行格式如下:
.class <访问权限> [关键修饰字] <类名>;
.super <父类名>;
.source <源文件名>
类的成员变量形式是:
.filed <访问权限> [关键修饰字] <字段名>:<字段类型>
函数的声明格式如下:
.method <访问权限> [关键修饰字] <方法原型>
<.locals> <.registers> // 函数中非参数的变量的多少
[.param] // 方法参数
[.line]
<代码>
.end method
Smali 指令有常量操作指令,方法调用指令,移位指令,分支判断指令。 常量操作指令主要是const相关指令,格式如下:
const-<类型> 寄存器, 操作数
const-string v1, "test" // 定义字符串“test”并存到 v1 寄存器中
const/16 v1, 0x1e // 定义了16位的数据常量"0x1e",并存到v1寄存器中
方法调用指令 是以invoke开头的相关指令,格式如下:
invoke-kind {vA,vB,vC},mehtod@DDDD
// mehtod@DDDD 表 示 函 数 的 引用;vA,vB,vC则表示函数的参数
// 其定义顺序与调用函数的参数一 一对应;kind则代表被调用的类型
// 主要有static、virtual、 super(被调用的函数是静态函数、正常的函数和父类函数等)
invoke-super {p0, p1}, Landroidx/Appcompat/App/AppCompatActivity;->onCreate (Landroid/os/Bundle;)V
// 调用AppCompatActivity的onCreate方法,p0是this,p1是bundle类型参数
移位指令是move相关指令,格式如下:
move v1,p1 // 将 p1 赋值给 v1
分支判断指令是if 相关指令, 格式如下:
if-[test] v1,v2, [condition] // 如果v1, v2 满足test,则跳转到condition 执行
if-ge p1, v0, :cond_0 // 如果 p1 >= v0, 则跳转到 cond_0
目前介绍了下Smali的基础,看起来也是比较好懂的