IDA調試android so的.init_array數組



參考: http://www.itdadao.com/articles/c15a190757p0.htmlhtml


一. 爲何要調試init_arrayjava

init_array的用途android

1. 一些全局變量的初始化 (我這裏試過, 一些全局變量的初始化,會統一用一個init_array表項來完成初始化)數組

2. 經過__attribute__ ((constructor)) 聲明的函數 (能夠定義n個)ionic

經過so加載流程來看,init_array是咱們程序代碼能夠控制的最先的時機了, 其次才加載Jni_onload函數

因此有些樣本會在init_array作一些反調試和相關環境檢測的活, 因此咱們須要在init_array中和對方兵戎相見
spa


固然網上已有不少教咱們如何在init_array下斷的函數, 可是卻都只教了方法, 沒有細說原理, 最後咱們可能只學會了幾個快捷鍵, 空有招式卻無內功, 知其然殊不知其因此然, 下面咱們就姿式和知識這2方面來進行討論操作系統


二. 斷init_array的姿式3d

1. 定位調試進程中linker的dlopen函數地址指針

把調試機器中的linker拷貝出來, 路徑爲/system/bin/linker, 而後開一個IDA分析

在Shift+F12在字符串窗口中查找"dlopen", 跟蹤引用到一個函數, 以下圖

 獲得其文件偏移爲0xF30


附加上調試器後, 咱們獲得linker加載到內存的起始地址爲400BD000 

 因此咱們在代碼窗口Go過去看看400BD000 + F30 = 400BDF30


發現所有是DCB形式的代碼(代碼沒有解析出來), 這個時候咱們須要對linker進行分析, 操做以下: 右鍵->Analyze Module


go過去咱們發現和靜態分析中的同樣,  在函數頭部下一個斷點

  


2. 定位到calling相關代碼

一樣在拷貝出來的ida搜索字符串calling


一樣定位到代碼,獲得文件偏移 2720


那麼咱們內存中的地址就是 400BD000 + 2720 = 400BF720

一樣在調試的ida中下好斷點, 第2個斷點就是調用.init_array數組的代碼

  


而後按F9,注意觀察寄存器窗口, 當有顯示調試的是你想要斷的so的時候開始注意

當斷點斷在BLX R4的時候,下一步就是調用init_array數組了, 因此F7跟進去

 


在直接把咱們想要分析的so拖到ida分析進行驗證, 代碼同樣, 說明咱們成功的斷點在了init_array數組

 


二. 斷init_array的知識

經過上面的操做咱們學會了招式, 內功心法卻不見修習, 下面咱們經過Android的系統源碼來一探究竟


環境介紹

源碼環境: Android 6.0.1

沒有下載源碼的同窗能夠去androidxref在線看源碼也很方面

http://androidxref.com/


1. 回到源頭看問題

咱們都知道咱們要在apk中要加載一個so咱們能夠經過

System.loadLibrary("libname");  

System.load("lib_path");                  

這2者區別以下:

(1). System.load參數必須爲庫文件的絕對路徑,能夠是任意路徑;

(2). System.loadLibrary參數爲庫文件名,不包含庫文件的擴展名,必須是在JVM屬性Java.library.path所指向的路徑中,路徑能夠經過System.getProperty('java.library.path')


2. java層到native層的過程

咱們把android_source\libcore\luni部分的源碼做爲單獨的部分丟進Source Insight進行分析

定位到android_source\libcore\luni\src\main\java\java\lang\System.java, 搜索loadLibrary, 就能夠開始分析了


java層代碼主要是一些路徑, 和標記值的初始化

最後比較關鍵的函數是JavaVMExt.LoadNativeLibrary, 該函數主要完成以下事情

1. 調用linker的dlopen完成加載

2. 調用dlsym獲取目標so的JniOnload地址並調用

3. 初始化SharedLibrary對象並添加到表中, 下次加載相同的so則不在重複加載


linker以前的函數調用流程圖以下:


3. linker的dlopen簡易分析

android系統經過調用linker的dlopen來完成so的轉載


把aosp\bionic目錄添加到source insight中進行分析

配合AndroidXref站點咱們找到, dlopen定義在dlfcn.cpp中


dlopen函數定義以下, 只是簡單的調用了dlopen_ext

 
跟進 dlopen_ext 函數, 該函數返回一個soinfo的結構體指針
並且這個指針最後做爲函數返回值返回了


do_dlopen簡單的判斷了一下參數, 而後調用find_library進行轉載連接so文件

加載成功後,返回soinfo對象指針,同時調用soinfo的成員函數call_constructors來調用so中的init_array


call_constructors先完成其餘模塊的加載,而後調用call_array()來調用init_array數組的調用

 
call_array循環調用call_funtion來進行加載

最後call_function只是簡單的調用傳進來的函數指針, 能夠看到咱們上面的下斷點的字符串就來自於下面 
 

因爲篇幅問題,大體介紹下linker的調用流程, 函數調用流程以下:

1. 在do_dlopen中經過find_library進行加載so

    在加載完so後經過call_constructors完成init_array的加載

2. find_library最後調用load_libray完成so的轉載

3. 最後經過load_library的elf_reader.load完成so的裝載


四.總結

因爲android是開源的操做系統, android中的不少問題咱們均可以經過分析源碼來了解細節, 解決問題, 並知其因此然

同時咱們還能夠經過編譯源碼來定製咱們想要的功能, 達到咱們想要的目的










相關文章
相關標籤/搜索