2011-01-27 136 views
4

我正在玩一個smali and baksmali在我寫的一個小型Hello World Android應用程序上。我的源代碼是:瞭解反彙編Dalvik代碼?

package com.hello; 

import android.app.Activity; 
import android.os.Bundle; 

public class Main extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
    } 
} 

,然後將其分解到:

.class public Lcom/hello/Main; 
.super Landroid/app/Activity; 
.source "Main.java" 


# direct methods 
.method public constructor <init>()V 
    .locals 0 

    .prologue 
    .line 6 
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V 

    return-void 
.end method 


# virtual methods 
.method public onCreate(Landroid/os/Bundle;)V 
    .locals 1 
    .parameter "savedInstanceState" 

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

    .line 11 
    const/high16 v0, 0x7f03 

    invoke-virtual {p0, v0}, Lcom/hello/Main;->setContentView(I)V 

    .line 12 
    return-void 
.end method 

我明白,這是某種中間表示的,但我不知道它是什麼。據我所知,必須有一些關於如何理解這種表示的規範,但無法弄清楚如何搜索它。因此給定一個apk文件,有人可以用通俗的話來解釋Dalvik opcode specification是如何用於表示的嗎?我現在的理解是這樣的:

  • 給定一個APK,我可以在一個二進制XML格式 提取 AndroidManifest.xml中,並使用一個工具,如 axml2xml.pl得到一個「文本」 版本清單的那是不是 完成或我可以使用 apktool獲得更具可讀性的 表單。但我仍然不確定他們使用的 規範將 轉換成文本的二進制XML。
  • 的 反編譯器莫名其妙利用 的Dalvil碼規範 讀取DEX文件和 轉換成上述表示。

上述兩個步驟中的任何信息(或許有一些簡單的例子)都會幫助我更好地理解概念。

更新1(貼從克里斯的答覆後):

所以基本上,我會做以下以在Dalvik字節碼到:

  • 採取的APK並提取它來獲得classes.dex文件。
  • 然後反彙編器讀取classes.dex文件並確定apk中存在的所有類。你能向我提供一些關於如何完成的信息嗎?它是否以十六進制模式解析文件並查找Dalvik規範,然後進行適當的解析?或者是其他事情發生?舉例來說,當我用classes.dex hexdump都可以,它給了我這樣的事情:

    64 65 78 0A 30 33 ...

難道這些現在被用來操作碼查找?

  • 假設工具是能夠進入的字節碼轉換爲單獨的類分離,則它繼續掃描從classes.dex文件中的十六進制代碼,並使用Davlik規範輸出來自表中的適當操作碼的名字?

其實,總之,我很想知道所有這些「魔法」是如何完成的。例如,如果我要學習編寫這個工具,我應該遵循什麼樣的高層路線圖?

回答

14

什麼你看是davlik字節碼拆卸。 Java代碼由dx工具轉換爲Dalvik字節碼。清單是一個單獨的問題,我將在一分鐘內解決。實際上,當您編譯Android應用程序時,dx工具會使用256個dalvik操作碼將Java代碼轉換爲字節碼(與javac將標準JVM應用程序的Java字節碼轉換爲Java字節碼的方式相同)。

例如,invoke-super是一個操作碼,指示dvm(dalvik虛擬機)調用超類的方法。同樣,invoke-interface指示dvm調用接口方法。

因此可以看到的是

super.onCreate(savedInstanceState); 

轉化爲

invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;) 

在這種情況下,invoke-super採用兩個參數,所述{p0,p1組和Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)參數,該參數是它使用該方法規範如有必要,查找並解決方法。

然後在構造函數區域調用invoke-direct

invoke-direct {p0}, Landroid/app/Activity;-><init>()V 

每個類具有被用於初始化類的數據成員,也稱爲構造一個init方法。在構造類時,虛擬機還必須調用超類的構造函數。這就解釋了爲什麼你的類的構造函數調用Activity的構造函數。

關於清單,發生了什麼(如果檢出源代碼,這些都在Dalvik規範中)是編譯器(生成apk文件)將清單轉換爲更加壓縮的格式(二進制xml )爲了節省空間。清單與您發佈的代碼沒有任何關係,它更多地指導dvm如何處理應用程序是整體關於ActivitiesServices等。您發佈的內容是實際執行的內容。

這是您的問題的高級答案。如果你需要更多,讓我知道,我會盡我所能。

編輯你基本上是對的。反編譯器將二進制數據從dex文件讀取爲字節流。它瞭解格式應該是什麼,並能夠抽出像常量,類等信息。關於操作碼,這正是它所做的。它理解每個操作碼的字節值是什麼(或者它是如何在dex文件中表示的)並且能夠將其轉換爲可讀的字符串。如果你打算實現這一點,除了理解編譯器的一般基礎知識外,我將首先深入理解一個dex文件的結構。從那裏,你將需要構建一個表,匹配opcode值與人類可讀的字符串。通過這些信息和一些關於字符串常量的附加信息,您可以構建編譯類的文本文件表示。那有意義嗎?

3

操作碼規範只描述說明。 dex file format不止於此 - 它包含Dalvik VM(和反彙編程序)解釋文件所需的所有元數據 - 字符串,類,類型,方法等。另請參閱official opcode spec,它比鏈接的更完整和詳細。

<plug> BTW,的IDA Pro下一版本將支持.DEX文件</plug>

+0

這看起來像一個更完整的頁面。謝謝! IDAPro似乎很棒,但商業化:(看起來只有舊版本免費提供) – Legend 2011-01-27 18:59:31

+0

netmite.com上的任何內容都不是「官方」的,官方版本位於Android源代碼樹中,例如http://android.git。 kernel.org/?p=platform/dalvik.git;a=tree;f=docs;h=7045c2e00b823918a8387187ca171d4c68936080;hb=HEAD。(OTOH,netmite副本比git存儲庫中的更容易閱讀,因爲CSS頁面) – fadden 2011-01-29 01:23:59