Android & iOS · 2014-07-10

Smali注入之打造属于自己的安卓crack利器

关于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