Android逆向基礎(chǔ):Smali語(yǔ)法

Smali是什么

Smali是Android虛擬機(jī)的反匯編語(yǔ)言。
我們都知道,Android代碼一般是用java編寫(xiě)的,執(zhí)行java程序一般需要用到j(luò)ava虛擬機(jī),在Android平臺(tái)上也不例外,但是出于性能上的考慮,并沒(méi)有使用標(biāo)準(zhǔn)的JVM,而是使用專(zhuān)門(mén)的Android虛擬機(jī)(5.0以下為Dalvik,5.0以上為ART)。Android虛擬機(jī)的可執(zhí)行文件并不是普通的class文件,而是再重新整合打包后生成的dex文件。dex文件反編譯之后就是Smali代碼,所以說(shuō),Smali語(yǔ)言是Android虛擬機(jī)的反匯編語(yǔ)言。

掌握Smali有哪些好處

1、動(dòng)態(tài)調(diào)試APK,通常靜態(tài)分析APK是不夠的,如果需要徹底分析APK的執(zhí)行邏輯,需要通過(guò)動(dòng)態(tài)調(diào)試來(lái)進(jìn)行。
具體教程參考:http://blog.csdn.net/hanchaohao2012/article/details/63253725
2、修改APK運(yùn)行邏輯,通過(guò)修改Smali代碼,再重新編譯打包成新的APK,是Android逆向的基本操作。

Smali基本語(yǔ)法

數(shù)據(jù)類(lèi)型

Smali Java 備注
v void 只能用于返回值類(lèi)型
Z boolean
B byte
S short
C char
I int
J long
F float
D double
Lpackage/name; 對(duì)象類(lèi)型 L表示這是一個(gè)對(duì)象類(lèi)型,package表示該對(duì)象所在的包,;表示對(duì)象名稱的結(jié)束
[類(lèi)型 數(shù)組 [I表示一個(gè)int型數(shù)據(jù),[Ljava/lang/String 表示一個(gè)String的對(duì)象數(shù)組

語(yǔ)法關(guān)鍵詞

關(guān)鍵詞 說(shuō)明
.class 定義java類(lèi)名
.super 定義父類(lèi)名
.source 定義Java源文件名
.filed 定義字段
.method 定義方法開(kāi)始
.end method 定義方法結(jié)束
.annotation 定義注解開(kāi)始
.end annotation 定義注解結(jié)束
.implements 定義接口指令
.local 指定了方法內(nèi)局部變量的個(gè)數(shù)
.registers 指定方法內(nèi)使用寄存器的總數(shù)
.prologue 表示方法中代碼的開(kāi)始處
.line 表示java源文件中指定行
.paramter 指定了方法的參數(shù)
.param 和.paramter含義一致,但是表達(dá)格式不同

寄存器

Java中變量都是存放在內(nèi)存中的,Android為了提高性能,變量都是存放在寄存器中的,寄存器為32位,可以支持任何類(lèi)型。
為什么寄存器比內(nèi)存快,可以參考這篇文章:http://www.ruanyifeng.com/blog/2013/10/register.html

寄存器分為如下兩類(lèi):
1、本地寄存器
用v開(kāi)頭數(shù)字結(jié)尾的符號(hào)來(lái)表示,v0, v1, v2,...
2、參數(shù)寄存器
用p開(kāi)頭數(shù)字結(jié)尾的符號(hào)來(lái)表示,p0,p1,p2,...
注意:
在非static方法中,p0代指this,p1為方法的第一個(gè)參數(shù)。
在static方法中,p0為方法的第一個(gè)參數(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:<類(lèi)型>

獲取指令
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這個(gè)String類(lèi)型的成員變量并放到v0這個(gè)寄存器中
iget-object v0,p0,Lcom/aaa;->view:Lcom/aaa/view;
iget-object比sget-object多一個(gè)參數(shù)p0,這個(gè)參數(shù)代表變量所在類(lèi)的實(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ù)

函數(shù)定義格式為:
.method public/private [static][final] methodName()<類(lèi)型>
.end method

Smali代碼示例:

.method private ifRegistered()Z
    .locals 2            // 本地寄存器的個(gè)數(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ù)分為兩類(lèi):direct method和virtual method
direct method就是private方法,virtual method就是指其余的方法。

調(diào)用指令:
invoke-direct
invoke-virtual
invoke-static
invoke-super
invoke-interface

調(diào)用格式:
invoke-指令類(lèi)型 {參數(shù)1, 參數(shù)2,...}, L類(lèi)名;->方法名
如果不是是靜態(tài)方法,參數(shù)1代表調(diào)用該方法的實(shí)例。

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來(lái)保存函數(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對(duì)象保存到v2中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。