Android逆向之Dex文件
最簡單的一個 dex 文件-HelloWorld
① 編譯 smali 為 dex java -jar smali.jar -o classes.dex HelloWorld.smali ② 查看設備信息 adb devices ③ 上傳文件 adb push HelloWorld.zip /data/local ④ 執行程序 adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld
最簡單的 dex 文件的分析,主要分為三大塊: ① Dex 文件頭 ② 各種數據的數組,包括字符串、類型、方法原型、字段、方法 ③ 類數據 ④ 其他
Dex 文件頭
字段 1:dex_magic,表示 dex 文件的文件標識,特征字符串 字段 2:checksum, 表示校驗和,對文件求了 32 位的 hash 值(從字段 3 開始到文件末尾)
字段 3:signature[], 表示 SHA1(沙 one),對文件求 hash 值(從字段 4 開始到文件末尾) 字段 4:file_size, 表示文件大小
字段 5:dex 文件頭大小 字段 6:數據排列方式-小端方式
各種表的大小以及偏移 ① string_ids_size 和 string_ids_off ,字符串表的大小和偏移 ② type_ids_size 和 type_ids_off,類型表的大小和偏移 ③ proto_ids_size 和 proto_ids_off,原型表的大小和偏移 ④ field_ids_size 和 field_ids_off,字段表的大小和偏移 ⑤ method_ids_size 和 method_ids_off,方法表的大小和偏移 ⑥ class_defs_size 和 class_defs_off,類數據表的大小和偏移
各種數據的數組,包括字符串、類型、方法原型、字段、方法 ① 字符串表
字符串表項,是一個字符串數據的偏移,偏移指向的是一個 string_data 結構。 String_data 結構中有兩個字段:
字段 1: 代表長度,數據類型是 uleb128,變長的數據類型(1-5 字節) 字段 2: 存儲數據,字符串以 0 結尾。 ② 類型表
類型表表項,是一個索引值,類型描述符字符串在字符串表中的索引,圖中的索引是 1,表 示在字符串表中的數組索引 1 中的元素。
類型描述符包括基本數據類型的描述符和類類型的描述符。 LHelloWorld; 是 HelloWorld 類的類描述符。
③ 原型表
原型表項中存儲的是函數原型的各部分描述信息。包括短類型(shorty_idx)、返回類型 (return_type_idx)、參數的類型(parameters_off,最終還是一個指向字符串表的數組下標) 注意:字段為返回類型(return_type_idx)的值,是類型表中的索引。 ④ 字段表
字段表項中內容存儲的是字段的信息。包括字段所在類(class_idx)、字段的類型(type_idx)、 字段的名稱(name_idx), class_idx 是類型表中的索引,type_idx 是類型表中的索引,字段名稱 的索引是字符串表的數組下標。 ⑤ 方法表
方法表項中存儲的是方法的信息,包括方法所在的類(class_idx)、方法的原型(proto_idx)、方 法的名稱(name_idx),其中 class_idx 是類型表中的索引,proto_idx 是在原型表中的索引,方 法名稱的索引是字符串表的數組下標。
類數據 類數據也是一個數組,每一個元素就是一個類的相關信息。
在表項中的 class_data 中存儲的是類數據,包括類名索引、訪問屬性、父類索引、接口偏移、 源碼索引、注解偏移、類數據偏移。
在類數據中有存儲類中的字段和方法信息,在每一個方法中的 code_item 結構中有一個字段 insns 數組,存儲的是 dalvik 虛擬機指令。指令可以使用 baksmali 反匯編成 smali 代碼。 ushort insns[8] = 62 00 00 00 1A 01 00 00 6E 20 01 00 10 00 0E 00 第一字節:
指令 1:62 00 00 00 sget-object v0,field@0000
偽代碼:sget-object v0,out Smali 代碼:sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; Java 代碼:System.out
指令 2:1A 01 00 00 const-string v1,string@0000
偽代碼:const-string v1,string[0] Smali 代碼:const-string v1,“Hello World!” 指令 3:6E 20 01 00 10 00 invoke-virtual {v0,v1} , method@0001
偽代碼:invoke-virtual {v0, v1}, method[1]
Smali 代碼:invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 更詳細的需要查看 baksmali 的源代碼。
指令 4:0E 00 return-void
在線分析 Android
解決 修改 x dex 文件之后的錯誤
當我們修改 dex 文件之后,即使再簽名,再打包,最終還是無法安裝,因為 dex 文件對文件 有校驗,安裝時會讀取 dex 文件頭部的 hash 值和重新計算的值進行比對,完成校驗。
此時模擬器中有安裝殘留,需要在/data/data/目錄中刪除對應的安裝目錄 重新安裝,即可完成。
修復 dex文件的原理
將 dex 文件頭部的兩個 Hash 值重新計算,然后寫回去。 ① 先計算 SHA-1 值(第三個字段),修改值 ② 再計算 CheckSum 值(第二個字段),修改值