如何簡單高效的學會Smali語法?

 

Q1:Smali是什麼。java

Smali是一種寬鬆式的Jasmin/dedexer語法.android

簡單來講就是咱們用java寫的代碼編譯成class打包成dex文件後使用baksmali程序逆向回來的一種語法。git

Q2:爲何要學習Smali。
首先,提到smali就不得不說逆向。早在尚未android以前,各大平臺和語言上就有對應的逆向一說。那麼到目前爲止,逆向一個apk一般是安全工程師(逆向工程師)和作破解等惡意分子由於某些利益在作(apk二次打包插入廣告、破解收費應用、惡意代碼植入、剽竊api等)。github

技術是一把雙刃劍,怎麼用在人。而不在技術自己上。那麼咱們說爲何應用層開發者也要學smali呢?我能想到如下幾點供參考。api

1.借鑑 當咱們發現其餘應用有一個很牛逼功能,而咱們想不明白如何實現的時候。拿不到源碼能夠選擇逆向。
2.安全 咱們寫的app須要考慮安全性,可是咱們可能只知道混淆和第三方加固,須要明白別人是怎麼破解咱們的應用。
3.適配 當咱們發現api在某些手機上被棄用,而其餘應用或系統應用又能實現該功能的時候。關於這點我以前寫過一篇逆向小米作適配的文章數組

喂,差很少夠了吧?還不能打動你學嗎?給你升職加薪怎麼樣? :)安全

噗,壞蛋!!!,我學 我學,還不行嗎?app

Q3:Smali難不難?
不難。也許你很早以前看過一些文章。或者也經常使用一些工具去打開反編譯後的代碼。看着一團麻的指令和一些你從未見過的關鍵字、代碼格式風格,賴不住性子就潦草的關掉了。但其實是你沒有找對方法來學習它。ide

Q4:怎麼學
我一貫的風格都是不愛把知識生拉硬套的往腦子裏塞,我更加習慣從實踐中去分析,然後反過來作總結。如今給你們推薦一款好用的Smali學習工具插件。咱們打開AndroidStudio找到插件安裝的位置。以下圖函數

 

打開 Browse Repositories,輸入java2smali安裝重啓便可。

 


github地址在這裏:intellij-java2smali

這個步驟之後,咱們就能夠愉快的將任何java代碼在androidStudio中直接轉換成smali來學習裏。步驟以下。
1.編寫一個最簡單的java文件。好比下面這樣的。

而後咱們點擊Build->Compile to smali

稍等幾秒鐘後就會獲得smali文件。

接下來咱們就能夠對照着java代碼來逐行分析這個smali文件。若是是第一次看咱們可能會被一些沒見過關鍵字干擾到。其實這裏有個很簡單的辦法。注意.line關鍵字就是用來描述當前代碼在java源文件中的行數。而後你能夠經過對照兩組代碼的方法進行反推。這樣就能夠很輕鬆的學會看smali文件。

好下面是一個示例代碼,供參考。

示例代碼:

原java代碼

public AA methodAReturn(AA mAA, AA sAA) {
        return mAA;
    }
AA aa= new AA();
//調用
  methodAReturn(aa, aa);

Smali代碼

.method public methodAReturn(Lcom/bolex/AA;Lcom/bolex/AA;)Lcom/bolex/AA;
    .registers 3
    .param p1, "mAA"    # Lcom/bolex/AA;
    .param p2, "sAA"    # Lcom/bolex/AA;

    .prologue
    .line 34
    return-object p1
.end method

  .line 21
    new-instance v0, Lcom/bolex/AA;
    invoke-direct {v0}, Lcom/bolex/AA;-><init>()V
    .line 22
    invoke-virtual {p0, v0, v0}, Lcom/bolex/seamAct;->methodAReturn(Lcom/bolex/AA;Lcom/bolex/AA;)Lcom/bolex/AA;

.line

.line 34

表示當前代碼在源java文件中的行數。

method

.method public methodAReturn(Lcom/bolex/AA;Lcom/bolex/AA;)Lcom/bolex/AA;

表示來自公共方法methodAReturn返回值是一個對象com.bolex.AA

registers

.registers 3

表示該函數上須要使用3個寄存器

param

.param p1, "mAA"    # Lcom/bolex/AA;
    .param p2, "sAA"    # Lcom/bolex/AA;

表示接收兩個入參都是AA對象,並標記寄存器p1和p2

.prologue

.prologue

表示函數內執行的起始標記。直譯爲開場白的意思。

.line

.line 34

表示在源代碼中的第34行。

return-object

return-object p1

表示 返回寄存器上p1對象

.end method

.end method

表示函數結束標記

new-instance

new-instance v0, Lcom/bolex/AA;

建立一個AA對象

invoke-direct

invoke-direct {v0}, Lcom/bolex/AA;-><init>()V

表示使用無參構造方法直接調用

invoke-virtual

invoke-virtual {p0, v0, v0}, Lcom/bolex/seamAct;->methodAReturn(Lcom/bolex/AA;Lcom/bolex/AA;)Lcom/bolex/AA;

表示爲虛擬方法

就是這個樣子的,有沒有很簡單呢?

以上只舉例了部分關鍵字,更多的關鍵字能夠自行依賴兩組文件反推。其實有時候更加講究的是一個方法。我以爲這個方法就挺不錯的,因此就分享給你們咯,咱也不須要刻意去背下來。熟能生巧,玩多了豈能不是老司機?

關於smali的知識還有不少本文並未詳細闡述,如寄存器、類型(原始類型、對象類型)、數組方法的表示形式。如讀者還須要進一步深刻挖。能夠參考官方文檔。裏面有詳細的解釋,已翻譯成中文版了。
https://source.android.com/devices/tech/dalvik/dex-format

做者:香脆的大雞排 連接:http://www.jianshu.com/p/b23782460f61 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索