1.前言:
這周公司有一個(gè)破解apk的需求,想要調(diào)起某軟件的視頻播放頁(yè)面,之前有一套通過(guò)發(fā)廣播調(diào)起的邏輯,該軟件更新版本后這一套邏輯就廢棄了。新版本的包拿過(guò)來(lái)反編譯后靜態(tài)分析,盯著別人代碼看了一天也沒(méi)找到突破口,師父看我實(shí)在太菜,決定把他的秘法傳授與我,這篇文章便是我自己消化吸收后再重新做的一個(gè)總結(jié)。接下來(lái)進(jìn)入今天的主題:Android反編譯之——斷點(diǎn)調(diào)試。
2.原理概述:
Android系統(tǒng)有自己的虛擬機(jī)Dalvik,代碼編譯最終不是采用java的class,而是使用的smali。我們反編譯得到的代碼,jar的話可能很多地方無(wú)法正確的解釋出來(lái),如果我們反編譯的是smali則可以正確的理解程序的意思。
3.準(zhǔn)備工具:
以下的版本都是我當(dāng)前使用的版本,做個(gè)參考
1.Android Studio-2.2,谷歌親兒子
2.apktool-2.2.2,使用它可以將apk反編譯,得到smali文件,也可以將反編譯出的文件重新打包,生成一個(gè)未簽名的apk文件
3.smalidea-0.03,這是一個(gè)AS上的插件,裝上它,就能用AS來(lái)斷點(diǎn)調(diào)試smali文件
4.signapk.jar、platform.x509.pem、platform.pk8,這里我是用的系統(tǒng)的簽名文件
4.準(zhǔn)備工作:
以下內(nèi)容引用自看雪論壇@火翼[CCG]的文章:
根據(jù)android官方文檔,要調(diào)試一個(gè)apk里面的dex代碼,必須滿足以下兩個(gè)條件中的任意一個(gè):
1. apk中的AndroidManifest.xml文件中的Application標(biāo)簽包含屬性android:debuggable=”true”
2. /default.prop中ro.debuggable的值為1
由于正常的軟件發(fā)布時(shí)都不會(huì)把a(bǔ)ndroid:debuggable設(shè)置為false(當(dāng)然也不排除某些很2的應(yīng)用偏偏就是true),所以要達(dá)成條件1需要對(duì)app進(jìn)行重新打包,這不僅每次分析一個(gè)apk都重復(fù)操作,而且很多軟件會(huì)對(duì)自身進(jìn)行校驗(yàn),重打包后執(zhí)行會(huì)被檢測(cè)到,所以想辦法滿足第2個(gè)條件是個(gè)一勞永逸的辦法。
由于default.prop是保存在boot.img的ramdisk中,這部分每次重新啟動(dòng)都會(huì)重新從rom中加載,所以要到目的必須修改boot.img中的ramdisk并重新刷到設(shè)備中。修改步驟如下(我沒(méi)試過(guò),有興趣的倒騰下):
1. 從Google官方網(wǎng)站下載到boot.img
2. 使用工具(abootimg,gunzip, cpio)把boot.img完全解開(kāi),獲取到default.prop
3. 修改default.prop
4. 把修改后的文件重新打包成boot_new.img
5. 使用fastboot工具把boot_new.img刷入設(shè)備(fastboot flash boot boot_new.img)
這里筆者使用的是方法1,即修改AndroidManifest.xml文件中的android:debuggable=”true”。方法2刷機(jī)什么的還是感覺(jué)有些麻煩,還有一種途徑是:AVD啟動(dòng)模擬器時(shí),ro.debuggable會(huì)被置1,但是有個(gè)弊端,如果選arm架構(gòu)的system image,速度奇慢;如果選x86架構(gòu)的system image,速度很快(現(xiàn)在AS原生模擬器的速度已經(jīng)優(yōu)化得很快了),但是如果apk里有編譯目標(biāo)是arm架構(gòu)的lib就無(wú)法安裝,會(huì)報(bào)錯(cuò)Failure [INSTALL_FAILED_NO_MATCHING_ABIS]。
我們來(lái)說(shuō)一下準(zhǔn)備工作的步驟:
1.使用apktool將要反編譯的apk進(jìn)行解包
java -jar apktool_2.2.2.jar d xxx.apk -o out
這一步會(huì)把a(bǔ)pk解包到out目錄下。apktool版本過(guò)低容易出現(xiàn)解包失敗的情況,這也是筆者之前踩到的一個(gè)小坑,所以建議使用最新的apktoo來(lái)完成反編譯的步驟。
2.修改AndroidManifest.xml文件中Application標(biāo)簽包含的屬性android:debuggable=”true”
3.使用apktool將out目錄下的文件重新打包成apk
java -jar apktool_2.2.2.jar b out -o unsigned.apk
這一步我們打包出來(lái)的是一個(gè)沒(méi)有簽名的apk,所以我把它取名unsigned.apk,便于理解。
4.給這個(gè)unsigned.apk簽名并安裝到調(diào)試設(shè)備上,這里我用了一個(gè)系統(tǒng)級(jí)的簽名
java -jar signapk.jar platform.x509.pem platform.pk8 unsigned.apk debug.apk
這里我是圖省事,手里剛好有現(xiàn)成的文件,就直接簽了一個(gè)系統(tǒng)簽名。非系統(tǒng)簽名也是沒(méi)有問(wèn)題的,簽名的方法有好多種,有興趣的朋友可以網(wǎng)上查一下相關(guān)內(nèi)容,這里不再贅述。
5.將smalidea插件安裝到AS上,具體步驟:File->Settings->Plugins->Install plugin from disk,然后選中下載的smalidea-0.03.zip文件,按照提示重啟AS就可以了。
6.在AS中新建一個(gè)工程,將apk反編譯后的smali目錄下的所有文件拷貝到剛才新建工程的src/目錄下。
準(zhǔn)備工作到這里就OK了,接下來(lái)就要開(kāi)始激動(dòng)人心的反編譯斷點(diǎn)調(diào)試了~
5.開(kāi)始斷點(diǎn)調(diào)試
1.打開(kāi)Android Device Monitor,在終端下運(yùn)行命令:
adb shell am start -D -n {Package Name}/.{Activity}
此時(shí)在調(diào)試設(shè)備上會(huì)顯示等待調(diào)試器接入,在Android Device Monitor上選中DDMS,發(fā)現(xiàn)需要調(diào)試的程序已經(jīng)顯示在列表里面了,我們需要記下它的端口號(hào):本例中需要記下的是8628這個(gè)端口號(hào)(測(cè)試后發(fā)現(xiàn)8700也是好使的)

