返回字符串的静态方法:
.class public Lf8/helloworld/helloStr; #类声明
.super Ljava/lang/Object;
.method public static retHello()Ljava/lang/String; #函数声明
.locals 1 #寄存器数量
const-string v0, "Hello World From StaticMethod."
return-object v0
.end method
返回静态field的方法:
.field public static final hStr:Ljava/lang/String; = "Hello World From Static Field."
.method public static retHello2()Ljava/lang/String;
.locals 1
sget-object v0, Lf8/helloworld/helloStr;->hStr:Ljava/lang/String; #获取field
return-object v0
.end method
普通的函数
.method public constructor ()V
.locals 0
invoke-direct {p0}, Ljava/lang/Object;->()V
return-void
.end method
.method public retHello3()Ljava/lang/String;
.locals 1
const-string v0, "Hello World From Method"
return-object v0
.end method
普通的field与返回其的函数
.field public hStr2:Ljava/lang/String;
.method public constructor <init>()V
.locals 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const-string v0, "Hello World"
iput-object v0, p0, Lf8/helloworld/helloStr;->hStr2:Ljava/lang/String;
return-void
.end method
.method public retHello4()Ljava/lang/String;
.locals 1
iget-object v0, p0, Lf8/helloworld/helloStr;->hStr2:Ljava/lang/String;
return-object v0
.end method
调用普通函数返回其field的时候需要先初始化一个实例
new-instance v1, Lf8/helloworld/helloStr;
invoke-direct {v1}, Lf8/helloworld/helloStr;-><init>()V
invoke-virtue {v1}, Lf8/helloworld/helloStr;->retHello3()Ljava/lang/String;
move-result-object v1
上面的代码只是为了进一步熟悉smali语法以代码的编写,实践中一个比较取巧的方法是先用java写好代码以及相关调用后,反汇编直接抠出代码。
Android Killer 自带3种代码模版
1)LoadLibrary
const-string v0, "so name"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
2)logcat
const-string v0, "you message"
invoke-static {v0}, Lcom/android/killer/Log;->LogStr(Ljava/lang/String;)V
这个模版实质上会在代码中插入一个包。
在smali中注入上述代码会在ddms中的Log窗口打印出日志信息。
3)toast
const-string v0, "you message"
const/4 v1, 0x1
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
4)dumpStack
invoke-static {}, Ljava/lang/Thread;->dumpStack()V
在smali中注入上述代码可以打印出程序执行过程中的调用堆栈,当在Jeb中反调试smali代码之后,当通过x查看引用没有结果时可以尝试使用注入该代码并在DDMS日志中查看相应调用。
5) traceview
invoke-static {}, Landroid/os/Debug;->startMethodTracing()V
invoke-static {}, Landroid/os/Debug;->stopMethodTracing()V
同时需要声明权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
traceView可以生成.trace文件显示出从某一个开始点到结束点的调用线程信息,用于追踪函数也可用来性能测试,需要读写权限。
6)等待调试:
invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
…….以上只是一些示例smali代码库,在对安卓应用层的逆向过程中可以不断扩充。