現建立了一個Android開發水友圈,圈內會不定時更新一些Android中高階的進階資料,歡迎大家帶著技術問題來討論,共同成長進步!(包含資深UI工程師,Android底層開發工程師,Android架構師,原生效能優化及混合優化,flutter專精);希望有技術的大佬加入,水圈內解決的問題越多獲得的權利越大!
本文介紹Android app程式碼(java + ndk)的反除錯的方法和保護程式碼增加逆向難度的一些基本方法。
Android自問世以來得以迅速發展,各大手機廠商紛紛投入成本開發、設計開發自己的Android系統,從2016年開始,Android已經超越ios成為全球最有影響力的作業系統。針對於Android app的逆向方法和逆向工具很多,所以反除錯對於Android的程式碼保護扮演著很重要的角色。本文從四個方面介紹一下Android反除錯的一些方法。
ps:反除錯並不能完全阻止逆向行為,只是在長期的攻防戰中給破解人員不斷的增加逆向難度。
Java:(1)Proguard藉助Android studio的proguard工具,對Java程式碼分別進行壓縮(Shrink)、優化(Optimize)、混淆(Obfuscate)、檢查(Veirfy)。
壓縮(Shrink):去掉程式碼中無用的類、函式方法和欄位。
優化(Optimize):對Android的可執行檔案dex進行優化,去掉無用指令。
混淆(Obfuscate):用毫無意義的欄位對程式碼的類名、函式名、變數名重新命名,比如用a, b, c這種。
檢查(Veirfy):對混淆後的程式碼進行檢查。
經過Proguard後,程式碼程式依然可以重新組織和處理,處理後的程式邏輯與之前完全一致,而混淆後的程式碼即便反編譯後依然很難閱讀。同時,在混淆過程中對於一些不影響正常執行的資訊將永久丟失,這些資訊的丟失使得程式更加難以理解。
同時,Proguard還可以控制對某個類混淆,以及對某個類的某些函式方法混淆。
下圖是一張混淆前和混淆後的對比圖:
混淆前:
混淆後:
(2)isDebuggerConnectedAndroid Debug類提供isDebuggerConnected函式,函式原型如下:
在VMDebug類裡的isDebuggerConnected的具體實現在ndk程式裡。
這裡暫且不跟進該函式,總之,isDebuggerConnected函式用於檢測此刻是否有偵錯程式掛載到程式上,如果返回值為true則表示此刻被除錯中。用法很簡單,如下:
(3)android:debuggable屬性在Android的AndroidManifest.xml清單檔案的application節點下加入android:debuggable="false"屬性,使程式不能被除錯。在Java程式程式碼裡也可檢測該屬性的值,如下:
NDK:
(1)ptrace函式Linux核心的ptrace函式原型:
ptrace可以允許A程序控制B程序,並且A程序可以檢查和修改B程序的記憶體和暫存器。但是一個程序只能被一個程序除錯,所以根據這個特點,可以讓程序自己ptrace自己,傳入的request設定為PTRACE_TRACEME,程式被自己附加除錯後,其他的除錯操作就會失敗了。
(2)檔案節點檢測一旦程式處於被除錯狀態,Linux會向程序的節點寫入資料,比如/proc/<pid>/status內容中的TracePid會寫入除錯程序的pid,如果TracePid的值不為0,就表明程序處於被除錯狀態了。
此外,通用的檢測邏輯還有檢測除錯的埠號,Linux的檔案節點/proc/net/tcp會記錄著正在執行的程序的本地的埠號,除錯工具IDA的預設的除錯埠是23946,通過讀取/proc/net/tcp內容,檢測是否有23946,如果找到了就表明程序處於被除錯狀態了。
(3)InotifyLinux的Inotify用於檢測檔案系統變化。它可以檢測單個檔案,也可以檢測整個目錄。
逆向最常做的一件事就是dump 記憶體,使用dd命令(或者如果使用gdb的話為gcore命令),dump掉/proc/<pid>/mem或/proc/<pid>/mpas或/proc/<pid>/pagemap的內容。
這裡,就可以使用Inotify API對上述三個檔案監控,如果有發現開啟、讀寫操作,極大概率就是程序正在被破解。
(4)so檔案hash值檢測so檔案在被JNI_Onload載入後,so檔案的函式的指令是固定的,若被偵錯程式掛載,下了斷點後指令會發生改變(斷點地址會被改寫為bkpt指令),計算記憶體中載入的so的hash值,進行校驗檢測函式是否被修改或被下斷點即可判斷出是否被除錯狀態。
(5)時間差檢測一個取巧的方法,正常情況下,一段程式在兩條程式碼之間的時間差是很短的,而對於除錯程式來說,單步除錯中的程式兩條程式碼之間的時間差會比較大,檢測兩條程式碼之間的時間差,可以大概率判斷程式是否被除錯。
Resource資原始檔:Android資原始檔經常被惡意篡改,植入各種廣告,外掛,嚴重影響了Android app生態平衡。
APK簽名檢測Android SDK中有apk 簽名檢測的方法,Framework的PackageManager類提供了getPackageInfo()函式,函式原型:
第二個引數傳入GET_SIGNATURES時,返回物件的signature欄位就是簽名信息,計算其hash值,前後對比hash值。實際可用的兩種方案:
(1)在本地Java程式碼裡進行校驗,不一致則強退應用;
(2)把簽名信息發到伺服器後臺,伺服器後臺記錄著正確的簽名信息,比對後不一致則返回一個錯誤給錯誤。
上述即為對於Android app的反除錯,程式碼保護的一些基本策略。
- 零基礎安卓開發起步(三)
- Android程序管理:Framework層概念
- 僅 2 位 Java 開發,使用小程式上線一款 App
- 使用VSCode 打包你的第一個flutter應用(安卓篇)
- 阿里面了9次,位元組撈了offer?Android開發狗25次大廠面試辛酸淚
- 方舟編譯器是將java程式碼像C++靜態編譯,那麼為什麼安卓當時一開始為啥不用C++?
- 專科渣校,嘔心瀝血在家3個月“拿下”330頁PDF,終於拿下阿里OFFer
- 神一樣的操作,真的牛逼了!Android Jetpack Compose 最全上手指南
- Android開發者必知的記憶體、效能優化細節
- Android面試官:你究竟有多大的勇氣,在簡歷上寫了“精通”?