背景
android逆向分析、脫殼破解分析過程中免不了和android的各種文件格式打交道(so、dex、xml、art、oat等等)。
Android下的兩個最重要的文件是DEX文件和SO文件,下面重點對這兩個文件及關聯(lián)文件進行下文的梳理總結(jié),以此用于溫故知新。
DEX文件
DEX它是android虛擬機的可執(zhí)行字節(jié)碼文件,我們知道java文件需要經(jīng)過javac編譯成class文件,dx工具會將所有的class文件合并處理最終生成dex文件。
dex文件分為四大部分: DEX文件頭,索引結(jié)構(gòu)區(qū),data數(shù)據(jù)區(qū),靜態(tài)鏈接數(shù)據(jù)區(qū)。
在dex文件中所有的代碼和數(shù)據(jù)都放在data數(shù)據(jù)區(qū)中,索引結(jié)構(gòu)區(qū)中存放的是data中各種數(shù)據(jù)的對應的偏移和索引。
ODEX文件
ODEX它的英文全稱為Optimized DEX;即優(yōu)化過的DEX。
在android5.0之前,Android采用的是JIT(just-in-time)即時編譯,也就是程序邊執(zhí)行邊編譯。為了增加程序執(zhí)行的效率,android在APK第一次安裝的時候?qū)⒊绦虻膁ex文件進行優(yōu)化生成odex文件,并將其放在了/data/dalvik-cache目錄下,等待下次apk運行時直接加載這個目錄中經(jīng)過優(yōu)化的odex文件(優(yōu)化基于當前系統(tǒng)的dalvik虛擬機版本,不同版本上的odex文件無法進行兼容),避免重復驗證提高執(zhí)行效率,加快APK的響應時間。
OAT文件
在android5.0之后,android使用的是AOT(Ahead-of-time)事前編譯,也就是程序在運行前先編譯。oat是ART虛擬機運行的文件,是ELF格式二進制文件,包含DEX和編譯的本地機器指令,oat文件包含DEX文件,因此比ODEX文件占用空間更大。
程序在首次安裝的時候,dex2oat默認會把classes.dex翻譯成本地機器指令,生成ELF格式的OAT文件,并將其放在了/data/dalvik-cache或者是/data/app/packagename/目錄下。ART加載OAT文件后不需要經(jīng)過處理就可以直接運行,它在編譯時就從字節(jié)碼裝換成機器碼了,因此運行速度更快。
在android5.0之后oat文件的后綴還是odex,但是已經(jīng)不是android5.0之前的文件格式,而是ELF格式封裝的本地機器碼,可以認為oat在dex上加了一層殼,可以從oat里提取出dex。
(elf格式的oat)
因為此時的oat文件是一個標準的elf文件,識別其實其是不是oat文件的標準就是看其符號表。
oatdata指向的是ELF文件的.rodata節(jié)區(qū),存放了OAT文件頭OATHeader,OAT的DEX文件頭,原始DEX文件的DexFile等信息。
oatexec指向的是ELF文件的.text節(jié)區(qū),這里存放的是編譯生成的指定平臺的二進制代碼。
oatlastword指向的是對應oat文件的結(jié)尾。
OAT文件大小差不多= dex文件+art文件
vdex文件
android8.0(Android O)之前dex文件嵌入到oat文件本身中,在Android 8.0之后dex2oat將classes.dex優(yōu)化生成兩個文件oat文件(.odex)和vdex文件(.vdex),其中包含APK的未壓縮DEX代碼,以及一些旨在加快驗證速度的元數(shù)據(jù)。
odex文件中包含了本機代碼的OAT
vdex文件包含了原始的DEX文件副本
ART文件
ART虛擬機在執(zhí)行dex文件時,需要將dex文件中使用的類,字符串等信息轉(zhuǎn)換為自定義的結(jié)構(gòu)。art文件就是保存APK中使用的一些類,字符串等信息的ART內(nèi)部表示,可以加快APK程序啟動的速度。
ELF文件
ELF文件格式提供了兩種不同的視角,在匯編器和鏈接器看來,ELF文件是由Section Header Table描述的一系列Section的集合,而執(zhí)行一個ELF文件時,在加載器(Loader)看來它是由Program Header Table描述的一系列Segment的集合。
ELF它是 Executable and Linking Format 的縮寫,它是android平臺上通用的二進制文件格式。在 Android 的 NDK 開發(fā)中,幾乎都是和 ELF 打交道。
比如:
1、c / c++ 文件編譯得到的 .o(或者 .obj)文件就是 ELF 格式的文件;
2、動態(tài)庫(.so)文件、可執(zhí)行文件也是 ELF 文件;
3、動態(tài)庫的字符串擦除、動態(tài)庫加殼、動態(tài)庫修復等都離不開 ELF;
ELF文件名稱中的Executable和 Linking表明 ELF 有兩種重要的特性。
1、Executable表示可執(zhí)行的。ELF 文件將參與程序的執(zhí)行(Execution)過程。包括二進制程序的運行以及動態(tài)庫 .so 文件的加載。
2、Linking表示可連接的。ELF 文件參與編譯鏈接過程。
文件加載
Android中Java層通過System.load或System.loadLibrary來加載一個so文件,它的定義在Android源碼中的路徑
為/libcore/luni/src/main/java/java/lang/System.java,執(zhí)行流程如下:
加載so的兩種方式
1、System.loadLibrary(path),只能加載jniLIbs目錄下的so文件,這個的執(zhí)行流程
1.1、先讀取so文件的.init_array段
1.2、執(zhí)行JNI_OnLoad函數(shù)
1.3、JNI_ONLoad是.so文件的初始函數(shù)
1.4、最后調(diào)用具體的native方法
2、System.load(path),可以加載任意路徑下的so
這兩種方式最終都會調(diào)用Android底層的dlopen來打開so
dlopen用來打開一個動態(tài)鏈接庫,并將其裝入內(nèi)存。它的定義在Android源碼中的路徑為/bionic/linker/dlfcn.cpp,執(zhí)行流程如下:
So文件的入口為init_array、init_func這些初始化函數(shù)。這部分在dlopen的過程中就會執(zhí)行,再之后的是JNI_Onload方法的調(diào)用。這里面可以注冊一些本地方法,也可以繼續(xù)做些變量的初始化等操作。
審核編輯:劉清
-
Android系統(tǒng)
+關注
關注
0文章
56瀏覽量
13475 -
虛擬機
+關注
關注
1文章
908瀏覽量
28086 -
ELF文件
+關注
關注
0文章
14瀏覽量
7128
原文標題:Android逆向基礎(DEX/ELF文件格式)
文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論