標籤:android 執行個體 dex smali dex結構
我在部落格上發表一些我的Android學習心得,希望對大家能有協助。
這一篇我們講述一下通過一個執行個體來分析dex檔案結構和組成。
參考Leb128資料類型 Android學習心得(5) --- dex資料類型LEB128
參考執行個體分析學習理解dex檔案結構Android學習心得(15) --- Dex檔案結構解析(1)
參考baksmali工具使用Android學習心得(4) --- MAC下smali檔案編寫與運行
1、編譯
我們通過一個例子來分析dex檔案的構成
建立一個Hello.java檔案,輸入下面的值,這個是我們學習的樣本
public class Hello { public static void main(String[] argc) { System.out.println("Hello world"); }}
通過編譯成.class檔案之後再編譯成.dex檔案
使用0xED開啟進行查看
2、Header
我們通過前一張中Dex Header解析
通過dex檔案中前0x70的header資料查詢並填入表格
前0x70資料
3、MapList
在Header中MapOff指向的是MapList結構
MapList結構第四節中已經定義,我們查詢並填寫表格
map_off中位移地址為0x0240,查詢相應地址第一個16位是MapItem的數目:0x000D(14個)
4、string_id_item
首先我們查看MapList中string_id_item,size是14個,從0x70開始
我們分別從0x176、0x17E等讀取出14個字串,並填入表格
5、type_id_item
我們查看MapList中type_id_item,個數是7個,從0xA8開始
由於這個是表示stringids的索引,查string_id_item表得出
6、proto_id_item
查看proto_id_item,個數是3個,從0xC4開始
通過查看proto_id_item結構,填入表格
7、field_id_item
我們查看MapList中field_id_item,個數是1個,從0xE8開始
通過查看field_id_item結構,填入表格
8、method_id_item
我們查看MapList中method_id_item,個數是4個,從0xF0開始
通過查看上一節中對method_id_item描述,填入表格
9、class_def_item
我們查看MapList中class_def_item,個數是1個,從0x110開始
通過上一節中DexClassDef結構,我們填寫表格
我們查看MapList中class_def_item,的確位移地址和個數都相同。
由於DexClass.h定義的u4是屬於Leb128
下面緊跟的是兩個直接方法
第一個是00 81 80 04 B0 02
從0x130開始分析code_item結構
分析思路整理如下
(1) 《Dalvik VM Instruction Format》 裡操作符 op 都是位於首個 16bit 資料的低 8 bit 起始的是 op = 0x70(2) 在 《Bytecode for Dalvik VM》 裡找到對應的 Syntax 和 format 。syntax = invoke-directformat = 0x35c (3) 在《Dalvik VM Instruction Format》裡尋找 35c , 得知 op = 0x70 的指令佔據 2 個 16 bit 資料 ,格式是 B|A|op CCCC G|F|E|D ,其中,B=1,A=0。我們查詢到: [B=1] op {vD}, [email protected]有上述得出CCCC = 3,D = 0;0E作業碼是對應的是return-void
得到指令是:
invoke-direct {v0}, Ljava/lang/Object;.<init>:()V return-void
第二個是01 09 C8 02
從0x148開始分析code_item結構
分析思路整理如下
(1) 《Dalvik VM Instruction Format》 裡操作符 op 都是位於首個 16bit 資料的低 8 bit 起始的是 op = 0x62(2) 在 《Bytecode for Dalvik VM》 裡找到對應的 Syntax 和 format 。syntax = sget-objectformat = 0x21c (3) 在《Dalvik VM Instruction Format》裡尋找 21c , 得知 op = 0x62 的指令佔據 2 個 16 bit 資料 ,格式是 AA|op BBBB ,其中,AA=00,BBBB=0。
得到指令是:
sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
繼續進行
(1) 《Dalvik VM Instruction Format》 裡操作符 op 都是位於首個 16bit 資料的低 8 bit 起始的是 op = 0x1A(2) 在 《Bytecode for Dalvik VM》 裡找到對應的 Syntax 和 format 。syntax = const-string vAA, [email protected]format = 0x21c (3) 在《Dalvik VM Instruction Format》裡尋找 21c , 得知 op = 0x1A 的指令佔據 2 個 16 bit 資料 ,格式是 onst-string vAA, [email protected] ,其中,AA=01,BBBB=1。
得到指令是:
const-string v1, "Hello World"
繼續進行
(1) 《Dalvik VM Instruction Format》 裡操作符 op 都是位於首個 16bit 資料的低 8 bit 起始的是 op = 0x6E(2) 在 《Bytecode for Dalvik VM》 裡找到對應的 Syntax 和 format 。syntax = invoke-virtualformat = 0x35c (3) 在《Dalvik VM Instruction Format》裡尋找 21c , 得知 op = 0x6E 的指令佔據 2 個 16 bit 資料 ,格式是 B|A|op CCCC G|F|E|D,其中,B=2, CCCC=2, E=1, D=0。其格式為:[B=2] op {vD, vE}, [email protected]
得到指令是:
invoke-virtual {v0, v1}, Ljava/io/PrintStream; -> println(Ljava/lang/String;)Vreturn-void
最終分析核心代碼
invoke-direct {v0}, Ljava/lang/Object;.<init>:()V sget-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
對比baksmali檔案產生smali檔案
.class public LHello;.super Ljava/lang/Object;.source "Hello.java"# direct methods.method public constructor <init>()V .registers 1 .prologue .line 1 invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void.end method.method public static main([Ljava/lang/String;)V .registers 3 .prologue .line 3 sget-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;)V .line 4 return-void.end method
核心代碼相同,分析正確。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android學習心得(16) --- Dex檔案結構執行個體解析(2)