015 Android之可执行文件dex
文章目錄
- 從一個hello world開始
- Dex文件結(jié)構(gòu)
- 文件頭
- 各種數(shù)據(jù)的數(shù)組
- 字符串表
- 類型表
- 原型表
- 字段表
- 方法表
- 類數(shù)據(jù)
- 手工解析Smali代碼
從一個hello world開始
smali代碼和dex之間有著千絲萬縷的聯(lián)系,先從一個最簡單的dex文件hello world開始,學(xué)習(xí)整個dex文件的結(jié)構(gòu)
.class public LHelloWorld; .super Ljava/lang/Object;.method public static main([Ljava/lang/String;)V.registers 2sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;const-string v1, "Hello World!"invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)Vreturn-void .end method以上面這段smali代碼為例
D:\Android\tools>java -jar smali.jar -o classes.dex HelloWorld.smali然后將smali代碼轉(zhuǎn)成dex文件,并打成壓縮包,命名為HelloWorld.zip
確保adb和模擬器連接成功
再將打包好的zip文件上傳到模擬器
接著執(zhí)行dex文件,可以看到成功打印了Hello World
Dex文件結(jié)構(gòu)
Dex文件主要可以分為三大塊:
文件頭
首先來看文件頭的部分
總共占0x70個字節(jié)大小,比較重要的字段有四個
除了這四個字段以外,文件頭部還有其他一些字段
各種表的大小及偏移
各種數(shù)據(jù)的數(shù)組
dex文件第二部分是各種數(shù)據(jù)的數(shù)組,包括字符串 類型 方法原型 字段 方法
字符串表
字符串表項,是一個字符串?dāng)?shù)據(jù)的偏移,偏移指向的是一個string_data結(jié)構(gòu)。string_data結(jié)構(gòu)中有兩個字段
字段1:字符串長度,數(shù)據(jù)類型是uleb128,安卓中特有的變長的數(shù)據(jù)類型
字段2:存儲數(shù)據(jù),字符串以0結(jié)尾
類型表
類型表,保存的是一個索引值,指向的是字符串表
例如:索引值為3表示的是字符串表的下標(biāo)為3的位置指向的是L/java/lang/Object這個字符串。
原型表
原型表中存儲的是函數(shù)原型的各部分描述信息。包括短類型(shorty_idx),返回類型(return_type_idx),參數(shù)的類型(parameters_off),最終還是一個指向字符串表的數(shù)組下標(biāo)。
注意:字段為返回類型(return_type_idx)的值,是類型表中的索引
字段表
存儲的是字段信息,包括字段所在類(class_idx),字段的類型(type_idx),字段的名稱(name_idx)。
class_idx是類型表中的索引,type_idx是類型表中的索引,字段名稱的索引是字符串的數(shù)組下標(biāo)
方法表
方法表中存儲的是方法的信息,包括方法所在的類(class_dex),方法的原型(proto_idx),方法的名稱(name_idx)。
其中class_idx是類型表的索引,proto_idx是原型表的索引,方法名稱的索引(name_idx)是字符串表的數(shù)組下標(biāo)
類數(shù)據(jù)
類數(shù)據(jù)也是一個數(shù)組,每一個元素就是一個類的相關(guān)信息。現(xiàn)在所分析的這個文件因為只有一個類,所以只有一個類的信息。
在表項中的class_data中存儲的是類數(shù)據(jù),包括類名索引,訪問屬性,父類索引,接口偏移,源碼索引,注解偏移,類數(shù)據(jù)偏移
其中,整個類的數(shù)據(jù)在class_data_item這個結(jié)構(gòu)中。
method_list是類內(nèi)所有方法的列表,因為當(dāng)前這個文件只有一個Main方法,所以列表內(nèi)只有一個結(jié)構(gòu)體。結(jié)構(gòu)體中有方法的基本信息,包括方法索引,訪問標(biāo)志,代碼偏移,代碼信息
其中code_item是整個代碼的信息,里面有兩個字段特別重要
ins_size:指令長度
ushort insns[8]:指令數(shù)組
這個數(shù)組存放的就是被翻譯成smali代碼的虛擬機指令,也就是OpCode
手工解析Smali代碼
62 00 00 00 1A 01 00 00 6E 20 01 00 10 00 0E 00接下來復(fù)制這一段十六進(jìn)制,手工將這段代碼解析成Smali代碼。
這里還需要借助一個文檔《(中文)Dalvik操作碼》,里面有所有的Opcode和對應(yīng)的操作碼以及示例。
首先找到62,62代表的指令含義是根據(jù)字段ID讀取靜態(tài)對象引用字段到vx,接著,還需要看懂旁邊的示例
6201 0C00解析為smali代碼是
sget‐object v1, Test3.os1:Lja va/lang/Object; // field@000c讀取 Object 的靜態(tài)對象引用字段 os1(字段表#CH 條目)到 v1。
也就說這條指令一共4個字節(jié)
62 代表操作碼 sget‐object 01 代表的是序號為1的寄存器v1 000C 代表字段表索引為0xC的字段接著再來看我們要解析的Opcode
62 00 00 00 1A 01 00 00 6E 20 01 00 10 00 0E 00先解析前四個字節(jié)
62 00 00 00具體含義如下
62 代表操作碼 sget‐object 00 代表的是序號為0的寄存器v0 0000 代表字段表索引為00的字段接下來在字段表中找到第0個字段
java.io.PrintStream java.lang.System.out第0個字段就是out這個對象,將這個字段翻譯為smali代碼
Ljava.lang.System;->out:java.io.PrintStream那么前四個字節(jié)
62 00 00 00解析為smali代碼就是
sget‐object v0, Ljava.lang.System;->out:java.io.PrintStream接著來看1A
1A08 0000解析為
const‐string v8, "" // string @0000存入 string@0000(字符串表#0 條目)的引用到 v 8
需要解析的Opcode
1A 01 00 00接著找到字符串表索引為0的字符串
那么這條指令解析為Smali代碼就是
const‐string v1, "Hello World!"接下來查找6E
直接看例子
6E53 0600 0421 ‐ invoke‐virtual { v4, v0, v1, v2, v3}, Test2.method5:(IIII)V // me thod@0006這條指令比較復(fù)雜,一共6個字節(jié),其中
6E---> invoke‐virtual 5---> 參數(shù)數(shù)量 3---> v3 0600--->method@0006 0421--->v4, v0, v1, v2調(diào)用參數(shù)表的編譯比較詭異,如果參數(shù)的數(shù)量大于4,第5個參數(shù)將編譯在指令字節(jié)的下一個字節(jié)的4個最低位
那么我們要解析的Opcode
6E 20 01 00 10 00就可以解析為
6E---> invoke‐virtual 2---> 參數(shù)數(shù)量 01 00--->method@0001 10 00--->v1 v0翻譯出來就是
invoke‐virtual {v0,v1},method@01找到函數(shù)表下標(biāo)為1的方法
void java.io.PrintStream.println(java.lang.String)轉(zhuǎn)為Smali代碼
Ljava/io/PrintStream;->println(Ljava/lang/String;)V完整的smali代碼就是
invoke‐virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V最后看0E
表示返回值為空
62 00 00 00 1A 01 00 00 6E 20 01 00 10 00 0E 00解析出來完整的smali代碼就是
sget‐object v0, Ljava.lang.System;->out:java.io.PrintStream;const‐string v1, "Hello World!"invoke‐virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)Vreturn‐void和HelloWorld.smali的源碼沒有區(qū)別
總結(jié)
以上是生活随笔為你收集整理的015 Android之可执行文件dex的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 014 Android之Cydia与Xp
- 下一篇: 016 Android之NDK开发