標籤:
八月的太陽曬得黃黃的,誰說這世界不是黃金?小雀兒在樹蔭裡打盹,孩子們在草地裡打滾。八月的太陽曬得黃黃的,誰說這世界不是黃金?金黃的樹林,金黃的草地,小雀們合奏著歡暢的清音:金黃的茅舍,金黃的麥屯,金黃是老農們的笑聲。 —— 徐志摩·八月的太陽
ilocker:關注 Android 安全(新入行,0基礎) QQ: 2597294287
在產生 native 程式時,在連結階段會傳入一個連結指令碼,在該指令碼中指定了程式的入口函數。
可以看到,在預設的連結指令碼 armelf_linux_eabi.x 中,入口函數指定為“_start”。
在 NDK 目錄下搜尋 ldscripts,所有的連結指令碼都在該目錄中。
_start 函數定義在 (libc 的 bionic 目錄下) Crtbegin.c 中。
在 _start 中又調用了 __libc_init,並將 main 函數的地址作為參數傳入。
再看 __libc_init 的源碼 (在 libc 的 bionic 目錄下的 Libc_init_static.cpp 檔案中):
在 __libc_init 中先進行一些初始化工作,再調用 preinit_array、init_array,最後調用由參數 slingshot 傳入的 main 函數。
上面的描述針對靜態連結的程式,對於動態連結的程式還稍有不同。
對於動態連結 (在 gcc 命令列中指定 -Bdynamic),在產生的可執行檔的 .interp 中儲存了程式解譯器的檔案路徑,預設為“/system/bin/linker”。
當執行動態連結的程式時,系統會解析該 ELF 檔案,並找到 .interp 中儲存的程式解譯器,也就是 android linker。然後先執行 linker,linker 會載入該程式的所依賴的一系列 so,並最後再調用該可執行程式。
linker 的入口函數 _start 不在 Crtbegin.c 中,而是在 linker 源碼的 begin.S 檔案中。
調用 __linker_init 函數完成 linker 的“自舉”,並進行一些初始化工作,最後會返回原 native 程式的入口函數的地址 (從 native 程式的 ELF Header 中找到)。
mov pc, r0,跳轉到 native 程式的入口函數 (_start) 去執行,接下來的執行過程與上面一樣。_start 調用 __libc_init。動態連結程式的 __libc_init 定義在 Libc_init_dynamic.cpp 檔案中 (靜態連結程式的 __libc_init 定義在 Libc_init_static.cpp 檔案中)。
看起來比靜態連結程式的 __libc_init 簡單點,因為一些初始化工作由 linker 完成了。
總結:靜態連結與動態連結的 native 程式的入口函數都是 _start。動態連結的程式在執行 _start 之前,需要先由 linker 載入依賴庫,並進行一些初始化工作。
學習資料: 《Android 軟體安全與逆向分析》
Android Native 程式逆向入門(一)—— Native 程式的啟動流程