1. 程式人生 > >反編譯apk + eclipse中除錯smali

反編譯apk + eclipse中除錯smali

  從來沒有想過反編譯apk是來的如此方便,並且還可以修改後重新編譯執行,這比在win下修改pe容易多了,感謝apktool和smali工具的作者提供這麼好的工具。

    跟蹤apk一般的做法是在反編譯的smali程式碼中插入log輸出,然後重新編譯執行看輸出日誌,這種方法費時費力,如果能夠實時除錯是最好的了。搜了一下,目前比較好的方法是使用NetBeans+DDMS。我嘗試過可以除錯,但不大認識NetBeans的操作,eclipse估計很多人都會吧,其實設定跟NetBeans大同小異。

    除錯步驟:

    1.對apk使用apktool反編譯出可除錯的smali程式碼到out資料夾,目前apktool最新的版本是2.0.0b7。

java -jar apktool_2.0.0b7.jar d -d test.apk -o out

    這裡必須使用-d引數,這樣反編譯出來的程式碼字尾均是java,因為只有java檔案才能被eclipse/netbeans識別除錯。

    2.設定除錯標記和尋找主類

    在輸出的out資料夾中,用文字編輯工具開啟AndroidManifest.xml,在application節點中設定屬性android:debuggable="true"。

    繼續在AndroidManifest.xml中,搜尋以下關鍵字

<intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
</
intent-filter>

    找到含有以上資訊的activity節點,記錄其android:name屬性的值,該值則為其應用的主類。如下面的例子,主類為com.acids.helloworld.MainActivity。

複製程式碼
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.acids.helloworld">
    <application 
android:debuggable="true" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:label="@string/app_name" android:name="com.acids.helloworld.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
複製程式碼

    3.在主類的onCreate事件中新增除錯等待。

    用文字編輯工具開啟主類檔案,找到onCreate方法,在第一句前插入invoke-static {}, Landroid/os/Debug;->waitForDebugger()V,記得新增a=0;//的字首保持上下一致,結果如下:

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

    4.儲存檔案,用apktool重新編譯打包為debug.apk

java -jar apktool_2.0.0b7.jar b -d out -o debug.apk

    5.對debug.apk簽名(需要下載簽名工具),我把簽名工具放在了signapk資料夾下,生成debug.sign.apk

java -jar .\signapk\signapk.jar .\signapk\testkey.x509.pem .\signapk\testkey.pk8 .\debug.apk .\debug.sign.apk

    6.上傳debug.sign.apk至手機或模擬器,然後安裝並執行。這時你會看到程式執行後停留在白屏介面,這時不要動裝置和退出程式,因為程式現在是執行到剛才新增的waitForDebugger程式碼這裡,這行程式碼的意思是一直掛起中,等待偵錯程式。

    下面開始設定實時除錯的環境。

    7.啟動eclipse,構建java專案

    1) File -> New -> Project -> Java Project -> Next

    2) Project Name隨便起,Use default location選項去掉,Location選擇out資料夾,然後Next

    3) 把smali資料夾設為Source Folder,然後Finish

    8.在eclipse中,開啟第2步找到的主類,並找到onCreate方法,在waitForDebugger後面的第一個方法開始新增斷點。如下圖

    9.開啟DDMS(路徑在%android-sdks%\tools\ddms.bat),如果在第6步中運行了修改後的程式,在DDMS的裝置列表中會顯示可以除錯的程式。

    對應程式最後一欄為8600/8700,其中8600即為除錯該程式的埠。

    10.現在要做的就是把程式碼與除錯程式關聯即可。 回到eclipse,配置遠端除錯

    1) 選單Run -> Debug -> Debug Configurations

    2) 雙擊Remote Java Application,Host處預設localhost就行,Port填第10步得到的8600,然後Apply -> Debug。

    11.這時eclipse自動切換至debug檢視,並看到程式已經執行並中斷在下一行可執行的程式碼了,相關的變數可以直接查看了。

 

    總結

    已經可以用eclipse除錯smali了,上面的例子是從程式開頭的地方開始除錯,但要除錯到自己所關心地方的程式碼處確實麻煩。建議先用jd-gui等軟體直接檢視反編譯的java程式碼,確定要除錯的位置後,再進入smali定位斷點並實時除錯,就可以事半功倍。如果不需要在程式的開頭除錯的話,建議把第三部的程式碼註釋掉。

    相關工具可以在這裡下載

    apktool: https://code.google.com/p/android-apktool/

    dex2jar: https://code.google.com/p/dex2jar/

    jd-gui: http://jd.benow.ca/