1. 程式人生 > >smali 除錯方法(動態除錯)

smali 除錯方法(動態除錯)

smali檔案

1.下圖為基本的smali結構

一個smali檔案對應一個class

2.欄位描述符

Java中Void在smali中對應V

Void -> V

其他具體描述符參考下面表格:

下面貼上兩段例子程式碼對應看下:
Android程式碼:

    package com.test.myapplication;

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

    public class MainActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            TextView tv = (TextView) findViewById(R.id.text);
            tv.setText("hello");
        }
    }

smali程式碼:

    .class public Lcom/test/myapplication/MainActivity;
    .super Landroid/app/Activity;
    .source "MainActivity.java"


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

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

        return-void
    .end method


    # virtual methods
    .method protected onCreate(Landroid/os/Bundle;)V
        .locals 2
        .param p1, "savedInstanceState"    # Landroid/os/Bundle;

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

        .line 12
        const/high16 v1, 0x7f030000

        invoke-virtual {p0, v1}, Lcom/test/myapplication/MainActivity;->setContentView(I)V

        .line 13
        const v1, 0x7f070009

        invoke-virtual {p0, v1}, Lcom/test/myapplication/MainActivity;->findViewById(I)Landroid/view/View;

        move-result-object v0

        check-cast v0, Landroid/widget/TextView;

        .line 14
        .local v0, "tv":Landroid/widget/TextView;
        const-string v1, "hello"

        invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

        .line 15
        return-void
    .end method

smali頭部分析:

.class public 對應 java class public

Lcom/test/myapplication/MainActivity; 類描述符 L+包+名+; 可檢視上面表中對應 Object —> Ljava/lang/Object;

.super欄位,表示從哪個類中擴展出來的, 此處對應 extends Activity

.source欄位,對應原始檔.source “MainActivity.java”表示java檔案就是MainActivity.java

smali方法分析:

固定格式

.method 開始

.end method 結尾

.method protected onCreate(Landroid/os/Bundle;)V -> protected void onCreate(Bundle savedInstanceState)

Landroid/os/Bundle; 傳入的引數, 最後面的V 表示返回值型別Void

invoke-virtual {p0, v1}, Lcom/test/myapplication/MainActivity;->findViewById(I)Landroid/view/View; -> TextView tv = (TextView) findViewById(R.id.text);

invoke-virtual 呼叫方法

move-result-object v0

把結果放到v0

const-string v1, “hello”

invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V

呼叫setText方法,把v1傳入

動態除錯:

工具:apktool

下載地址:https://bitbucket.org/iBotPeaches/apktool/downloads/

注意:此處介紹的動態除錯方法是比較舊的方法,下載2.1.0版本以下的,因為新版本的apktool -d 選項已經移除

反編譯原始碼中新增除錯:

1)java -jar apktool.jar d -d 目標.apk -o 結果放置目錄

2)修改AndroidMainfest檔案,在application節點新增 android:debuggable=”true”

3)在入口類的onCreate方法中新增:

invoke-static{},Landroid/os/Debug;->waitForDebugger()V

新增後示例:

a=0;// .method protected onCreate(Landroid/os/Bundle;)V
a=0;//     .locals 2
a=0;//     .param p1, "savedInstanceState"    # Landroid/os/Bundle;
a=0;// 
a=0;//     .prologue
a=0;//     .line 11
a=0;//     invoke-static{},Landroid/os/Debug;->waitForDebugger()V
a=0;//     invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

4)回編譯修改過的apk檔案

java -jar apktool.jar b -d 程式碼目錄 -o 目標apk名稱

問題:我在此處用android studio 編譯了一個apk回編譯失敗,暫時沒有解決,直接使用eclipse編譯了一個demo.apk

5)對生成的apk進行簽名,簽名方法可以參照之前的Android反編譯和回編譯文章

使用android studio進行動態除錯:

1)匯入已經反編譯修改好的功能程式碼

開啟Android Studio ->File -> Open -> 選擇剛才反編譯的目錄

2)在相應位置設定斷點

3)設定遠端除錯選項

Run -> Edit Configurations… -> 點選“+” -> Remote -> Host:localhost Port:8700

4)切換到另外一個編寫android程式碼的android studio視窗

開啟Android Device Monitor

點選要除錯的程式的程序

5) 切換到smali工程視窗

點選除錯按鈕,開始除錯

至此就可以像除錯android程式碼一樣除錯smali 程式碼啦