Smali是什么?
简介
Smali是用于Dalvik(Android虚拟机)的反汇编程序实现,汇编工具(将Smali代码汇编为dex文件)为smali.jar,与之对应的baksmali.jar则是反汇编程序(下载地址),官方所说的基于Jasmin/dedexer语法,实际根不知道是什么鬼……
Smali支持注解、调试信息、行数信息等基本Java的基本特性,可以说是很接近Java编译在JVM上的中间语言了,一般用来做Android程序的逆向工程,还可以。。搞搞小名堂
个人认为Smali只是用于做反汇编的一种语言实现,如果可以,自己也能定义一套这样的语言,实现反汇编的效果
Smali基础
下面的内容涉及一些Smali编程的结构和基本语法,这些基本语法,在使用Smali修改App逻辑时需要用到
Smali文件结构
一个Smali文件对应的是一个Java的类,更准确的说是一个.class文件,如果有内部类,需要写成ClassName$InnerClassA
、ClassName$InnerClassB
…这样的形式
基本类型
类型关键字 | 对应Java中的类型说明 |
---|---|
V | void,只能用于返回类型 |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long (64 bits) |
F | float |
D | double (64 bits) |
对象
Object类型,即引用类型的对象,在引用时,使用L开头,后面紧接着的是完整的包名,比如:java.lang.String
对应的Smali语法则是Ljava/lang/String
数组
数组定义比较有意思,一维数组在类型的左边加一个方括号,比如:[I
等同于Java的int[]
,每多一维就加一个方括号,最多可以设置255维。。。
方法声明及调用
官方Wiki中给出的Smali引用方法的模板如下:
Lpackage/name/ObjectName;->MethodName(III)Z
第一部分Lpackage/name/ObjectName;
用于声明具体的类型,以便JVM寻找
第二部分MethodName(III)Z
,其中MethodName为具体的方法名,()
中的字符,表示了参数数量和类型,即3个int型参数,Z为返回值的类型,即返回Boolean类型
由于方法的参数列表没有使用逗号这样的分隔符进行划分,所以只能从左到右,根据类型定义来区分参数个数,这一点需要比较仔细来观察
如果需要调用构造方法,则MethodName为:<init>
寄存器声明及使用
在Smali中,如果需要存储变量,必须先声明足够数量的寄存器,1个寄存器可以存储32位长度的类型,比如Int,而两个寄存器可以存储64位长度类型的数据,比如Long或Double
声明可使用的寄存器数量的方式为:.registers N
,N代表需要的寄存器的总个数,同时,还有一个关键字.locals
,它用于声明非参数的寄存器个数(包含在registers声明的个数当中),也叫做本地寄存器,只在一个方法内有效,但不常用,一般使用registers即可
示例:
.method private test(I)V
.registers 4 # 声明总共需要使用4个寄存器
const-string v0, "LOG" # 将v0寄存器赋值为字符串常量"LOG"