PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘。目前又不当COO,还是得用心记代码哦!
日前網上有 MyTV X HTC One HD 版 Android app 流出,但由於程式制约了只有 HTC One 手機才可以使用,大部份用家得物無所用。當然,道高一尺,魔高一丈,很快的就有人放出破解版,解除了這個制约,Android 全機種都可以用了。
他是如何做到破解的呢?這篇文章會拆解一下這個流出來的 apk 檔,並提供一些工具給大家分析代碼,西杰相信這個過程並不困難,大部份 programmer 學一會兒就應該看得懂!(當然並不是全部 apk 檔都可以用统一方法來破解,加了殼的 apk 就比較困難了)
利申:本文章僅供教學用,請勿嘗試公開發佈破解檔案
工欲善其事,必先利其器,這次我們會用到 dex2jar 這個工具,它的用处是幫我們把 apk 爆開成多個 bytecode 檔,我們就是透過修改這些 bytecode 檔來破解 Android app 的了。值得一提的是,dex2jar 的 wiki 已經清晰說明如何把 apk 檔反譯成 bytecode 檔和如何重新打包,讀完以下教學仍不清晰的話可以參考一下。
下載了 dex2jar 之後,我們就能够開始反譯 apk 檔了,dex2jar 提供的例子是這樣:
# convert classes.dex in test_apk-debug.apk to test_apk-debug_dex2jar.jar d2j-dex2jar.sh -f -o test_apk-debug_dex2jar.jar test_apk-debug.apk # verify jar d2j-asm-verify.sh test_apk-debug_dex2jar.jar # convert to jasmin format d2j-jar2jasmin.sh -f -o test_apk_jasmin test_apk-debug_dex2jar.jar
三個步驟,第一步將 apk 檔內的 classes.dex 抽出來並反譯成 jar,classes.dex 就是主程式所在的地方。第二步是驗証 jar 檔(但我不清晰有什麼用,估計是驗証它是不是完整可執行的檔案吧)。第三步是把 jar 檔轉為 jasmin 格式(大概是 Java bytecode 的意思)。
應用在 mytv 上,上列三個 command 應為:
./d2j-dex2jar.sh -f -o ../apk/mytvhd_prod.jar ../apk/mytvhd_prod.apk ./d2j-asm-verify.sh ../apk/mytvhd_prod.jar ./d2j-jar2jasmin.sh -f -o ../apk/mytvhd_prod ../apk/mytvhd_prod.jar
這個時候就應該會有一個裝滿 .j 檔的資料夾,這些 .j 檔就是我們要研讨的 bytecode 檔了。由於 MyTV 程式啟動時就已經會欄截非 HTC One 用家,因此我們當然要看看 MyTV 最開始時的那個 Activity 發生了什麼,到哪裏找呢?manifest 吧,不過說實話,有開發 Android 經驗的 programmer 應該大約估計到那個 Activity 放在何處的吧!就是 com.tvb.mytvhd.activity.StartUpActivity 了!開啟 StartUpActivity.j 後,你會看到一大堆陌生的代碼(估計你不會常常看 bytecode 吧...)
不要緊,你要仔細研讨的話可以到維基看看 Java bytecode 有什麼指令可以用,但這裏就只是快速找尋所需代碼做示範!有開發 Android app 的 programmer,Activity 啟動時執行的是哪個 method(不計 constructor)?是 onCreate!在代碼中搜尋一下吧。
看到了嗎?很短的一個 method,有注意到 229 行的這句嘛?
invokespecial com/tvb/mytvhd/activity/StartUpActivity/error_nonHTC()V
又什麼什麼 invoke,又什麼什麼 error_nonHTC ,還不是我們要找的東西!?仔細研讨一下上文下理。
執行 isHTCOne(),ifeq 就是如果結果等如 0 (false) 的話就跳到 L0,而 L0 就是執行 error_nonHTC(),很明顯就是要用來告訴用家它不是 HTC 機然後退出程式,那要如何改呢?方法有二:一,ifeq 轉為 ifne,那麼不是 HTC One 就能够看到,反而 HTC One 看不到;二,把整段檢查代碼刪掉,速度還可以快一點不用檢查!來試試方法二吧。
只要把相關的 ifeq 和 isHTCOne() 以及 L0: 下的檢查代碼刪掉便可!
重新打包 apk 檔,可用以下 command!
# build jar d2j-jasmin2jar.sh -f -o test_apk_jasmin.jar test_apk_jasmin/ # verify jar d2j-asm-verify.sh test_apk_jasmin.jar # convert to dex d2j-jar2dex.sh -f -o classes.dex test_apk_jasmin.jar # make a copy cp test_apk-debug.apk test_apk-debug-toast.apk # replace classes.dex in test_apk-debug-toast.apk zip -r test_apk-debug-toast.apk classes.dex # sign the apk d2j-apk-sign.sh -f -o test_apk-debug-toast-signed.apk test_apk-debug-toast.apk
把例子中的檔案名換成相對應的 mytvhd 就能够了!
#把 jasmin 代碼重新打包成 jar 檔 ./d2j-jasmin2jar.sh -f -o ../apk/mytvhd_prod_new.jar ../apk/mytvhd_prod #驗証一下 ./d2j-asm-verify.sh ../apk/mytvhd_prod_new.jar #把 jar 檔變成 Dalvik VM 的 dex 檔 ./d2j-jar2dex.sh -f -o ../apk/classes.dex ../apk/mytvhd_prod_new.jar #複製一份新的 apk 以免改動原有 apk cp ../apk/mytvhd_prod.apk ../apk/mytvhd_prod_new.apk #把新的 dex 檔放到 apk 中,代替原有的 classes.dex zip -r ../apk/mytvhd_prod_new.apk ../apk/classes.dex #sign apk ./d2j-apk-sign.sh -f -o ../apk/mytvhd_prod_new_signed.apk ../apk/mytvhd_prod_new.apk
失敗了,為什麼!?呵呵,西杰第一次嘗試就為這個蠢問題花了不少時間,原因其實很簡單,把新的 apk 解壓縮一下就能够看到問題。
看到嗎?有兩個 classes.dex,是 zip command 用錯了,classes.dex 應該要放在根目錄才可以,那解決方法呢?很簡單,把 apk/classes.dex 拉出來放在根目錄然後再 zip 一次和 sign 一次就好了。
成功了!其實破解軟件沒有大家想像的那麼難,現成工具已經做得很好,只要花少許時間分析一下人家的代碼就能够了。當然,我還是那句,本篇文章只是為了教學,研讨一下 apk,看看如何做逆向工程,並不是要你們把世界間的軟件都破下來,請尊敬別人!
參考:
https://code.google.com/p/dex2jar/wiki/ModifyApkWithDexTool
http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
http://dukeland.hk/2013/05/13/android-apk-reverse-engineering-cracking-the-mytv-hd-restriction/
文章结束给大家分享下程序员的一些笑话语录: 人在天涯钻,哪儿能不挨砖?日啖板砖三百颗,不辞长做天涯人~