1. 實戰背景
由於工作需要,要爬取某款App的數據,App的具體名稱此處不便透露,避免他們發現並修改加密邏輯我就得重新破解了。
爬取這款App時發現,抓包抓到的數據是加密過的,如圖1所示(原數據較長,圖中有省略),可以看到這個超長的data1字段,而且是加密過的。顯然,對方不想讓我們直接拿到它的信息,選擇傳過來一個加密的字段,而我們要做的,就是解密這個字段。
圖1 數據包截圖
2. 問題分析
既然服務器返回了一段無法閱讀的加密數據,那么必然,這段數據是在客戶端進行解密的。因此,我們要做的就是找出解密代碼,重現它,從而來破解這段加密數據。
所以,我們要做的,就是逆向App→找到解密函數→重現。就這么簡單。
3. 實戰記錄
1) 脫殼
拿到APK后,要做的第一件是就是查殼。如果你第一件事就是用jadx、AndroidKiller、APKTool等各種工具懟的話,那你一定是個愣頭青,鐵頭娃,石樂志。如圖2所示,可以看到這個App是經過騰訊加固的,需要費一番功夫才能拿到源碼。
圖2 查殼
脫殼是一項比較麻煩的工作,脫殼大神可以直接進入下一步,像我一樣的小菜雞建議轉去閱讀《Android逆向基礎篇(脫殼機)》,擁有一部脫殼機可以助你輕松無腦的脫去市面上大多數的殼。
2) 找到解密函數
找源碼是有技巧的,一行一行閱讀的話頭都禿了源碼還沒讀完,因此需要巧用搜索功能。
對於搜索功能,個人十分推薦jadx,它的搜索功能十分強大,但隨之而來的是它對內存的巨大需求。可以看到圖3中,它占了1600多MB內存。
圖3 jadx占用內存
這里分享一下我對於代碼搜索的一些拙見。想破解請求中的加密字段,首先肯定是搜索加密的字段名,但有時候這些字段叫做“token”、“key”等隨便搜搜幾千個的名字,那就很難從幾千個中找出來了。這種情況,可以搜索請求的URL,然后一步步findusage,找出用這個URL的代碼,慢慢抽絲剝繭總能找到的,個人感覺效率直接搜字段名要高。使用URL搜索時不建議輸入整個URL,大多數情況下都會拼接的,找幾個有特征的詞去搜就行了。
對於返回的加密數據,上面這種搜URL的方法就不好使了。圖1中可以看到加密字段叫data1,幸好它不叫data,如果它叫data,那就得從5000多個data中把它挖出來。而源碼中的data1,只有52個,瞬間篩掉了99%的無關代碼。
搜索結果如圖4所示。截全圖的話看不清,因此這里只截取部分。相信有視力5.3英語16級的小伙伴已經發現了,幾個閃亮的、引人注目的“Decode”,decode data1,那還有疑問嗎?肯定是它干的好事呀。
圖4 “data1”搜索結果
在上面隨便找個decode雙擊,然后按住ctrl點擊函數名,就能看到這個decode函數的源碼了,如圖5所示,這個名為eee3DecodeECB的函數,八成就是我們想要找到的解密函數了。
圖5 decode函數源碼
3) 重現
直接把這段代碼復制進Intellij中,效果如圖6所示。
圖6 Intellij截圖(1)
圖6紅的仿佛夢中的A股,股市越紅越好,而代碼則是越紅越不好。我們需要處理這些cannot resolve的東西。
缺啥補啥,先看變量,需要ENCODING,f224IV,SECRET_KEY,不出所料,這幾個都是類中定義的靜態變量,順便把開頭的import也一起復制過來,現在的效果就好多了。
圖7 Intellij截圖(2)
這里的Base64這個包原本是android.util.Base64,在開發安卓時,在Android Studio中直接import就可以了,但在Intellij中直接import是不行的,需要自己把這個包下載一下。
不報錯了,那就寫個main函數解密試試。把抓包抓到的巨長無比的data1復制到main中的data1,然后調用一下剛才重現的解密函數。因為data1實在是長,這里就不復制進去的,請自行腦補。還有,記得一定要寫try。
圖8 main函數
從頭到尾再看一遍我們重現的解密代碼,一切都很perfect,運行走起。看一下運行結果,是一段Json格式的數據,找一個json在線格式化的網站把運行結果復制進行,結果如圖9所示,顯然,完成了對加密數據包的解密
圖9 運行結果
可以看到,經過上述操作,完成了對加密數據包的解密。
4. 總結
上述過程並不復雜,也幾乎沒有任何難點,因此這種加密方式可以說並不合格,甚至可以說有些自欺欺人。加密的本意顯然是為了增加一點破解難度,但我這樣的菜雞也只花了不到半小時就完成了破解,何況專業的逆向大神呢。講真,哪怕把data1這個名字改成data也能增加一些破解的時間成本。
單純的Java代碼加密太容易破解了,建議此類場景還是用So加密更好,畢竟想要把so文件執行起來還是得費一番功夫的。