Android逆向学习---静态分析反调试apk
分析環境:JEB2.2.7+IDA7.0??測試手機:nexus
 IDA7.0下載鏈接
 鏈接:https://pan.baidu.com/s/1xEtjnTVZFuLiMpHKwMOY2Q?密碼:g3v9
一 用jeb反編譯反調試挑戰.apk
 1打開Manifest查看android:debuggable="true" 說明此程序是可以被動態調試的。
 2找到程序入口MainActivity 分析可知程序運行的時候調用了myJNI類中的Native函數checkport并彈框 所以checkport是彈框的內容 看函數名可知里面也有可能做了反調試
 3分析代碼可知程序彈框后說明checkport函數已經執行完了,但是IDA掛起來后程序還是退出,說明還是被反調試了 猜想有兩種情況:
 猜想一: checkport函數中開啟了一個線程循環來做反調試 就算函數執行完 這個線程中的反調試還是運行的 (如果不開啟線程 循環檢測反調試程序主線程將會堵塞 )
 猜想二: 我們知道init_array和JNI_OnLoad會在so加載的時候就開始執行,所以程序也有可能會在這里開啟線程進行反調試。
?
?
?
4.帶著上面的猜想 我們下面來分析下so
二 驗證猜想一
 IDA分析so
 解壓反調試挑戰.apk進入lib文件夾下找到libsix.so并用ida打開??由于我手機支持v7所以這里我打開的是armeabi-v7a下的so
 注意:這里一定要打開手機對應的so 如果手機是arm的就打開armeabi文件夾下的so,支持v7則打開armeabi-v7a下的so 同理x86的要打開x86文件夾下的so進行分析??這里很重要 不然會和動態調試的內存地址不對應
 1.我們先來找到 checkport函數 看看代碼里面到底有什么 按照以前教程中找Native函數的方法 我們打開函數導出表發現并沒有checkport函數 在String窗口搜索恭喜你,挑戰成功!也是搜索不到的說明此字符串被隱藏了??但是發現了JNI_OnLoad函數 說明函數checkport是動態注冊的。
?
2. 怎么在IDA里面找到動態注冊的函數呢?動態注冊的函數一般會在.data.rel.ro.local或data中 Ctrl+s打開segment表??找到.data.rel.ro.local??這個段里面放的是動態注冊的函數 點進去后就找到Checkport函數了 函數的定義在dword_1140中
 ?
 ?
3點進dword_1140發現這部分代碼IDA沒有解析好??這里需要手動解析一下 點住dword_1140右鍵Data轉化成數據 然后鼠標放在__unwind按住P鍵就轉換成函數了 這個函數就是checkport對應的函數
 ?
?
?
?
 4.分析checkport函數 F5轉換成C偽代碼 導入Jni.h (不會導入的看前面的課程) 然后手動解析代碼 提高代碼可讀性 解析完成后Esc返回到C代碼 再按下F5刷新一下代碼 解析的字符串就出來了
?
?
?
 5 通過以上操作可以看到 恭喜你,挑戰成功字符串已經被我們解析出來了 接下來分析這個函數 這個函數會 讀取/proc/net/tcp,查找23946端口,也就是IDA動態調試的端口 如果查找到了說明程序正在被動態調試 然后退出程序 從而達到了反調試的目的。
 但是這里我們看到這個函數的反調試并沒有放到線程中做 說明只執行一次就結束了??而且測試一驗證的時候這里的代碼已經執行完了??所以其他地方一定還有反調試 并且只能在這個函數之前執行。
?
三 驗證猜想二
 init_array介紹
 init_array段是在so加載的時候執行的 執行順序要優先于 JNI_OnLoad??所以這里是最早被執行的函數 把反調試和so的解密放到這里是比較好的選擇。
 1 ctrl+s打開segment表找到.init_array段點進去 發現init_array段里面有一個thread_create函數 點進去F5轉換成C偽代碼 并分析函數
?
?
?
?
?
 2.我們打開命令行窗口來驗證一下 查看當前程序的status文件??ps命令用來列出系統中當前運行的那些進程
?
?
?
 3.通過上面分析可知thread_create函數是創建線程循環讀取當前程序的Tracepid的值 如果值大于0說明程序當前正在被動態調試并退出程序 那么現在就知道為什么在程序彈出恭喜你,挑戰成功框后我們進行動態調試 程序還是會退出了 因為這里開啟了一個線程進行循環反調試。
 4.那么到這里程序的反調試是不是就找完了呢?剛剛我們也說了除了init_array還有一個地方JNI_OnLoad函數也會在so剛加載的時候運行 那么出于習慣 我們還是來看一下JNI_OnLoad函數
四 JNI_OnLoad函數
 1.在函數窗口中搜索并找到JNI_OnLoad函數 F5反編譯成C偽代碼(有點時候導出表里面是沒有JNI_OnLoad函數的 所以這里在函數窗口中搜索)?
?
?
?
?
?
 2.經過上面分析知道 JNI_OnLoad函數中調用SearchObjProcess函數進行反調試??這個函數通過ps列出當前手機的所有進程 然后如果進程名中包含android_server,gdbserver,gdb等名稱 則認為程序當前被動態調試 退出程序
五 小結
 1.首先我們通過JEB工具靜態分析了反調試挑戰.apk 發現在MainActivity類中調用了Native函數checkprot 因為這個函數是動態注冊的 所以我們在data.rel.ro.local段中找到了這個函數 分析知道這個函數會讀取/proc/net/tcp,查找23946端口 如果找到則認為程序當前被動態調試 退出程序
 2 在init_array段里面發現了thread_create函數 這個函數創建了一個線程循環來讀取/proc/pid/status文件下的TracePid的值 如果大于0說明程序正在被調試 退出程序
 3.JNI_OnLoad函數中發現了SearchObjProcess函數通過搜索指定進程名來判斷程序有沒有被調試
六 解決方案一
 1.對于checkprot我們可以通過-p將IDA調試端口改為23947或者其他端口 注意端口轉發和IDA調試的端口號都要改成23947
?
?
?
 2.對于thread_create函數我們可以刷機改內核讓TracePid的值永遠為0?
 3.對抗SearchObjProcess函數可以將android_server改成其他名字然后運行 比如zs ls ww(張三,李四,王5)
七 解決方案二?
 1.也可以通過exit函數定位到反調試位置并patch掉當前函數 這里以thread_create函數為例子 因為此函數在init_array段里面 所以是沒有調用的地方的 這里直接把第二條指令改成pop直接出棧? ?改Hex指令這里我就不為你演示了 前面教程都有教過。
?
?
?
?
?
?
2.對于SearchObjProcess函數 直接找到調用此函數的位置 然后nop掉 或者進函數里面把exit給nop掉都行??最后一處反調試這里也不演示了 方法相同
?
八 另一種patch方法?
以前我們都是用IDA插件modifyfile.plw來patch 其實還有一種patch的方法 直接用IDA Patch Program插件來Patch也是可以的 點菜單Edit->Patch Progra
?
?
?
?
 最后將patch后的so替換原包的so 重打包簽名 運行 即可過反調試。
九總結
 本節課我帶你用JEB+IDA工具靜態分析了反調試APK 通過本節課的學習 你了解了init_array段和JNI_OnLoad函數的執行順序和這三處反調試的找尋方法??對于反調試 當然也可以通過搜尋特征的方式定位位置 比如TracePid反調試可以在字符串窗口搜索/proc/%d/status 檢測進程名可以搜索android_server??檢測端口號搜索5D8A 然后我又帶你重溫了一遍函數Patch的方法 以及第二種保存修改so的方法 通過本節課我想你對反調試技術已經有了初步的了解 教程附件里面前人總結出來的反調試大全 你可以看一看并且學習一下。學習完之后 下節課我將會為你講解怎么動態調試這個apk。。。
 ?
總結
以上是生活随笔為你收集整理的Android逆向学习---静态分析反调试apk的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 【Android测试】MonkeyRun
 - 下一篇: 浙江省机电工程师职称评审条件及流程