Smali語法基礎


Smali是什么

Smali是Android虛擬機的反匯編語言。
我們都知道,Android代碼一般是用java編寫的,執行java程序一般需要用到java虛擬機,在Android平台上也不例外,但是出於性能上的考慮,並沒有使用標准的JVM,而是使用專門的Android虛擬機(5.0以下為Dalvik,5.0以上為ART)。Android虛擬機的可執行文件並不是普通的class文件,而是再重新整合打包后生成的dex文件。dex文件反編譯之后就是Smali代碼,所以說,Smali語言是Android虛擬機的反匯編語言。

掌握Smali有哪些好處

1、動態調試APK,通常靜態分析APK是不夠的,如果需要徹底分析APK的執行邏輯,需要通過動態調試來進行。
具體教程參考:https://www.jianshu.com/p/9931a1e77066
2、修改APK運行邏輯,通過修改Smali代碼,再重新編譯打包成新的APK,是Android逆向的基本操作。

Smali基本語法

數據類型

語法關鍵詞

寄存器

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

寄存器分為如下兩類:
1、本地寄存器
用v開頭數字結尾的符號來表示,v0, v1, v2,...
2、參數寄存器
用p開頭數字結尾的符號來表示,p0,p1,p2,...
注意:
在非static方法中,p0代指this,p1為方法的第一個參數。
在static方法中,p0為方法的第一個參數。

Smali代碼示例:

const/4 v0, 0x1 //把值0x1存到v0本地寄存器
iput-boolean v0,p0,Lcom/aaa;->IsRegisterd:Z //把v0中的值賦給com.aaa.IsRegistered,p0代表this,相當於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多一個參數p0,這個參數代表變量所在類的實例。這里p0就是this

Smali代碼示例1:

const/4 v3, 0x0
sput-object v3, Lcom/aaa;->timer:Lcom/aaa/timer;

相當於java代碼:this.timer = null;

Smali代碼示例2:

.local v0, args:Landroid/os/Message;
const/4 v1, 0x12
iput v1,v0,Landroid/os/Message;->what:I

相當於java代碼:args.what = 18;
其中args為Message的實例

函數

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

Smali代碼示例

.method private ifRegistered()Z
    .locals 2            // 本地寄存器的個數
    .prologue
    const/4 v0, 0x1      //v0賦值為1
    if-eqz v0, :cond_0   //判斷v0是否等於0,等於0則跳到cond_0執行
    const/4 v1, 0x1      //符合條件分支
    :goto_0              //標簽
    return v1            //返回v1的值
    :cond_0              //標簽
    const/4 v1, 0x0      //cond_0分支
    goto :goto_0         //跳到goto_0執行
.end method

函數分為兩類:direct method和virtual method
direct method就是private方法,virtual method就是指其余的方法。

調用指令:
invoke-direct
invoke-virtual
invoke-static
invoke-super
invoke-interface

調用格式:
invoke-指令類型 {參數1, 參數2,...}, L類名;->方法名
如果不是是靜態方法,參數1代表調用該方法的實例。

Smali代碼示例:

const-string v0, "NDKLIB"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

相當於java代碼:System.loadLibrary("NDKLIB")

函數返回結果
Smali需要用指令move-result或move-result-object來保存函數返回的結果

Smali代碼示例:

const-string v0, "Eric"
invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2

表示將方法t返回的String對象保存到v2中。

方法的定義

private static int sum(int a, int b) {
        return a+b;
}

使用編譯后是這樣

.method private static sum(II)I
    .locals 4   #表示需要申請4個本地寄存器
    .parameter
    .parameter #這里表示有兩個參數
    .prologue
    .line 27 
    move v0, p0
    .local v0, a:I
    move v1, p1
    .local v1, b:I
    move v2, v0
    move v3, v1
    add-int/2addr v2, v3
    move v0, v2
    .end local v0           #a:I
    return v0
.end method

從上面可以看到函數聲明使用.method開始 .end method結束,java中的關鍵詞private,static 等都可以使用,同時使用簽名來表示唯一的方法,這里是sum(II)I。

指令執行

smali字節碼是類似於匯編的,如果你有匯編基礎,理解起來是非常容易的。
比如:
move v0, v3 #把v3寄存器的值移動到寄存器v0上.
const v0, 0x1 #把值0x1賦值到寄存器v0上。
invoke-static {v4, v5}, Lme/isming/myapplication/MainActivity;->sum(II)I #執行方法sum(),v4,v5的值分別作為sum的參數

條件跳轉分支

"if-eq vA, vB, :cond_x" --- 如果vA等於vB則跳轉到:cond_x
"if-ne vA, vB, :cond_x" --- 如果vA不等於vB則跳轉到:cond_x
"if-lt vA, vB, :cond_x" --- 如果vA小於vB則跳轉到:cond_x
"if-ge vA, vB, :cond_x" --- 如果vA大於等於vB則跳轉到:cond_x
"if-gt vA, vB, :cond_x" --- 如果vA大於vB則跳轉到:cond_x
"if-le vA, vB, :cond_x" --- 如果vA小於等於vB則跳轉到:cond_x
"if-eqz vA, :cond_x" --- 如果vA等於0則跳轉到:cond_x
"if-nez vA, :cond_x" --- 如果vA不等於0則跳轉到:cond_x
"if-ltz vA, :cond_x" --- 如果vA小於0則跳轉到:cond_x
"if-gez vA, :cond_x" --- 如果vA大於等於0則跳轉到:cond_x
"if-gtz vA, :cond_x" --- 如果vA大於0則跳轉到:cond_x
"if-lez vA, :cond_x" --- 如果vA小於等於0則跳轉到:cond_x
轉自: https://www.jianshu.com/p/ba9b374346dd


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM