5

私が書いた小さな Hello World Android アプリケーションで、smali と baksmali をいじっています。私のソースコードは次のとおりです。

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 オペコード仕様を使用してこの表現に到達する方法について、誰かが素人の言葉で説明できますか? 私の現在の理解はこれです:

  • APK を指定すると、バイナリ XML 形式で AndroidManifest.xml を抽出し、 axml2xml.plなどのツールを使用して、完全ではない「テキスト」バージョンのマニフェストを取得するか、 apktoolを使用してより読みやすいものを取得できます。形。しかし、バイナリー XML をテキストに変換するために彼らがどのような仕様を使用しているのかはまだわかりません。
  • 逆アセンブラーは、何らかの形で Dalvil オペコード仕様を利用して、dex ファイルを読み取り、それを上記の表現に変換しています。

上記の 2 つの手順に関する情報 (おそらくいくつかの簡単な例を含む) は、概念を正しく理解するのに大いに役立ちます。

更新 1 (Chris からの返信後に投稿):

基本的に、Dalvik バイトコードにたどり着くには次のようにします。

  • apk を取得して展開し、classes.dex ファイルを取得します。
  • 次に、逆アセンブラーは classes.dex ファイルを読み取り、apk に存在するすべてのクラスを判別します。これがどのように行われるかについての情報を教えてもらえますか? ファイルを 16 進モードで解析し、Dalvik 仕様を検索して、適切に解決しますか? それとも何か他のことが起こっていますか?たとえば、classes.dex で hexdump を使用すると、次のような結果が得られました。

    64 65 78 0a 30 33 ...

これらは現在 Opcode ルックアップに使用されていますか?

  • ツールが着信バイトコードを個別のクラスに分離できたと仮定すると、classes.dex ファイルから 16 進コードをスキャンし続け、Davlik 仕様を使用してテーブルから適切な Opcode 名を出力しますか?

実際、要するに、この「魔法」がどのように行われるかを知りたいのです。たとえば、このツールの作成方法を学ぶ場合、従うべき高レベルのロードマップは何ですか?

4

2 に答える 2

14

あなたが見ているのは、davlik バイトコードです。Java コードは、dx ツールによって Dalvik バイトコードに変換されます。マニフェストは、すぐに説明する別の問題です。実際には、Android アプリケーションをコンパイルすると、dx ツールは 256 個の dalvik オペコードを使用して Java コードをバイトコードに変換します (javac が Java を標準 JVM アプリケーションの Java バイトコードに変換するのと同じ方法です)。

たとえばinvoke-super、スーパー クラスでメソッドを呼び出すように dvm (dalvik 仮想マシン) に指示するオペコードです。同様にinvoke-interface、インターフェイス メソッドを呼び出すように dvm に指示します。

だからあなたはそれを見ることができます

super.onCreate(savedInstanceState);

に変換します

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

この場合、グループと、必要に応じてメソッドを検索して解決するために使用するメソッド仕様であるパラメーターinvoke-superの 2 つのパラメーターを取ります。{p0,p1Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)

次にinvoke-direct、コンストラクター領域での呼び出しがあります。

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

すべてのクラスにはinit、コンストラクターとも呼ばれる、クラスのデータ メンバーを初期化するために使用されるメソッドがあります。クラスを構築するとき、仮想マシンはスーパークラスのコンストラクターも呼び出す必要があります。これは、クラスのコンストラクターがコンストラクターを呼び出す理由を説明していますActivity

マニフェストに関しては、コンパイラ (apk ファイルを生成する) が目的のためにマニフェストをより圧縮された形式 (バイナリ xml) に変換することです (ソースコードをチェックアウトすると、これはすべて Dalvik 仕様にあります)。省スペースの。マニフェストは、投稿したコードとは関係ありません。アプリケーションを処理する方法について dvm に指示しActivitiesますServices

それはあなたの質問に対する大まかな答えです。さらに必要な場合はお知らせください。最善を尽くします。

編集あなたは基本的に正しいです。逆コンパイラは、バイナリ データを dex ファイルからバイト ストリームとして読み取ります。フォーマットがどうあるべきかを理解し、定数、クラスなどの情報を引き出すことができます。オペコードに関しては、まさにそれが機能します。各オペコードのバイト値 (または dex ファイルでの表現方法) を理解し、それを人間が読める文字列に変換できます。これを実装する場合は、コンパイラの一般的な基本を理解することは別として、dex ファイルの構造を深く理解することから始めます。そこから、オペコード値と人間が読める文字列を一致させるテーブルを作成する必要があります。その情報と、文字列定数などに関するいくつかの追加情報を使用して. コンパイルされたクラスのテキスト ファイル表現を作成できます。それは理にかなっていますか?

于 2011-01-27T18:40:50.297 に答える
3

オペコード仕様は、命令のみを記述します。dex ファイル形式はそれだけではありません。Dalvik VM (および逆アセンブラー) がファイルを解釈するために必要なすべてのメタデータ (文字列、クラス、型、メソッドなど) が含まれています。公式の opcode specも参照してください。リンクしたものよりも完全で詳細です。

<plug>ところで、 IDA Proの次のバージョンでは、.dex ファイルの逆アセンブルがサポートされます。</plug>

于 2011-01-27T18:38:40.193 に答える