日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dex文件格式

發布時間:2025/3/20 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dex文件格式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文件頭(File Header)

Dex文件頭主要包括校驗和以及其他結構的偏移地址和長度信息。

字段名稱 偏移值 長度 描述
magic 0x0 8 'Magic'值,即魔數字段,格式如”dex/n035/0”,其中的035表示結構的版本。
checksum 0x8 4 校驗碼。
signature 0xC 20 SHA-1簽名。
file_size 0x20 4 Dex文件的總長度。
header_size 0x24 4 文件頭長度,009版本=0x5C,035版本=0x70。
endian_tag 0x28 4 標識字節順序的常量,根據這個常量可以判斷文件是否交換了字節順序,缺省情況下=0x78563412。
link_size 0x2C 4 連接段的大小,如果為0就表示是靜態連接。
link_off 0x30 4 連接段的開始位置,從本文件頭開始算起。如果連接段的大小為0,這里也是0。
map_off 0x34 4 map數據基地址。
string_ids_size 0x38 4 字符串列表的字符串個數。
string_ids_off 0x3C 4 字符串列表表基地址。
type_ids_size 0x40 4 類型列表里類型個數。
type_ids_off 0x44 4 類型列表基地址。
proto_ids_size 0x48 4 原型列表里原型個數。
proto_ids_off 0x4C 4 原型列表基地址。
field_ids_size 0x50 4 字段列表里字段個數。
field_ids_off 0x54 4 字段列表基地址。
method_ids_size 0x58 4 方法列表里方法個數。
method_ids_off 0x5C 4 方法列表基地址。
class_defs_size 0x60 4 類定義類表中類的個數。
class_defs_off 0x64 4 類定義列表基地址。
data_size 0x68 4 數據段的大小,必須以4字節對齊。
data_off 0x6C 4 數據段基地址

魔數字段

? ? ?魔數字段,主要就是Dex文件的標識符,它占用4個字節,在目前的源碼里是 “dex\n”,它的作用主要是用來標識dex文件的,比如有一個文件也以dex為后綴名,僅此并不會被認為是Davlik虛擬機運行的文件,還要判斷這 四個字節。另外Davlik虛擬機也有優化的Dex,也是通過個字段來區分的,當它是優化的Dex文件時,它的值就變成”dey\n”了。根據這四個字 節,就可以識別不同類型的Dex文件了。

? ? ? 跟在“dex\n”后面的是版本字段,主要用來標識Dex文件的版本。目前支持的版本號為“035\0”,不管是否優化的版本,都是使用這個版本號。

檢驗碼字段

? ? ?主要用來檢查從這個字段開始到文件結尾,這段數據是否完整,有沒有人修改過,或者傳送過程中是否有出錯等等。通常用來檢查數據是否完整的算法,有 CRC32、有SHA128等,但這里采用并不是這兩類,而采用一個比較特別的算法,叫做adler32,這是在開源zlib里常用的算法,用來檢查文件 是否完整性。該算法由MarkAdler發明,其可靠程度跟CRC32差不多,不過還是弱一點點,但它有一個很好的優點,就是使用軟件來計算檢驗碼時比較 CRC32要快很多??梢夾ndroid系統,就算法上就已經為移動設備進行優化了。

? ? ?Java中可使用java.util.zip.Adler32類做校驗操作

SHA-1簽名字段

? ? ?dex文件頭里,前面已經有了面有一個4字節的檢驗字段碼了,為什么還會有SHA-1簽名字段呢?不是重復了嗎?可是仔細考慮一下,這樣設計自有道理。因 為dex文件一般都不是很小,簡單的應用程序都有幾十K,這么多數據使用一個4字節的檢驗碼,重復的機率還是有的,也就是說當文件里的數據修改了,還是很 有可能檢驗不出來的。這時檢驗碼就失去了作用,需要使用更加強大的檢驗碼,這就是SHA-1。SHA-1校驗碼有20個字節,比前面的檢驗碼多了16個字 節,幾乎不會不同的文件計算出來的檢驗是一樣的。設計兩個檢驗碼的目的,就是先使用第一個檢驗碼進行快速檢查,這樣可以先把簡單出錯的dex文件丟掉了, 接著再使用第二個復雜的檢驗碼進行復雜計算,驗證文件是否完整,這樣確保執行的文件完整和安全。

