如何脫殼加固過的Apk並利用其API「走近庫」

0x00 尋找突破口

打開首頁,emm 就一個登錄頁面,沒了 隨便寫點東西提交看看

天生手欠的我一不小心就多輸了一個單引號

WDNMD,除了數字和字母其他都不行? 這叫我怎麼測? 剛剛要放棄,就在這時,首頁的一個二維碼吸引了我 正是安卓端的軟件,眼前一亮,彷彿找到了打開新世界的大門

開開心心地把軟件下載過來,想反編譯找找看有什麼可利用的接口

360加固? fa?!

我以為上帝關上了我的門,還會留個窗給我,結果還是無情地把窗給我鎖上了

0x01 zjDroid脫殼

刀不鋒利馬太瘦,你拿什麼工具和我斗。 我們已經知道不論是利用什麼方法加固apk 若要讓軟件要正常運行,就必須讓程序最終加載原dex文件,這樣的話,如果我能dump出內存中已經加載的dex 就可以無視在加載dex前的一大堆解殼操作 而ZjDroid就可以做到這一點,ZjDroid是一款基於Xposed開發的插件,它可以輕鬆地hook住所有的activity,並且將軟件當前加載的dex寫出

在github上fork其源碼,進行分析 有進行過Xposed插件開發的大佬們都知道,想讓Xposed加載你編寫的插件的核心代碼 就必須在assest/xposed_init文件內寫入你想要加載的核心代碼的所在包

進入ReverseXposedModule類

可以看到圖中兩處紅線標記處 因為我們的目的是Dump處dex文件,所以先對第二處紅線標記處進行分析 跟進DexFileInfoCollecter的start方法

通過觀察代碼可知,第一處紅線標記處程序利用反射找到了系統DexFile類的openDexFileNative方法 這個方法和系統加載dex文件有關,這裡不深入分析 接着看第二處標記處,程序調用Xposed模塊的hookMethod方法hook住了openDexFileNative方法 繼續看第三處,在hook完成之後,只要系統調用到了openDexFileNative方法,紅線處的代碼就會執行 第三處紅線處的代碼用於獲取加載的dex的信息,這裡不深入分析 也就是說,只要用戶打開某個app,系統調用dex文件的方法就會被執行,那麼ZjDroid只需要hook住系統調用dex文件的方法,就可以在軟件加載原dex後做任何事情了! hook加載dex方法的代碼已經執行完畢

我們回到ReverseXposedModule類中的第一處紅線標記處,進行分析 跟進其調用的initModuleContext方法

查看第一處標記,程序同樣的找到了Application類的onCreate方法 開發過app的大佬們都很熟悉這個onCreate方法吧,這是每個軟件在啟動時默認最先執行的方法 這裡ZjDroid同樣對系統的Application類的onCreate方法進行了hook,換句話說,只要用戶點開任何一個軟件,都能被程序hook住 同樣的,程序也是利用hookMethod進行的hook操作,hook後的操作在ApplicationOnCreateHook類中,跟進代碼

可以看到程序給每個被hook的app註冊了一個廣播,跟進代碼

分析代碼可知,當被hook的app接收到含有com.zjdroid.invoke字符的廣播時就會進入判斷 程序將提取出廣播中鍵為"target"和"cmd"的值 通過圖中第二處紅線下方的代碼可知target就是app的pid號 在獲取cmd的值後,cmd的值將被傳入CommandHandlerParser類中 跟進代碼

觀察代碼可知cmd的值就是一個json格式的字符串 程序將根據json中的值對應地執行操作 我們需要dump出dex文件,假設我發送的廣播進入了ACTION_DUMP_DEXFILE分支 程序將向DumpDexFileCommandHandler類傳入指定值,跟進代碼

其中紅線標記處就是dump dex文件的核心代碼了 跟進

查看其中紅線處,data成員調用的方法就是dump出內存中dex文件的代碼,接着程序將data寫出到指定目錄 遺憾的是,紅線出的代碼為native層的代碼,而native層的代碼作者並沒有開源 編譯,運行 踩坑注意:這個工具的so文件似乎在5.0以上的安卓系統不起作用,所以我特意刷了一個4.4的安卓再去安裝ZjDroid 在手機的Xposed中啟用此插件,然後打開需要脫殼的app adb shell dumpsys activity top查看最頂層活動的PID號 接着發送廣播dump出dex

dex被成功dump、

0x02 尋找接口

查看軟件的入口 打開指定類 未加殼的dex成功被加載了! 我現在看到的是原dex的代碼,而不是殼dex的代碼!

可以看到onCreate方法為native層方法,但是接着往下看 getInfo方法中有一個利用post請求調用的登錄接口 請求一下看看什麼情況

WTF?返回的實體中告訴我無權調用此接口?! 難怪把onCreate方法放在native層里!一定是在onCreate方法中需要進行什麼操作才能正常調用此接口 可native層的代碼實在是無能為力 本打算就這麼放棄了,最後一次在代碼中搜索可能存在的接口

其中一處接口讓我眼前一亮

WTF?!WTF?!居然可以請求!還沒有過濾特殊符號?! 管理員還真是粗心

丟到sqlmap里

收工!

ps:具體細節不做演示,本文僅限圈內技術交流禁止用於非法用途!