关于Smali注入大家应该了解过,网上有不少教程。那些注入代码看上去简单,实际用起来得花不少功夫。
普通的注入就是在软件源代码中添加几行代码,用于改变软件的功能,或查看某个寄存器在运行中具体的值。
需要注意的地方是:添加的注入代码所使用的寄存器不影响其他代码的执行。当注入代码较多时,这个要求就变得很困难了。
在这里我的解决办法是:把注入代码写进自己专属的crack.smali,然后在要注入的地方调用crack.smali里的注入方法即可,只用一行注入代码,而且不影响其他寄存器。
举个例子说明下两种方法的区别,假设原软件中有以下代码:
.method public methodName()Ljava/lang/String; .locals 4 .prologue const-string v0, “test1” const-string v3, “test2” invoke-static {v0}, Lpackage/name/ObjectName;——>methodName1(Ljava/lang/String;)Ljava/lang/String; move-result-object v1 invoke-static {v1}, Lpackage/name/ObjectName;——>methodName2(Ljava/lang/String;)Ljava/lang/String; move-result-object v2 invoke-static {v3}, Lpackage/name/ObjectName;——>methodName3(Ljava/lang/String;)V new-instance v3, Ljava/lang/StringBuilder; invoke-direct {v0, v3}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v0 invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v0 return-object v0 .end method
假如我要查看move-result-object v1和move-result-object v2,两处中v1、v2的值该如何注入?
普通的log.d注入方法如下(可以用Logcat查看日志):
.method public methodName()Ljava/lang/String; .locals 5 .prologue const-string v0, “test1” const-string v3, “test2” invoke-static {v0}, Lpackage/name/ObjectName;——>methodName1(Ljava/lang/String;)Ljava/lang/String; move-result-object v1 const-string v4, “info” invoke-static {v4, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I invoke-static {v1}, Lpackage/name/ObjectName;——>methodName2(Ljava/lang/String;)Ljava/lang/String; move-result-object v2 const-string v4, “info” invoke-static {v4, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I invoke-static {v3}, Lpackage/name/ObjectName;——>methodName3(Ljava/lang/String;)V new-instance v3, Ljava/lang/StringBuilder; invoke-direct {v0, v3}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v0 invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v0 return-object v0 .end method
在上面的代码中,我先是修改了开头的“.locals 5”,表示使用的寄存器为v0-v4。然后我用v4作为log.d的第一个参数,寄存器v1、v2为第二个参数。
由于原代码中,v0、v1、v2、v3从头到尾都有使用,所以注入时使用这几个寄存器会影响软件的正常执行,所以我才修改“.locals”开辟新的寄存器v4。
明显这样注入很麻烦。而且刚好v1、v2都是字符串,符合log.d的要求。如果v1、v2为整数值,注入就更加复杂了。
下面看看创建了crack.smali的注入会如何。
假设我已经有了个crack.smali,代码如下:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12 |
.
class public Lcrack; .
super Ljava/lang/Object; .source
"crack.java" .method
public static log(Ljava/lang/String;)V
.locals
1
.prologue
const
-string v0,
"info"
invoke-
static {v0, p0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
return
-
void .end method |