劉龍錦 張志杰 梁世民


關鍵詞:Android;Jadx;逆向
1引言
Jadx工具是一款反編譯利器,支持命令行和圖形化界面,能夠以最簡單的方式完成APK的反編譯工作,反編譯后的代碼可閱讀程度極高,同時擁有強大的搜索定位功能,可以極大地提高反編譯后閱讀代碼及尋找關鍵代碼的效率。本文以句讀APP為例,對Android APP逆向進行了研究。
2環境介紹及逆向思路
本文使用的句讀APP版本號為V4.5.0,在豌豆莢上發布時間為2022年01月13日。抓包工具為Progress Telerik Fiddler Classic V5.0。模擬器為夜神Android模擬器V7.0.3.0(安裝Xposed框架,JustTruseMe模塊)。
逆向的思路一般為:(1)對應用進行抓包分析;(2)使用JADX反編譯APK程序;(3)使用JADX尋找分析關鍵函數;(4)使用編程語言還原通信協議算法。
3抓包分析
句讀APP在防抓包層面未做有效的防護,使用常規抓包環境即可抓取,對sentences/random接口進行抓取,得到以下數據。
GET:
https:
∥judouapp. com/api/v2/sentences/random?
newbie= true&system_version=7.1.2&platform=android&device_ type=MI9&app—key=fd13a4la-a194-4650-aOb2-56ld4b3187lc&device—id=458d834d-ee47-7f34-c5d4-8cle6bf825f3&signature= 7a602ae13dbfda013f23f5311948134l&version= 4.5.O×tamp= 1657659250&version_code= 1057&channel= ch_huawei
經多次抓取發現,句讀APP的API接口公共參數為system—version, platform, device—type,app _key,device_ id,
signature,
version,
timestamp,
version一code,channel。signature的值為動態計算,timestamp的值為當前時間戳,其他參數為固定值。抓包過程中并未發現上傳日記等操作,可以暫時推斷句讀APP的風控系統主要是對signature參數值計算,計算正確值即可獲取服務端正常的數據返回。
4反編譯APK
使用Jadx工具打開句讀APP,通過Jadx返回的源文件列表判定句讀APP使用了Tencent的安全加固服務,需要進行脫殼后才能得到Dex文件,使用FDex2的Xposed進行脫殼得到對應的Dex文件后導出到桌面,拖人Jadx進行分析即可。由于反編譯后的Dex文件較多,在分析時會稍微麻煩,因此得到啟示:使用加固平臺及對APP進行多Dex文件處理可以提高APP的安全性,延緩攻擊者破解的速度。
5分析關鍵函數
多數APP使用okhttp庫進行網絡請求,okhttp庫處理公共參數的方法一般為實現Interceptor接口,所以可以直接搜索Interceptor關鍵字,從而快速定位添加公共參數代碼位置[1]。通過分析定位到句讀APP添加公共參數的代碼的dex文件,使用Jadx工具打開該文件,搜索關鍵字“Interceptor”,得到圖1所示數據。
排除okhttp開始的節點,最終只剩下tech開頭的兩個節點,再根據關鍵字network推斷最后一個節點可能性最大,進入tech.caicheng. judourili. network.g類中,閱讀代碼,在intercept方法中發現了相關代碼,如圖2所示。
signature參數由aVar.c方法計算得出,此方法傳人了兩個參數,一個是固定字符串,另外一個為HashMap類型的容器。首先,確認HashMap的數據內容,閱讀tech.caicheng.judourili. network-g類的代碼,通過Jadx分析出HashMap的內容為兩種形式,一種是CET方式請求數據,另一種是POST方式提交數據。如果是CET方式提交數據,則把URL中的鍵值對參數拆分并依次加入HashMap;如果是POST方式提交數據,則把RequestBody中的鍵值對參數依次加入HashMap。其次,判斷是否已經登錄,如果已經登錄則把token加入HashMap。最后,把公共參數加入HashMap即可。
確認aVar.c方法的代碼,閱讀反編譯后的代碼得知aVar為s.a類型,從導包代碼中確認s.a類型來自tech.caicheng.judourili. util.s類中,但是在此Dex文件中并未發現有對應的util包,由此推斷util包存放在別的Dex文件中。經過一個個文件的打開尋找,確認tech.caicheng.judourili. util包存放的Dex文件后使用Jadx打開。
閱讀該Dex文件代碼,分析出c方法的大致邏輯為判定參數str,hashMap不為空之后,取出hashMap的鍵名做數組排序,再將鍵值以“鍵名=值”的形式加入arrayList,最后加上secret_key= strc此處的str為參數str也就是一個固定字符串),全部加入數組之后,再調用m(1())方法,所以我們需要繼續向下閱讀I(1())方法。
l方法的代碼比較簡單容易理解,遍歷list,在每一個元素后面加上字符串“&”,最后返回一個字符串。
m方法代碼也比較容易理解,大致的流程為:判斷str參數不為空,長度不為0之后,進行md5加密,返回加密后的字符串,該字符串就是signature參數的值。在代碼中看到有一行代碼為byte[]bytes=str.getBytes( d.a),此處需要確定d.a參數,在m方法中并未發現有定義d.a,可以推斷d.a為類成員變量或者為其他類的靜態常量,在導包代碼處發現了導包語句import
kotlin. text.d,可以確定d.a為系統常量,再根據getBytes方法所需要的參數可以斷定d.a為字符串類型,即應該是文字的編碼格式,大概率為utf-8,最終的值在還原算法是再確認即可。至此,加密的流程已經走完,接下來還原該參數的計算方法。
6還原加密算法
上述分析步驟得出計算signature參數主要需要還原m,l,c三個方法,得益于Jadx強大的反編譯功能,反編譯后的代碼還原程度非常高[2],接近于源代碼,所以還原加密算法大致的流程為:復制Jadx中的代碼,導人需要的包,處理程序中的錯誤即可。
(1)還原m方法,在Jadx中復制m方法代碼,手動修改d.a為UTF-8,去除i.d方法的代碼、@NotNull代碼之后,最終還原的代碼為:
(4)對還原的代碼進行測試,測試需要構建數據請求,參照文中抓包數據的例子構建即可,只需要判定加密后的字符串與抓包的加密字符串是否一致,發送請求后句讀APP的服務器正常返回數據即可。句讀APP請求的Header參數中并未有其他值,爬取句讀APP的數據,拼接好URL發送到句讀APP的服務器即可,測試代碼如下:
7結束語
得益于Jadx工具強大的反編譯功能,面對加密算法在Java層的應用,Jadx可以方便地還原加密算法。如果攻擊者有一定的編程經驗,還原APP的加密算法所需要的時間不會太長。從本次逆向分析得到了很多寶貴的經驗,為設計APP的風險控制系統提供了必要的理論實踐基礎,在設計移動風險控制系統時,APP端應該著重注意以下事項:(1)對于生成的device_id應該做合法性校驗,限制每一個device_id單位時間內請求次數;(2)應在合理、合法范圍內收集用戶的行為數據并上傳到服務器分析,從而判定用戶發送的請求是否合法;(3)盡可能不要使用常規的MD5加密算法進行加密,可以使用AES,RSA等高級加密算法;(4)簽名加密算法盡量放到SO層計算,在SO層也要做好代碼混淆以及采用OLLVM等防護手段。