由於某個機緣,我拿到一個賽車app,玩了一會想買個裝備,竟然要我掏錢包,做爲一名cracker,我以爲個人尊嚴受到了嚴重的蔑視(無奈錢包空空),我以爲要捍衛我那脆弱的玻璃心(錢包),因此,開幹吧。我搜索了網上相關的帖子,發現這個apk的破解都是講了關鍵點都在哪裏,沒有具體的關鍵點查找思路,因此我從新本身破解了一次,中間屢次誤入歧途,我把本身的詳細思路發在這裏,與全部的菜鳥共勉。html
Android killer v1.3.1.0 -- 用於搜索字符串和重打包,下文使用縮寫AKjava
Apktool Box v1.6.4 – 用於獲取調試啓動命令,下文使用縮寫ABandroid
小米5 MIUI9.5.1.0 android7.0 – 用於運行apk程序員
Android Studio 2.3.3(安裝 smalidea-0.0.5插件) – 用於調試smali源碼,下文使用縮寫AS編程
Jadx-gui 0.7.1 – 用於查看smali反編譯源碼,其實AK也有反編譯功能,可是AK的反編譯有的地方沒有jadx好看,我發現switchcase結構AK老是翻譯成ifelse結構。網絡
使用AS調試smali須要apk設置調試標識(否則AS會顯示錯誤:Unable to open debugger port (localhost:7800): java.net.SocketException "connection reset"),用AK打開apk,從工程管理器欄打開文件androidmanifest.xml,在application項添加以下代碼:app
1
|
android:debuggable="true"
|
以下圖:tcp
而後選擇菜單android->編譯,重打包APK。並安裝到米5裏面。ide
使用AB打開apk,點擊啓動命令按鈕生成調試啓動命令,函數
將上圖中下面的命令拷貝到cmd中,啓動apk,手機中apk會停在調試啓動界面。而後查看apk的進程PID,
而後使用adb命令轉發調試到tcp端口8700,以下:
接下來,使用AS創建smali源碼的工程,並配置調試端口,這部份內容網上有現成的教程,這裏就很少說了,創建完了以後,點擊調試按鈕,AS下面顯示日誌以下表示啓動調試成功:
到此,調試環境搭建成功,下面開始破解。
老思路,先是試用一下。點擊遊戲的購買,會彈出一個購買的框,須要輸入手機號和驗證碼,這裏隨便輸入一個手機號和驗證碼,點擊確認支付,不出意外會失敗,並彈出一個提示框:
好了,這是個人第一個第一個失敗點。個人思路是,既然它給了這個錯誤提示,那麼顯示這個錯誤的地方確定有支付成功和失敗的邏輯,那麼我修改了這個邏輯,就能夠了。OK,下面就是如何找到這個判斷的邏輯。沒錯,字符串查找,最傳統的方法,在android裏面搜字符串,不能直接搜漢字,須要將它轉爲unicode碼,而後將「短信驗證碼驗證失敗」轉換爲unicode碼,則爲「\u77ed\u4fe1\u9a8c\u8bc1\u7801\u9a8c\u8bc1\u5931\u8d25 」,結果沒有找到,好吧,是否是字符串拼接出來的呢,短一點,搜「短信驗證碼」,而後有了搜索結果
很差意思,我是小菜看不懂smali,將其轉換爲java源代碼,
原函數太大了,這裏只貼了一部分,看着邏輯真不像,那麼究竟是不是這個邏輯呢?驗證的辦法很簡單,在這裏下個斷點,而後,沒有斷下來。那麼在函數入口下個斷點,仍是沒有來。好吧,這個思路以失敗了結。後來跟蹤代碼我才知道這個支付框是從so裏面彈出來的。嗚嗚。。
以前搜過相似的帖子,帖子說是搜字符串「支付成功」,因此我將字符串轉化爲unicode碼,到AK裏面去搜索,而後搜索到三個結果:
一樣,驗證這裏是否是判斷是否支付成功的邏輯代碼,在每一個字符串所在的函數頭部設置斷點,這裏沒有在字符串所在的位置設置斷點是由於我是不會掏錢包的,全部的操做都是支付失敗的操做,支付成功的代碼邏輯確定是不會來的,因此在函數頭部設置斷點,而後,點擊確認支付沒有斷下來,可是當我點擊關閉按鈕時,卻成功的斷在了第一個函數中。這是意外的驚喜。而後使用jadx查看這個函數的邏輯:
代碼的邏輯很清晰,檢查參數resultCode的值,而後判斷是否支付成功,因此這裏頗有可能就是我要的關鍵代碼邏輯。驗證一下,把全部的switch結構都改爲到case1分支。Smali代碼的語法是把全部的case放到一塊,以下
上面代碼的意思是將switch裏面的值與1比較,結果爲0則跳轉到pswitch_0標號,結果爲1則跳轉到pswitch_1執行,因此這裏把全部的標號都改成pwtich_0,並在下面添加一行,這樣默認狀況也會跳轉到pswtich_0,即三種無論resultCode爲什麼值,都會跳轉到成功的分支,以下:
最後,編譯重打包,安裝測試,成功,OK。至此,成功破解了這個app的內功功能。
其實,當初我並無按下支付框的關閉按鈕,因此我走的是另外一條思路,若是看到這裏你還有耐心,能夠看下個人彎路,哈哈。
思路三:個人彎路
當在三個「支付成功」字符串所在的函數設置斷點,點擊手機上確認支付按鈕時,三個斷點都沒有來。而後我換了搜所的字符串爲「支付失敗」,而後搜到6個結果
我在6個結果的字符串所在的函數頭部設置斷點,點擊確認支付按鈕,結果全部的斷點都沒有來。後來我就去網上搜帖子,見到有帖子說「支付失敗」所在的一個函數checkPayResultTest的調用者在用戶點擊購買時被調用。因此我轉變了思路,放棄了直接查找判斷是否支付成功的代碼,而是查找能在支付過程當中會被執行到的函數,而後我能夠從這個函數跟蹤到判斷支付的代碼。使用jadx打開apk,定位到函數checkPayResultTest,右鍵find usage,
而後查看其調用函數,
在此函數的頭部設置斷點,當我點擊購買時,程序斷在了這裏。這是個喜訊。此時,我發現手機上的支付框尚未彈出來,因此我想,我能夠從這裏跟蹤下去知道支付框彈出,而後找到確認支付按鈕的回調。因而我一路F7單步步入跟進去,當調試跟蹤到下圖中的紅線標識部分時我跟不進去了:
經過查資料我才知道,這是jni調用,我這才知道了,爲何我以前設置的失敗斷點都沒有來,緣由最後掉用到so庫裏了。那怎麼辦,難道我要算調試so文件麼?而後我仔細觀察了這個函數調用,發現這裏有個回調,因而我找到回調定義的地方,
哈哈,是否是很眼熟,在回調裏面設置斷點,而後此次我鬼使神差的點擊了支付框的關閉按鈕,而後斷下來了。哈哈。再而後的操做就如同上個思路同樣了。這就是個人彎路了。
這裏怎麼說呢,其實也不算是程序的漏洞,而是程序員的一種編程習慣。我稱之爲「漏洞」,經過這個「漏洞」能夠定位到支付功能必須執行的某些代碼。思路是這樣的,我發如今程序的代碼中有不少調試日誌輸出,我若是能修改程序輸出日誌,那麼當我使用支付功能的時候,相關代碼會輸出相關調試信息,而後我搜索輸出的字符串,不就能夠定位到支付功能必定會調用的代碼嗎!
首先,隨便找一段代碼,看看它是如何輸出的,
從上圖能夠看出,調試信息的輸出是經過一個叫LogUil.iT函數實現的,找到這個函數:
這裏會看到,代碼中有個DEBUG標誌,若是此標誌爲真則輸出調試信息,而後找到這個標誌賦值的位置:
原本覺得這個標誌是會在構造裏面賦值的,沒想到竟然是判斷sdcard路徑下有沒有alg,哈哈,那就更簡單了,我在手機的sdcard下面放了一個alg文件,
而後打開DDMS,啓動程序,點擊購買,DDMS日誌視圖裏面發現以下信息:
到AK裏面去搜索字符串「支付接口被遊戲調用」,哈哈,有一條結果:
轉到java源代碼:
在AS中對應位置下斷點,程序成功斷下來啦。哈哈。
雖然走了不少的彎路,可是也發現了不少有趣的東西。例如經過日誌來定位代碼,so中彈出對話框是沒法在java中找到關鍵點的,要多試幾種別的操做。
附件太大,這裏給個連接吧:https://pan.baidu.com/s/1P40TZLvJXV727-mlJLNIdA
本帖子若是引發任何其它負面的影響,請版主直接刪帖便可。
若是轉載,請聲明來自看雪。