? ? ? SHA(Secure Hash Algorithm, 安全散列算法)是美國國家安全局設計,美國國家標準與技術研究院發布的一系列密碼散列函數。SHA-1看起來和MD5算法很像,也許是Ron Rivest在SHA-1的設計中起了一定的作用。SHA-1的內部比MD5更強,其摘要比MD5的16字節長4個字節,這個算法成功經受了密碼分析專家 的攻擊,也因而受到密碼學界的廣泛推崇。這個算法在目前網絡上的簽名,BT軟件里就有大量使用,比如在BT里要計算是否同一個種子時,就是利用文件的簽名 來判斷的。同一份8G的電影從幾千BT用戶那里下載,也不會出現錯誤的數據,導致電影不播放。

map_off字段

這個字段主要保存map開始位置,就是從文件頭開始到map數據的長度,通過這個索引就可以找到map數據。map的數據結構如下:

名稱 大小 說明
size 4字節 map里項的個數
list 變長 每一項定義為12字節,項的個數由上面項大小決定。

map數據排列結構定義如下:

<span class="coMULTI" style="line-height: 20px;">/* *Direct-mapped "map_list". */</span><span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexMapList <span class="br0" style="line-height: 20px;">{</span>u4 size<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* #of entries inlist */</span>DexMapItem list<span class="br0" style="line-height: 20px;">[</span><span class="nu0" style="line-height: 20px;">1</span><span class="br0" style="line-height: 20px;">]</span><span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* entries */</span> <span class="br0" style="line-height: 20px;">}</span>DexMapList<span class="sy0" style="line-height: 20px;">;</span>

每一個map項的結構定義如下:

<span class="coMULTI" style="line-height: 20px;">/* *Direct-mapped "map_item". */</span><span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexMapItem <span class="br0" style="line-height: 20px;">{</span>u2 type<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* type code (seekDexType* above) */</span>u2 unused<span class="sy0" style="line-height: 20px;">;</span>u4 size<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* count of items ofthe indicated type */</span>u4 offset<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* file offset tothe start of data */</span> <span class="br0" style="line-height: 20px;">}</span>DexMapItem<span class="sy0" style="line-height: 20px;">;</span>

DexMapItem結構定義每一項的數據意義:類型、類型個數、類型開始位置。

其中的類型定義如下:

<span class="coMULTI" style="line-height: 20px;">/*map item type codes */</span> <span class="kw2" style="line-height: 20px;">enum</span><span class="br0" style="line-height: 20px;">{</span>kDexTypeHeaderItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeStringIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeTypeIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeProtoIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeFieldIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0004</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeMethodIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0005</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeClassDefItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0006</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeMapList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeTypeList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationSetRefList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationSetItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeClassDataItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeCodeItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeStringDataItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeDebugInfoItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2004</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeEncodedArrayItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2005</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationsDirectoryItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2006</span><span class="sy0" style="line-height: 20px;">,</span> <span class="br0" style="line-height: 20px;">}</span><span class="sy0" style="line-height: 20px;">;</span>

從上面的類型可知,它包括了在dex文件里可能出現的所有類型。可以看出這里的類型與文件頭里定義的類型有很多是一樣的,這里的類型其實就是文件頭里定義 的類型。其實這個map的數據,就是頭里類型的重復,完全是為了檢驗作用而存在的。當Android系統加載dex文件時,如果比較文件頭類型個數與 map里類型不一致時,就會停止使用這個dex文件

string_ids_size/off字段

這兩個字段主要用來標識字符串資源。源程序編譯后,程序里用到的字符串都保存在這個數據段里,以便解釋執行這個dex文件使用。其中包括調用庫函數里的類名稱描述,用于輸出顯示的字符串等。

string_ids_size標識了有多少個字符串,string_ids_off標識字符串數據區的開始位置。字符串的存儲結構如下:

<span class="coMULTI" style="line-height: 20px;">/** Direct-mapped "string_id_item".*/</span> <span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexStringId <span class="br0" style="line-height: 20px;">{</span>u4 stringDataOff<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* file offset to string_data_item */</span> <span class="br0" style="line-height: 20px;">}</span> DexStringId<span class="sy0" style="line-height: 20px;">;</span>

可以看出這個數據區保存的只是字符串表的地址索引。如果要找到字符串的實際數據,還需要通過個地址索引找到文件的相應開始位置,然后才能得到字符串數據。 每一個字符串項的索引占用4個字節,因此這個數據區的大小就為4*string_ids_size。實際數據區中的字符串采用UTF8格式保存。

例如,如果dex文件使用16進制顯示出來內容如下:
063c 696e 6974 3e00
其實際數據則是”<init>\0”

另外這段數據中不僅包括字符串的字符串的內容和結束標志,在最開頭的位置還標明了字符串的長度。上例中第一個字節06就是表示這個字符串有6個字符。

關于字符串的長度有兩點需要注意的地方:

1、關于長度的編碼格式

dex文件里采用了變長方式表示字符串長度。一個字符串的長度可能是一個字節(小于256)或者4個字節(1G大小以上)。字符串的長度大多數都是小于 256個字節,因此需要使用一種編碼,既可以表示一個字節的長度,也可以表示4個字節的長度,并且1個字節的長度占絕大多數。能滿足這種表示的編碼方式有 很多,但dex文件里采用的是uleb128方式。leb128編碼是一種變長編碼,每個字節采用7位來表達原來的數據,最高位用來表示是否有后繼字節。

它的編碼算法如下:

<span class="coMULTI" style="line-height: 20px;">/** Writes a 32-bit value in unsigned ULEB128 format.* Returns the updated pointer.*/</span> DEX_INLINE u1<span class="sy0" style="line-height: 20px;">*</span> writeUnsignedLeb128<span class="br0" style="line-height: 20px;">(</span>u1<span class="sy0" style="line-height: 20px;">*</span> ptr<span class="sy0" style="line-height: 20px;">,</span> u4 data<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw1" style="line-height: 20px;">while</span> <span class="br0" style="line-height: 20px;">(</span><span class="kw2" style="line-height: 20px;">true</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>u1 out <span class="sy0" style="line-height: 20px;">=</span> data <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>out <span class="sy0" style="line-height: 20px;">!=</span> data<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="sy0" style="line-height: 20px;">*</span>ptr<span class="sy0" style="line-height: 20px;">++</span> <span class="sy0" style="line-height: 20px;">=</span> out <span class="sy0" style="line-height: 20px;">|</span> <span class="nu12" style="line-height: 20px;">0x80</span><span class="sy0" style="line-height: 20px;">;</span>data <span class="sy0" style="line-height: 20px;">>>=</span> <span class="nu0" style="line-height: 20px;">7</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span> <span class="kw1" style="line-height: 20px;">else</span> <span class="br0" style="line-height: 20px;">{</span><span class="sy0" style="line-height: 20px;">*</span>ptr<span class="sy0" style="line-height: 20px;">++</span> <span class="sy0" style="line-height: 20px;">=</span> out<span class="sy0" style="line-height: 20px;">;</span><span class="kw2" style="line-height: 20px;">break</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="kw1" style="line-height: 20px;">return</span> ptr<span class="sy0" style="line-height: 20px;">;</span> <span class="br0" style="line-height: 20px;">}</span>

它的解碼算法如下:

<span class="coMULTI" style="line-height: 20px;">/** Reads an unsigned LEB128 value, updating the given pointer to point* just past the end of the read value. This function tolerates* non-zero high-order bits in the fifth encoded byte.*/</span> DEX_INLINE <span class="kw4" style="line-height: 20px;">int</span> readUnsignedLeb128<span class="br0" style="line-height: 20px;">(</span><span class="kw4" style="line-height: 20px;">const</span> u1<span class="sy0" style="line-height: 20px;">**</span> pStream<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw4" style="line-height: 20px;">const</span> u1<span class="sy0" style="line-height: 20px;">*</span> ptr <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span>pStream<span class="sy0" style="line-height: 20px;">;</span><span class="kw4" style="line-height: 20px;">int</span> result <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>result <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw4" style="line-height: 20px;">int</span> cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">=</span> <span class="br0" style="line-height: 20px;">(</span>result <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;">|</span> <span class="br0" style="line-height: 20px;">(</span><span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">7</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">14</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">21</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="coMULTI" style="line-height: 20px;">/** Note: We don't check to see if cur is out of* range here, meaning we tolerate garbage in the* high four-order bits.*/</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> cur <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">28</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="sy0" style="line-height: 20px;">*</span>pStream <span class="sy0" style="line-height: 20px;">=</span> ptr<span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">return</span> result<span class="sy0" style="line-height: 20px;">;</span> <span class="br0" style="line-height: 20px;">}</span>

根據上面的算法分析上面例子字符串,取得第一個字節是06,最高位為0,因此沒有后繼字節,那么取出這個字節里7位有效數據,就是6,也就是說這個字符串是6個字節,但不包括結束字符“\0”。

2、關于長度的意義

由于字符串內容采用的是UTF-8格式編碼,表示一個字符的字節數是不定的。即有時是一個字節表示一個字符,有時是兩個、三個甚至四個字節表示一個字符。 而這里的長度代表的并不是整個字符串所占用的字節數,表示這個字符串包含的字符個數。所以在讀取時需要注意,尤其是在包含中文字符時,往往會因為讀取的長 度不正確導致字符串被截斷。

總結

以上是生活随笔為你收集整理的dex文件格式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。