smali語法複習

特點

Smali彙編指令特點:
參數操作從目標到源的順序(類似x86彙編)
根據字節碼的類型和大小,添加後綴消除歧義
64位常規字節碼添加-wide
特殊字節碼添加具體類型
基於寄存器操作,不存在傳統彙編的棧操作,沒有pop,push
每個寄存器均爲32位,64位數據類型用連續兩個寄存器存儲表示

基本類型
V void (只能用於返回值類型) 
Z boolean 
B byte 
S short 
C char 
I int 
J long 
F float 
D Double 

數據類型

對象類型
表示方法:L包名+類名;(L;作爲起始結束符)
eg:
java.lang.String
Ljava/lang/String;
com.example.applicationandjni.MainActivity
Lcom/example/applicationandjni/MainActivity;
數組表示,類型前面加[
int[] --> [I
Int[][] --> [[I
String[] --> Ljava/lang/String;

方法的表示形式:
Lpackage/name/ObjectName;——>methodName(III)Z  詳解如下:
Lpackage/name/ObjectName  表示類型
methodName   表示方法名
III   表示參數(這裏表示爲3個整型參數)

字段的表示形式:
Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;表示: 包名,字段名和各字段類型

寄存器

有兩種方式指定一個方法中有多少寄存器是可用的:
.registers  指令指定了方法中寄存器的總數
.locals        指令表明了方法中非參寄存器的總數,出現在方法中的第一
方法的傳參:
當一個方法被調用的時候,方法的參數被置於最後N個寄存器中;
例如,一個方法有2個參數,5個寄存器(v0~v4)
那麼,參數將置於最後2個寄存器(v3和v4)
非靜態方法中的第一個參數總是調用該方法的對象;一般都爲p0
說明:對於靜態方法除了沒有隱含的this參數外,其他都一樣

常用命令法V和P
v表示本地寄存器,p表示參數寄存器
eg:一個方法有兩個局部變量,三個參數
v0         v0第一個本地寄存器 
v1         v1第二個本地寄存器 
v2         p0 (this) 
v3         p1 第一個參數 
v4         p2 第二個參數 
v5         p3 第三個參數

V命名法和P命名法的比較:使用P命名是爲了防止以後如果在方法中增加寄存器,需要對參數寄存器重新進行編號的缺點

再次強調:Long和Double類型是64位的,需要2個寄存器
例如:對於非靜態方法
LMyObject——>myMethod(IJZ)V;
有4個參數:LMyObject,int,long,bool;   需要5個寄存器來存儲參數;
P0    this
P1    I (int)
P2,P3  J (long)不能分開用,因爲JAVA解釋執行,沒有這種
P4    Z(bool)

smali文件

頭部
.class public Lcom/example/applicationandjni/MyApplication;
.super Landroid/app/Application;
.source "MyApplication.java"
.field
成員變量(靜態,非靜態)
.method
成員方法
其他
通過讀dex確定的smali文件結構。

字段聲明表示
public static aa:F
作用域 變量名:變量類型

方法聲明表示:
public pri_method(ILjava/lang/String;)Ljava/lang/String;
作用域 方法名(參數類型)返回值類型

public 、protected聲明
invoke-virtual(因爲繼承,有重載)
private聲明
invoke-direct
Static聲明
invoke-static
調用父類方法
invoke-super

所有smali彙編調用的方法沒有默認返回值比如x86/64的eaxrax,必須要調用一個move-result-object/其他類型 vx
 

Demo

下面分析一個彙編demo,先變成class,再變成dex,將dex,用baksmali解包

像那些R$的都是一些資源文件。跟資源文件耦合。

# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .registers 6
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;p0傳的是this

    .prologue
    .line 51
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 52
    const/high16 v0, 0x7f030000

    invoke-virtual {p0, v0}, Lcom/example/testtype/MainActivity;->setContentView(I)V

    .line 54
    const/4 v0, 0x1

    const-string v1, "1"

    invoke-virtual {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pub_method(ILjava/lang/String;)V

    .line 55
    const/4 v0, 0x2

    const-string v1, "2"

    invoke-virtual {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pro_method(ILjava/lang/String;)I

    .line 56
    const/4 v0, 0x3

    const-string v1, "3"

    invoke-direct {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pri_method(ILjava/lang/String;)Ljava/lang/String;

    .line 58
    const/4 v0, 0x4

    const-string v1, "4"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pub_static_method(ILjava/lang/String;)V

    .line 59
    const/4 v0, 0x5

    const-string v1, "5"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pro_static_method(ILjava/lang/String;)I

    .line 60
    const/4 v0, 0x6

    const-string v1, "6"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pri_static_method(ILjava/lang/String;)Ljava/lang/String;

    .line 62
    const-wide/16 v0, 0xa#long

    iput-wide v0, p0, Lcom/example/testtype/MainActivity;->a:J #看起來用了v0,實際上是v0v1,因爲是long

    .line 63
    const/16 v0, 0x14

    iput v0, p0, Lcom/example/testtype/MainActivity;->b:I

    .line 64
    const/high16 v0, 0x41f00000    # 30.0f

    sput v0, Lcom/example/testtype/MainActivity;->aa:F

    .line 65
    const-wide/high16 v0, 0x4044000000000000L    # 40.0

    sput-wide v0, Lcom/example/testtype/MainActivity;->bb:D

    .line 67
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;#java特性,字符串不可變,將2個字符串相加先newstringbuild,然後拼接起來,然後tostring
   

    iget-wide v2, p0, Lcom/example/testtype/MainActivity;->a:J

    invoke-static {v2, v3}, Ljava/lang/String;->valueOf(J)Ljava/lang/String;#java/lang/String類的valueOf方法傳入一個Jlong型,返回字符串型。

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V#兩個參數第一個參數相當於this是個對象,第二個參數是含參的構造函數,就是new一個對象,先new對象,上面的函數,再調用他的構造函數

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;//掉stringbuilder轉成String

    move-result-object v1#生成strign給v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 68
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    iget v2, p0, Lcom/example/testtype/MainActivity;->b:I

    invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 69
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    sget v2, Lcom/example/testtype/MainActivity;->aa:F

    invoke-static {v2}, Ljava/lang/String;->valueOf(F)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 70
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    sget-wide v2, Lcom/example/testtype/MainActivity;->bb:D

    invoke-static {v2, v3}, Ljava/lang/String;->valueOf(D)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 71
    return-void
.end method

.method protected pro_method(ILjava/lang/String;)I
    .registers 7
    .param p1, "n"    # I
    .param p2, "tag"    # Ljava/lang/String;

    .prologue
    .line 21
    mul-int/lit8 v0, p1, 0x2

    .line 22
    .local v0, "m":I
    const-string v1, "MF"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-static {p2}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v3

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    const-string v3, ": "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 23
    return v0
.end method

.method public pub_method(ILjava/lang/String;)V
    .registers 7
    .param p1, "n"    # I
    .param p2, "tag"    # Ljava/lang/String;

    .prologue
    .line 16
    mul-int/lit8 v0, p1, 0x2

    .line 17
    .local v0, "m":I
    const-string v1, "MF"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-static {p2}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v3

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    const-string v3, ": "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 18
    return-void
.end method

第二個pro_method逆向寫僞代碼如下 

package com.example.testtype
class Mainactivity extends Activity{
    protected int pro_method(int n,String tag)
    {
        int v0=n*0x2;
        string v1="MF";
        String v3=String.valueOf(tag);
        SrtringBuilder v2=new StringBuilder(v3);
        v3=":";
        v2=v2.append(v3);
        v2=v2.append.(v0);
        String v2=v2.toString();
        log.i(v1,v2);
        return v0;
    //其實這些代碼再java裏就是
            int m=n*0x02;
        Log.i("MF",tag+":"+m);
        return m;

    }
}

之所以要逆smali代碼,因爲是如果是大數組,jeb反編譯回是空,不是正常的。只能看smali彙編。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章