標籤:ini crackme 工程 輸入 查看 library 工程路徑 語言 結構
現在很多 apk 在開發中為了保證代碼不被輕易逆向出來會對關鍵代碼採用 ndk開發的方式。
什麼是 Android NDK?
Android NDK(Native Development Kit )是一套工具集合,允許你用像C/C++語言那樣實現應用程式的一部分。同時,Android NDK對於Android SDK只是個組件,它可以幫我們產生的JNI相容的共用庫可以在大於Android1.5平台的ARM CPU上運行,將產生的共用庫拷貝到合適的程式工程路徑的位置上,以保證它們自動的添加到你的apk包中。
所以學會分析 .so 檔案(載入流程、方式等)對安卓逆向來說是比較重要的。
那so一般如何分析java層函數調用:
通過System.loadLibrary找到該方法對應的so檔案,使用ida載入後尋找匯出函數,native函數註冊的兩種形式:
靜態註冊:java_xxx_xxx_xxx_類名_方法名(參數)
動態註冊:RegisterNatives
Android 對 .so 檔案載入時首先會查看 .init 或 .init_array 段是否存在,如果存在那麼就先運行這段的內容,如果不存在的話那麼就檢查是否存在 JNI_Onload 存在則執行。
實際分析一個CrackMe.apk吧。
1)反編譯 apk 檔案得到 smali 代碼
分析後可以看到調用了 .so 檔案裡定義的 check 函數,然後這個 check 函數又和 button 的 OnClick 事件綁定,可以判斷 check 則是判斷使用者輸入 key 是否正確的函數。
2)用 IDA 對 libqtfreet.so 進行分析
首先先看看有沒有 JAVA_com_qtfreet_crackme001_check 這樣類似的函數,如果存在的話就說明 .so 檔案裡面沒有對 check 函數進行動態註冊,JAVA_com_qtfreet_crackme001_check 就是 smali 裡面調用的 check 函數原型,直接分析即可。
如果沒有發現上面類似函數的話則說明 smali 調用的 check 函數進行了動態註冊,此時需要找到註冊的位置。
因為 .init 或者 .init_array 在 IDA 動態調試的時候是不會顯示出來的,所以需要靜態分析出這兩段的位移量然後動態調試的時候計算出絕對位置,然後在 make code(快速鍵:c),這樣才可以看到該段內的代碼內容。
查看 .init_array 段的地址有兩種辦法:
1.可以使用 IDA 載入 .so 檔案,建立 “Segments” 視圖,這裡會列出不同類型的程式碼片段資訊,如所示。
2.可以使用二進位工具 readelf 來查看 .so 檔案的結構,在 OS X 上面可以使用 greadelf 代替。
3)可以看到這裡兩個都指示 .init_array 存在,並且位移量為 0x20790,IDA 定位到該位置查看。
.init_array 執行完之後就跳到 JNI_Onload 裡面執行,IDA 跳到 JNI_Onload 之後 F5 查看虛擬碼。
看到高亮的 RegisterNatives,進去第三個參數 off_21458 位置查看儲存的內容。
4)可以看到這裡最後執行了一個 memcmp 所以可以確定 sub_8A64 開始是關鍵的判斷代碼,直接將 memcmp 的傳回值修改即可成功破解 crackme。
Android 逆向實戰(一)