2.新建遠(yuǎn)程調(diào)試:依次點(diǎn)擊Run-> Edit Configuration->“+”號(hào)->Remote,選中剛才新建的工程,填寫(xiě)上一步中記下的端口號(hào):

3.在工程中找到smali文件相應(yīng)位置處設(shè)置斷點(diǎn)(在想設(shè)斷點(diǎn)的位置前后多設(shè)置幾個(gè)斷點(diǎn)),點(diǎn)擊Run->Debug->Unnamed,其中Unnamed是剛才新建的遠(yuǎn)程調(diào)試的名字。
4.將程序執(zhí)行到斷點(diǎn)的地方,不出意外的話,你應(yīng)該已經(jīng)看到程序被斷住了:

恭喜你!已經(jīng)成功了! 接下來(lái)就好好享受Debug Step By Step的快感吧~
6.寫(xiě)在最后
這是筆者第一次寫(xiě)東西,可能會(huì)有些許疏漏,如有問(wèn)題,歡迎指正~
感謝師父bk,傾囊相授。
文中所用技術(shù)參考阿里無(wú)線安全團(tuán)隊(duì)于2015年04月13日發(fā)表的《解密所有APP運(yùn)行過(guò)程中的內(nèi)部邏輯》一文,由于有了更好的工具,所以步驟也相對(duì)簡(jiǎn)化了一些。