【逆向教程】Smali代码③

寄存器

相信大家在看Smali时注意到了有很多v0、v1、v2、p0、p1、p2之类的标识符,这些都代表了寄存器。
那么什么是寄存器呢?你可以把它认为是变量,或者是暂时存放东西的地方。

举个例子:

有一个静态方法abc(String),如果你要在Java方法中调用这个方法,直接输入abc("Hello");就行了。

而在Smali中,你不能直接把字符串参数传递给方法,你需要一个寄存器(比如v0),先把"Hello"放到v0中,然后再调用abc方法,并告诉它你需要的参数在v0里面,自己去拿吧。

# 定义一个字符串常量"Hello"放到v0中
const-string v0, "Hello"
# 调用abc方法,需要的参数放在v0中
invoke-static {v0}, LXX;->abc(Ljava/lang/String;)V


现在大家理解什么是寄存器了吧。

另外寄存器v0、v1、v2后面的数字也不是随便写的,需要在方法的开头用.registers N来指定寄存器的数量,然后才可以使用寄存器v0v(N-1)

参数寄存器

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

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

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

普通寄存器对应参数寄存器
v0
v1
v2p0
v3p1
v4p2

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

普通寄存器参数寄存器初始化
v0
v1
v2p011
v3p122
v4p233

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

普通寄存器参数寄存器初始化
v0
v1
v2
v3p011
v4p122
v5p233

思考一下,如果不使用参数寄存器,代码中全部用vN,那么改变寄存器数量后,你还得改多少代码?

隐藏的参数

对于非静态方法,它的参数寄存器数量比实际参数多了一个,p0会固定用于表示当前类实例(Java中的this),从p1开始才是真正的参数,我们可以通过Java2Smali工具来验证一下,Java代码如下:

174956zab85hrsqebrbb8k.png插图(1)


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

test1()的Smali代码:

175322guo6d6q8ybbd6557.png插图(2)



test2()的Smali代码:

175322woo00gu5moom08m6.png插图(3)



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

那test2()中的p0真的代表this吗?我们也可以修改代码验证下:

20200912105119424.png插图(4)
20200912105131686.png插图(5)



到这边讲的都是基础知识,大家不懂的可以随时回复提问,下一篇开始讲代码了。

© 版权声明
THE END
喜欢就支持以下吧
点赞154
分享
评论 抢沙发