Android安全面試——加載流程面試考點
請用微信掃一掃
分享
Android逆向篇01——加載流程面試點
本文主要講解Android逆向中的Android APK編譯流程、編譯原理、Android 系統(tǒng)加載流程、Android APP啟動流程、Android APP類加載機制。
一、Android APK編譯流程
我們用一張圖來描述apk的構(gòu)建流程:
上述的步驟為:
(1)aapt打包資源文件
資源文件(res文件夾下的文件)通過aapt打包生成R.java(資源索引文件)、arsc資源文件和res文件
(2)處理aidl files
AIDL是Android接口定義語言,是Android提供的IPC的一種獨特實現(xiàn),這里生成對應(yīng)的Java接口文件
(3)編譯
使用javac將R.java文件、工程源碼文件、aidl.java文件編譯成.class文件
(4)生成dex文件
源碼.class文件和第三方j(luò)ar或者library通過dx工具打包成dex文件
(5)apkbuilder(生成未簽名apk)
將classes.dex、resources.arsc、res文件夾(res/raw資源被原裝不動地打包進APK之外,其它的資源都會被編譯或者處理)、Other Resources(assets文件夾)、AndroidManifest.xml打包成apk文件
(6)對apk文件進行簽名
apksigner工具會對未簽名的apk驗證簽名。得到一個簽名后的apk(signed.apk)
(7)zipalign(對齊)
release mode 下使用 aipalign進行align,即對簽名后的apk進行對齊處理,以便2可以通過內(nèi)存映射來訪問
上面過程則完成了Android中的apk的編譯流程,但是步驟(4)中將so庫進行打包,這里so庫一般存放在lib文件夾下,Android一般通過ndk將c/c++代碼編譯為so文件,這里我們可以詳細了解一下編譯原理。
詳細參考博客:Android APK編譯流程
二、編譯原理
我們可以借助gcc來實現(xiàn)上面的過程:
(1)預處理階段
預處理器(cpp)根據(jù)以字符``#開頭的命令修給原始的C程序,結(jié)果得到另一個C程序,通常以.i作為文件擴展名。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。
命令行:gcc -E hello.c hello.i
考點經(jīng)常問include在哪個階段處理,就是該階段
(2)編譯階段
將文本文件hello.i翻譯成hello.s,包含相應(yīng)的匯編語言程序
(3)匯編階段
將.S文件翻譯成機器指令,然后把這些指令打包成一種可重定位目標程序的格式,并把結(jié)果保存在目標文件.o中(匯編——>機器)
gcc -c hello.c hello.o
(4)鏈接階段
hello程序調(diào)用了printf函數(shù),鏈接器(Id
)就把printf.o文件并入hello.o文件中,得到hello可執(zhí)行文件,然后加載到存儲器中由系統(tǒng)執(zhí)行。
函數(shù)庫包括靜態(tài)庫和動態(tài)庫 靜態(tài)庫:編譯鏈接時,把庫文件代碼全部加入可執(zhí)行文件中,運行時不需要庫文件,后綴為.a。 動態(tài)庫:編譯鏈接時,不加入,在程序執(zhí)行時,由運行時鏈接文件加載庫,這樣節(jié)省開銷,后綴為.so。(gcc編譯時默認使用動態(tài)庫)再經(jīng)過匯編器和連接器的作用后輸出一個目標文件,這個目標文件為可執(zhí)行文件
詳細參考博客:Android Hook技術(shù)學習——常見的Hook技術(shù)方案總結(jié)
三、Android系統(tǒng)啟動流程
具體步驟如下
(1)引導層: 手機開機后,引導芯片啟動,引導芯片開始從固化在ROM里的預設(shè)代碼執(zhí)行,加載引導程序到到RAM,BootLoader檢查RAM,初始化硬件參數(shù)等功能;(2)內(nèi)核層: Kernel層主要加載一些硬件設(shè)備驅(qū)動,初始化進程管理等操作。在Kernel中首先啟動swapper進程(pid=0),用于初始化進程管理、內(nèi)管管理、加載Driver等操作,再啟動kthread進程(pid=2),這些linux系統(tǒng)的內(nèi)核進程,kthread是所有內(nèi)核進程的鼻祖;(3)Native層:啟動初始化進程管理等操作會啟動init進程 ,這些在Native層中,init進程是所有進程的鼻祖,解析執(zhí)行init.rc,到app_process進程,然后app_process孵化zygote進程(4)java框架層:zygote進程會加載虛擬機,啟動System_Server進程
總結(jié):
加載BootLoader --> 初始化內(nèi)核 --> 啟動init進程 --> init進程fork出Zygote進程 --> Zygote進程fork出SystemServer進程
詳細參考:Xposed定制
四、Android APP啟動流程
SystemServer啟動了一個更加重要的服務(wù)ActivityManagerService
,AMS其中很重要的一個作用就是啟動Launcher
進程
(1)點擊桌面APP圖標時,Launcher的startActivity()方法,通過Binder通信,調(diào)用system_server進程中AMS服務(wù)的startActivity方法,發(fā)起啟動請求(2)system_server進程接收到請求后,向Zygote進程發(fā)送創(chuàng)建進程的請求(3)Zygote進程fork出App進程,并執(zhí)行ActivityThread的main方法,創(chuàng)建ActivityThread線程(4)創(chuàng)建ActivityThread線程--->handlerbindapplication進程初始化————>Application的構(gòu)造函數(shù)————>Application.attachBaseContext()————>Application.onCreate()函數(shù)最后才會進入MainActivity中的attachBaseContext函數(shù)、onCreate函數(shù)
詳細參考:Android漏洞之戰(zhàn)(12)——整體殼脫殼詳解
五、Android APP類加載流程
Android Java層的類加載流程:
Android Native層:
DefineClass--->LoadClass->LoadClassMembers->LoadMethod-->LinkCode--->Execute
詳細參考:Android漏洞之戰(zhàn)(12)——整體殼脫殼詳解
考點:LoadClass加載和forName加載的區(qū)別
(1)使用LoadClass()加載 不會初始化靜態(tài)塊(2)使用forName()加載 會初始化靜態(tài)塊