首页
社区
课程
招聘
[原创]Smali 基础扫盲
发表于: 2020-8-31 14:20 11299

[原创]Smali 基础扫盲

2020-8-31 14:20
11299

鉴于 Frida 的强大,现在简单的安卓逆向已经基本上可以不用看 Smali 了,但并不是说完全弃用了。

Smali 实质上就是 Java 字节码,一句 Java 代码会对应多句 Smali 代码

例子:

写为 Smali 就是:

通常一个java文件中,可以定义多个类(含匿名内部类), 但一个 smali 只能定义一个类,smali 文件内容的格式如下:

其中除了boolean对应Z,long对应J,其它都是对应首个字母大写,还是很好记的

Smali中通过在类型前面加[来表示该类型的数组,例如[I表示int[],[Ljava/lang/String;表示String[],如果要表示多维数组,只需要增加[的数量,例如[[I表示二维数组int[][]

例子:

在Smali中都是用L包名路径/类名;表示,例如Android中的TextView类,它的包名是 android.widget,如果你要在Smali中表示这个类,就要写成 Landroid/widget/TextView

Smali中定义方法的语法是:

其中参数类型可以有0个或多个返回类型必须是一个,当要表达多个参数类型时,只需简单地将它们连接到一起,例如:

(int, int, String) 表示为 (IILjava/lang/String;)

Smali中必须以非常详细的形式指定要调用的方法,包括类名、方法名、参数类型和返回类型,其具体形式是:

类名->方法名(参数类型)返回类型

使用语法是:invoke-xxxxxx {参数列表}, 类名->方法名(参数类型)返回类型

所以当你在Smali代码中看到invoke开头的指令,就可以直接确定这句代码用于调用某个方法,至于invoke-后面跟着的单词,取决于它要调用的方法的类型。

虚方法其实是Java多态中的一个概念,大家应该知道Java中子类可以重写父类中可被继承的非final方法,调用这些方法时,都需要使用invoke-virtual指令,才能实现多态的特性,例如下面代码:

表面上看是调用Object的equals方法,但是由于obj实际上是字符串“123”,而字符串类String中重写了equals方法,所以虚拟机最后调用的是String的equals方法。

由于调用虚方法时,虚拟机需要先查找该方法是否被重写,而对于那些无法被重写的方法,查找显得是在浪费时间,所以使用invoke-direct指令来提高效率,其通常用于final方法、private方法、构造方法。

调用static方法时,就使用invoke-static。

在子类中,如果它已经重写了父类的XX方法,而又想调用父类的XX方法时,可通过super.XX()来调用,其对于的指令就是 invoke-super

invoke-xxxxxx {参数列表}, 类名->方法名(参数类型)返回类型

如果类名对应的类是个接口,那么xxxxxx就得写 interface

Smali中定义方法的语法是:

例如:

当一个字段是 staticfinal (静态常量)且类型为基本类型, 可以直接为他赋值:

字段包含注解:

和调用方法类似,在引用一个字段时,也需要详细形式指定字段:

类名->字段名:字段类名

例如:

v0、v1、v2、p0、p1、p2之类的标识符,这些都代表了寄存器。你可以把它认为是变量,或者是暂时存放东西的地方。

例子:

寄存器v0、v1、v2后面的数字也不是随便写的,需要在方法的开头用.registers N来指定寄存器的数量,然后才可以使用寄存器v0到v(N-1)。就像C中申请内存同理

上面说的都是普通寄存器vN,另外Smali还特意定义了一种参数寄存器pN,用于存放这个方法传入的参数的值。

如果一个方法有n个寄存器,有m个参数,那么n必须大于等于m,并且n个寄存器的后面m个是参数寄存器,举个例子:

某个静态方法abc(int, int, int),它一共有3个参数,如果它一共有5个寄存器(通过.registers N定义,N不能小于3)。

当我调用 abc(11, 22, 33) 时,p0 中的值初始化为11,p1 中的值初始化为22,p2 中的值初始化为33,v0v1 不会初始化。

当把寄存器数量改成6(.registers 6),寄存器就会变成下表所示:

非静态方法,它的参数寄存器数量参数多了一个,p0会固定用于表示当前类实例(this),从p1开始才是真正的参数,Java代码如下

test1()test2() 的唯一区别就是一个是静态一个非静态

test1() 的 smali

test2() 的 smali

两个方法都是依次打印出两个参数,test1()中打印第一个参数用的是p0,打印第二个参数用的是p1;对照下test2()中则分别用的是p1和p2。

后面有空会继续完善

 
 
 
 
 
 
 
 
 
 
 
 
 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-8-31 14:22 被番茄西瓜汤编辑 ,原因:
收藏
免费 11
支持
分享
最新回复 (9)
雪    币: 768
活跃值: (690)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
优秀
2020-8-31 15:55
0
雪    币: 19950
活跃值: (4942)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2020-9-1 11:43
0
雪    币: 207
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
优秀!
2020-9-2 19:49
0
雪    币: 1457
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
优秀
2020-9-2 23:07
0
雪    币: 5330
活跃值: (5464)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
很6
2020-9-3 00:20
0
雪    币: 922
活跃值: (1813)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
7
谢谢大佬
2023-1-30 16:38
0
雪    币: 587
活跃值: (3497)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢大佬
2023-1-30 19:35
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
感谢分享!
2023-1-30 19:54
0
雪    币: 223
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享,学会了
2023-2-5 10:53
0
游客
登录 | 注册 方可回帖
返回
//