Smali是什么
Smali是Android虛擬機的反匯編語言竖共。
我們都知道惶桐,Android代碼一般是用java編寫的含潘,執(zhí)行java程序一般需要用到j(luò)ava虛擬機,在Android平臺上也不例外肤晓,但是出于性能上的考慮爷贫,并沒有使用標(biāo)準(zhǔn)的JVM认然,而是使用專門的Android虛擬機(5.0以下為Dalvik补憾,5.0以上為ART)。Android虛擬機的可執(zhí)行文件并不是普通的class文件卷员,而是再重新整合打包后生成的dex文件盈匾。dex文件反編譯之后就是Smali代碼,所以說毕骡,Smali語言是Android虛擬機的反匯編語言削饵。
掌握Smali有哪些好處
1、動態(tài)調(diào)試APK未巫,通常靜態(tài)分析APK是不夠的窿撬,如果需要徹底分析APK的執(zhí)行邏輯,需要通過動態(tài)調(diào)試來進行叙凡。
具體教程參考:http://blog.csdn.net/hanchaohao2012/article/details/63253725
2劈伴、修改APK運行邏輯,通過修改Smali代碼握爷,再重新編譯打包成新的APK跛璧,是Android逆向的基本操作。
Smali基本語法
數(shù)據(jù)類型
Smali | Java | 備注 |
---|---|---|
v | void | 只能用于返回值類型 |
Z | boolean | |
B | byte | |
S | short | |
C | char | |
I | int | |
J | long | |
F | float | |
D | double | |
Lpackage/name; | 對象類型 | L表示這是一個對象類型新啼,package表示該對象所在的包追城,;表示對象名稱的結(jié)束 |
[類型 | 數(shù)組 | [I表示一個int型數(shù)據(jù)燥撞,[Ljava/lang/String 表示一個String的對象數(shù)組 |
語法關(guān)鍵詞
關(guān)鍵詞 | 說明 |
---|---|
.class | 定義java類名 |
.super | 定義父類名 |
.source | 定義Java源文件名 |
.filed | 定義字段 |
.method | 定義方法開始 |
.end method | 定義方法結(jié)束 |
.annotation | 定義注解開始 |
.end annotation | 定義注解結(jié)束 |
.implements | 定義接口指令 |
.local | 指定了方法內(nèi)局部變量的個數(shù) |
.registers | 指定方法內(nèi)使用寄存器的總數(shù) |
.prologue | 表示方法中代碼的開始處 |
.line | 表示java源文件中指定行 |
.paramter | 指定了方法的參數(shù) |
.param | 和.paramter含義一致,但是表達格式不同 |
寄存器
Java中變量都是存放在內(nèi)存中的座柱,Android為了提高性能,變量都是存放在寄存器中的物舒,寄存器為32位色洞,可以支持任何類型。
為什么寄存器比內(nèi)存快茶鉴,可以參考這篇文章:http://www.ruanyifeng.com/blog/2013/10/register.html
寄存器分為如下兩類:
1锋玲、本地寄存器
用v開頭數(shù)字結(jié)尾的符號來表示,v0, v1, v2,...
2涵叮、參數(shù)寄存器
用p開頭數(shù)字結(jié)尾的符號來表示惭蹂,p0,p1,p2,...
注意:
在非static方法中伞插,p0代指this,p1為方法的第一個參數(shù)盾碗。
在static方法中媚污,p0為方法的第一個參數(shù)。
Smali代碼示例:
const/4 v0, 0x1 //把值0x1存到v0本地寄存器
iput-boolean v0,p0,Lcom/aaa;->IsRegisterd:Z //把v0中的值賦給com.aaa.IsRegistered廷雅,p0代表this耗美,相當(dāng)于this.Isregistered=true
成員變量
成員變量定義格式為:
.field public/private [static][final] varName:<類型>
獲取指令
iget, sget, iget-boolean, sget-boolean, iget-object, sget-object
操作指令
iput, sput, iput-boolean, sput-boolean, iput-object, sput-object
array的操作是aget和aput
指令解析
sget-object v0,Lcom/aaa;->ID:Ljava/lang/String;
獲取ID這個String類型的成員變量并放到v0這個寄存器中
iget-object v0,p0,Lcom/aaa;->view:Lcom/aaa/view;
iget-object比sget-object多一個參數(shù)p0,這個參數(shù)代表變量所在類的實例航缀。這里p0就是this
Smali代碼示例1:
const/4 v3, 0x0
sput-object v3, Lcom/aaa;->timer:Lcom/aaa/timer;
相當(dāng)于java代碼:this.timer = null;
Smali代碼示例2:
.local v0, args:Landroid/os/Message;
const/4 v1, 0x12
iput v1,v0,Landroid/os/Message;->what:I
相當(dāng)于java代碼:args.what = 18;
其中args為Message的實例
函數(shù)
函數(shù)定義格式為:
.method public/private [static][final] methodName()<類型>
.end method
Smali代碼示例:
.method private ifRegistered()Z
.locals 2 // 本地寄存器的個數(shù)
.prologue
const/4 v0, 0x1 //v0賦值為1
if-eqz v0, :cond_0 //判斷v0是否等于0商架,等于0則跳到cond_0執(zhí)行
const/4 v1, 0x1 //符合條件分支
:goto_0 //標(biāo)簽
return v1 //返回v1的值
:cond_0 //標(biāo)簽
const/4 v1, 0x0 //cond_0分支
goto :goto_0 //跳到goto_0執(zhí)行
.end method
函數(shù)分為兩類:direct method和virtual method
direct method就是private方法,virtual method就是指其余的方法芥玉。
調(diào)用指令:
invoke-direct
invoke-virtual
invoke-static
invoke-super
invoke-interface
調(diào)用格式:
invoke-指令類型 {參數(shù)1, 參數(shù)2,...}, L類名;->方法名
如果不是是靜態(tài)方法蛇摸,參數(shù)1代表調(diào)用該方法的實例。
Smali代碼示例:
const-string v0, "NDKLIB"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
相當(dāng)于java代碼:System.loadLibrary("NDKLIB")
函數(shù)返回結(jié)果
Smali需要用指令move-result或move-result-object來保存函數(shù)返回的結(jié)果
Smali代碼示例:
const-string v0, "Eric"
invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2
表示將方法t返回的String對象保存到v2中灿巧。