1、Smali 简介
介绍:简单来说就是我们用java写的代码编译成class打包成dex文件后使用baksmali程序逆向回来的一种语法。
使用场景:对于一个release包的问题排查,我们既没有日志,也无法调试,又没有崩溃。出了问题非常难分析,有时会需要解开包,在里面加上日志,或者让程序在某个方法崩溃。但解开后我们得到的是smali代码,我们需要在里面添加打日志,制造崩溃的smali代码。
工具:
- 解包合包我们需要用到apktool
- 合包后的apk是无法安装的,需要签名后才能安装,所以需要用到jarsigner
- 直接解开apk看res和java内容,用到jadx
修改流程:
- 解包:apktool d xxx.apk。如果仅改smali可以不反编译res,加上-r就可以了
- 修改smali, 路径在 smali 目录下面
- 合包:apktool b xxx/
- 签名:jarsigner -verbose -keystore [keystore].jks -signedjar [签名后输出apk路径].apk [需要签名的apk路径].apk [keystore alias]
2、常用smali代码合集
2.1、模拟一个空指针
1) java代码:
1 2 |
String a = null; a.toString(); |
2) 对应smali代码:
1 2 3 4 5 6 |
.line 6 const/4 v0, 0x0 .line 7 .local v0, "a":Ljava/lang/String; invoke-virtual {v0}, Ljava/lang/String;->toString()Ljava/lang/String; |
3) 确认在smali对应的位置:
例如我们需要在exit()方法的360和361行之间造一个空指针
4) 在smali文件修改:
在smali 文件夹下找到对应的文件,可以找到.line360和.line361,在这两个之间就是我们想要加空指针的地方
5) 修改后合包再用jadx工具打开确认修改结果:
ok,空指针制造完毕。用同样的方法我们也可以在指定的位置增加日志打印,日志打印的smali代码请参考2.2节
2.2、打印日志
2.2.1、日志打印
java 代码
1 2 |
String a = "test"; android.util.Log.d("conio", ">>"+a); |
对应的smali代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.line 11 const-string v0, "test" .line 12 .local v0, "a":Ljava/lang/String; const-string v1, "conio" new-instance v2, Ljava/lang/StringBuilder; invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V const-string v3, ">>" invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I |
2.2.2、简单日志打印
java代码
1 |
android.util.Log.d("conio", "test"); |
smali代码
1 2 3 4 5 6 |
.line 11 const-string v0, "conio" const-string v1, "test" invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I |
3、常见语法解释
3.1、goto :goto_0
1 2 3 4 5 |
.line 565 :goto_0 return-void ... goto :goto_0 |
跳转到 :goto_0标签处,上面的代码为跳到void方法的return语句处。