Android Dex文件格式(一)
dex是Android平台上(Dalvik虚拟机)的可执行文件, 相当于Windows平台中的exe文件, 每个Apk安装包中都有dex文件, 里面包含了该app的所有源码, 通过反编译工具可以获取到相应的java源码。
public class Hello
{
public static void MyPrint(String str)
{
System.out.printf(str + "\r\n");
}
public static void main(String[] argc)
{
MyPrint("nihao, shijie");
System.out.println("Hello World!");
}
}
javac Hello.java
dx --dex --output=Hello.dex Hello.class

javac -source 1.6 -target 1.6 Hello.javaadb push Hello.dex /mnt/sdcard/adb shell dalvikvm -cp /mnt/sdcard/Hello.dex Hello


| 字段名称 | 偏移量 | 长度(byte) | 当前例子中字段值 | 字段描述 |
| magic | 0x0 | 0x8 | dex 035 | dex魔术字, 固定信息: dex\n035 |
| checksum | 0x8 | 0x4 | 0x0F828C9C | alder32算法, 去除了magic和checksum 字段之外的所有内容的校验码 |
| signature | 0xc | 0x14 | 58339636BED8A6CC826E A09B77D5C3A620262CD |
sha-1签名, 去除了magic、checksum和 signature字段之外的所有内容的签名 |
| fileSize | 0x20 | 0x4 | 0x0000043C | 整个dex的文件大小 |
| headerSize | 0x24 | 0x4 | 0x00000070 | 整个dex文件头的大小 (固定大小为0x70) |
| endianTag | 0x28 | 0x4 | 0x12345678 | 字节序 (大尾方式、小尾方式) 默认为小尾方式 <--> 0x12345678 |
| linkSize | 0x2c | 0x4 | 0x00000000 | 链接段的大小, 默认为0表示静态链接 |
| linkOff | 0x30 | 0x4 | 0x00000000 | 链接段开始偏移 |
| mapOff | 0x34 | 0x4 | 0x0000039C | map_item偏移 |
| stringIdsSize | 0x38 | 0x4 | 0x00000019 | 字符串列表中的字符串个数 |
| stringIdsOff | 0x3c | 0x4 | 0x00000070 | 字符串列表偏移 |
| typeIdsSize | 0x40 | 0x4 | 0x00000009 | 类型列表中的类型个数 |
| typeIdsOff | 0x44 | 0x4 | 0x000000D4 | 类型列表偏移 |
| protoIdsSize | 0x48 | 0x4 | 0x00000006 | 方法声明列表中的个数 |
| protoIdsOff | 0x4c | 0x4 | 0x000000F8 | 方法声明列表偏移 |
| fieldIdsSize | 0x50 | 0x4 | 0x00000001 | 字段列表中的个数 |
| fieldIdsOff | 0x54 | 0x4 | 0x00000140 | 字段列表偏移 |
| methodIdsSize | 0x58 | 0x4 | 0x00000009 | 方法列表中的个数 |
| methodIdsOff | 0x5c | 0x4 | 0x00000148 | 方法列表偏移 |
| classDefsSize | 0x60 | 0x4 | 0x00000001 | 类定义列表中的个数 |
| classDefsOff | 0x64 | 0x4 | 0x00000190 | 类定义列表偏移 |
| dataSize | 0x68 | 0x4 | 0x0000028C | 数据段的大小, 4字节对齐 |
| dataOff | 0x6c | 0x4 | 0x000001B0 | 数据段偏移 |
//Direct-mapped "string_id_item".
struct DexStringId {
u4 stringDataOff; //file offset to string_data_item
};



| index | stringDataOff | utf16_size | data | string |
| 0 | 0x252 | 0x02 | 0x0D, 0x0A , 0x00 | 回车换行 |
| 1 | 0x256 | 0x06 | 0x3C, 0x69, 0x6E, 0x69, 0x74, 0x3E, 0x00 | <init> |
| 2 | 0x25E | 0x0C | 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00 | Hello World! |
| 3 | 0x26C | 0x0A | 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2E, 0x6A, 0x61, 0x76, 0x61, 0x00 | Hello.java |
| 4 | 0x278 | 0x01 | 0x4C, 0x00 | L |
| 5 | 0x27B | 0x07 | 0x4C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x3B, 0x00 | LHello; |
| 6 | 0x284 | 0x02 | 0x4C, 0x4C, 0x00 | LL |
| 7 | 0x288 | 0x03 | 0x4C, 0x4C, 0x4C, 0x00 | LLL |
| 8 | 0x28D | 0x15 | 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x69, 0x6F, 0x2F, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6D, 0x3B, 0x00 | Ljava/io/PrintStream; |
| 9 | 0x2A4 | 0x12 | 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x3B, 0x00 | Ljava/lang/Object; |
| 10 | 0x2B8 | 0x12 | 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x00 | Ljava/lang/String; |
| 11 | 0x2CC | 0x19 | 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x42, 0x75, 0x69, 0x6C, 0x64, 0x65, 0x72, 0x3B, 0x00 | Ljava/lang/StringBuilder; |
| 12 | 0x2E7 | 0x12 | 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x3B, 0x00 | Ljava/lang/System; |
| 13 | 0x2FB | 0x07 | 0x4D, 0x79, 0x50, 0x72, 0x69, 0x6E, 0x74, 0x00 | MyPrint |
| 14 | 0x304 | 0x01 | 0x56, 0x00 | V |
| 15 | 0x307 | 0x02 | 0x56, 0x4C, 0x00 | VL |
| 16 | 0x30B | 0x13 | 0x5B, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x3B, 0x00 | [Ljava/lang/Object; |
| 17 | 0x320 | 0x13 | 0x5B, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F, 0x6C, 0x61, 0x6E, 0x67, 0x2F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x3B, 0x00 | [Ljava/lang/String; |
| 18 | 0x335 | 0x06 | 0x61, 0x70, 0x70, 0x65, 0x6E, 0x64, 0x00 | append |
| 19 | 0x33D | 0x04 | 0x6D, 0x61, 0x69, 0x6E, 0x00 | main |
| 20 | 0x343 | 0x0D | 0x6E, 0x69, 0x68, 0x61, 0x6F, 0x2C, 0x20, 0x73, 0x68, 0x69, 0x6A, 0x69, 0x65, 0x00 | nihao, shijie |
| 21 | 0x352 | 0x03 | 0x6F, 0x75, 0x74, 0x00 | out |
| 22 | 0x357 | 0x06 | 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00 | printf |
| 23 | 0x35F | 0x07 | 0x70, 0x72, 0x69, 0x6E, 0x74, 0x6C, 0x6E, 0x00 | println |
| 24 | 0x368 | 0x08 | 0x74, 0x6F, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00 | toString |

//Direct-mapped "type_id_item".
struct DexTypeId {
u4 descriptorIdx; //DexStringId中的索引下标
};

| index | descriptorIdx | string |
| 0 | 0x05 | LHello; |
| 1 | 0x08 | Ljava/io/PrintStream; |
| 2 | 0x09 | Ljava/lang/Object; |
| 3 | 0x0A | Ljava/lang/String; |
| 4 | 0x0B | Ljava/lang/StringBuilder; |
| 5 | 0x0C | Ljava/lang/System; |
| 6 | 0x0E | V |
| 7 | 0x10 | [Ljava/lang/Object; |
| 8 | 0x11 | [Ljava/lang/String; |

3. 方法声明索引区, 描述dex文件中所有的方法声明
//Direct-mapped "proto_id_item".
struct DexProtoId {
u4 shortyIdx; //DexStringId中的索引下标
u4 returnTypeIdx; //DexTypeId中的索引下标
u4 parametersOff; //DexTypeList的偏移
};
//Direct-mapped "type_item".
struct DexTypeItem {
u2 typeIdx; //DexTypeId中的索引下标
};
//rect-mapped "type_list".
struct DexTypeList {
u4 size; //DexTypeItem的个数
DexTypeItem list[1]; //DexTypeItem变长数组
};


| index | shortyIdx | returnTypeIdx | parametersOff | shortyIdx_string | returnTypeIdx_string |
| 0 | 0x07 | 0x01 | 0x23C | LLL | Ljava/io/PrintStream; |
| 1 | 0x04 | 0x03 | 0x0 | L | Ljava/lang/String; |
| 2 | 0x06 | 0x04 | 0x244 | LL | Ljava/lang/StringBuilder; |
| 3 | 0x0E | 0x06 | 0x0 | V | V |
| 4 | 0x0F | 0x06 | 0x244 | VL | V |
| 5 | 0x0F | 0x06 | 0x24C | VL | V |
type_list:
| parametersOff | typeIdx | string |
| 0x23C | 0x03 | Ljava/lang/String; |
| 0x23C | 0x07 | [Ljava/lang/Object; |
| 0x244 | 0x03 | Ljava/lang/String; |
| 0x24C | 0x08 | [Ljava/lang/String; |
//Direct-mapped "field_id_item".
struct DexFieldId {
u2 classIdx; 类的类型, DexTypeId中的索引下标
u2 typeIdx; 字段类型, DexTypeId中的索引下标
u4 nameIdx; 字段名称, DexStringId中的索引下标
};

| index | classIdx | typeIdx | nameIdx | classIdx_string | typeIdx_string | nameIdx_string |
| 0 | 0x05 | 0x01 | 0x15 | Ljava/lang/System; | Ljava/io/PrintStream; | out |
//Direct-mapped "method_id_item".
struct DexMethodId{
u2 classIdx; 类的类型, DexTypeId中的索引下标
u2 protoIdx; 声明类型, DexProtoId中的索引下标
u4 nameIdx; 方法名, DexStringId中的索引下标
};

| index | classId | protoIdx | nameIdx | classIdx_string | protoIdx_string | nameIdx_string |
| 0 | 0x00 | 0x03 | 0x01 | LHello; | void() | <init> |
| 1 | 0x00 | 0x04 | 0x0D | LHello; | void(Ljava/lang/String;) | MyPrint |
| 2 | 0x00 | 0x05 | 0x13 | LHello; | void([Ljava/lang/String;) | main |
| 3 | 0x0x1 | 0x00 | 0x16 | Ljava/io/PrintStream; | Ljava/io/PrintStream; (Ljava/lang/String;, [Ljava/lang/Object;) |
printf |
| 4 | 0x01 | 0x04 | 0x17 | Ljava/io/PrintStream; | void(Ljava/lang/String;) | println |
| 5 | 0x02 | 0x03 | 0x01 | Ljava/lang/Object; | void() | <init> |
| 6 | 0x04 | 0x03 | 0x04 | Ljava/lang/StringBuilder; | void() | <init> |
| 7 | 0x04 | 0x02 | 0x12 | Ljava/lang/StringBuilder; | Ljava/lang/StringBuilder; (Ljava/lang/String;) |
append |
| 8 | 0x04 | 0x01 | 0x18 | Ljava/lang/StringBuilder; | Ljava/lang/String;() | toString |
//Direct-mapped "map_list".
struct DexMapList {
u4 size; //DexMapItem的个数
DexMapItem list[1]; //变长数组
};
struct DexMapItem {
u2 type; //kDexType开头的类型
u2 unused; //未使用, 用于字节对齐
u4 size; //指定类型的个数
u4 offset; //指定类型数据的文件偏移
};
/* map item type codes */
enum {
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
kDexTypeProtoIdItem = 0x0003,
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
kDexTypeClassDefItem = 0x0006,
kDexTypeMapList = 0x1000,
kDexTypeTypeList = 0x1001,
kDexTypeAnnotationSetRefList = 0x1002,
kDexTypeAnnotationSetItem = 0x1003,
kDexTypeClassDataItem = 0x2000,
kDexTypeCodeItem = 0x2001,
kDexTypeStringDataItem = 0x2002,
kDexTypeDebugInfoItem = 0x2003,
kDexTypeAnnotationItem = 0x2004,
kDexTypeEncodedArrayItem = 0x2005,
kDexTypeAnnotationsDirectoryItem = 0x2006,
};

| index | type | unused | size | offset | type_string |
| 0 | 0x00 | 0x00 | 0x01 | 0x00 | kDexTypeHeaderItem |
| 1 | 0x01 | 0x00 | 0x19 | 0x70 | kDexTypeStringIdItem |
| 2 | 0x02 | 0x00 | 0x09 | 0xD4 | kDexTypeTypeIdItem |
| 3 | 0x03 | 0x00 | 0x06 | 0xF8 | kDexTypeProtoIdItem |
| 4 | 0x04 | 0x00 | 0x01 | 0x140 | kDexTypeFieldIdItem |
| 5 | 0x05 | 0x00 | 0x09 | 0x148 | kDexTypeMethodIdItem |
| 6 | 0x06 | 0x00 | 0x01 | 0x190 | kDexTypeClassDefItem |
| 7 | 0x2001 | 0x00 | 0x03 | 0x1B0 | kDexTypeCodeItem |
| 8 | 0x1001 | 0x00 | 0x03 | 0x23C | kDexTypeTypeList |
| 9 | 0x2002 | 0x00 | 0x19 | 0x252 | kDexTypeStringDataItem |
| 10 | 0x2003 | 0x00 | 0x03 | 0x372 | kDexTypeDebugInfoItem |
| 11 | 0x2000 | 0x00 | 0x01 | 0x388 | kDexTypeClassDataItem |
| 12 | 0x1000 | 0x00 | 0x01 | 0x39C | kDexTypeMapList |
Android Dex文件格式(一)的更多相关文章
- Android Dex文件格式(二)
第三块: 数据区 索引区中的最终数据偏移以及文件头中描述的map_off偏移都指向数据区, 还包括了即将要解析的class_def_item, 这个结构非常重要,下面就开始解析 c ...
- Android Dex文件格式解析
Dex文件是Android虚拟机下的可执行文件,包含了应用程序所用到所有操作指令和运行时数据.在程序编译过程中,java源文件先被编译成class文件,然后通过dx工具将多个class文件整合为一个d ...
- dex文件格式一
一.生成dex文件 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.jav ...
- dex文件格式学习
一.dex文件的生成 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.ja ...
- [Android Security] DEX文件格式分析
copy from : https://segmentfault.com/a/1190000007652937 0x00 前言 分析 dex 文件格式最好的方式是找个介绍文档,自己再写一个简单的 de ...
- Android逆向之旅---解析编译之后的Dex文件格式
一.前言 新的一年又开始了,大家是否还记得去年年末的时候,我们还有一件事没有做,那就是解析Android中编译之后的classes.dex文件格式,我们在去年的时候已经介绍了: 如何解析编译之后的xm ...
- dex文件格式二
一. dex文件头 (1) magic value 在DexFile.c dexFileParse函数中 会先检查magic opt 啥是magic opt呢? 我们刚刚从cache目录拷贝出来的 ...
- Android学习笔记----解决“com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536”问题
同时在工程中引入了多个第三方jar包,导致调用的方法数超过了android设定的65536个(DEX 64K problem),进而导致dex无法生成,也就无法生成APK文件. 解决办法如下: 1.谷 ...
- 解决“com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536”问题(l转)
同时在工程中引入了多个第三方jar包,导致调用的方法数超过了android设定的65536个(DEX 64K problem),进而导致dex无法生成,也就无法生成APK文件. 解决办法如下: 1.谷 ...
随机推荐
- 《所用到的AJAX技术基础》
来自百度网页,w3cshool网页:AJAX = Asychronous JavaScript and XML,翻译成中文为:异步的JavaScript XML. 异步的意思就是不重新加载整个页面,后 ...
- [REP]AWS Regions and Availability Zones: the simplest explanation you will ever find around
When it comes to Amazon Web Services, there are two concepts that are extremely important and spanni ...
- vmware 修改IP 提示子网掩码错误~
我打开[编辑]->[虚拟网络编辑器]菜单 修改网络设置 提示 子网掩码错误 如下图所示 上网查询,使用如下方法解决问题 这个虚拟网络编辑器是给你添加网卡的,你添加vmnet1就是在你真实的电脑上 ...
- vs文件属性(生成操作)各选项功能(发布Web项目时使用)
转自:http://www.cnblogs.com/paulhe/p/4490583.html 右击项目里的文件,选择属性(F4)会有[生成操作]的选项. 它提供了14项选择,如图: 在这说一下常用的 ...
- cordova-screenshot
The Screenshot plugin allows your application to take screenshots of the current screen and save the ...
- 使用Maven加载项目有Dubbo框架时出现的常见异常情况
异常描述: The matching wildcard is strict, but no declaration can be found for element 'dubbo ...
- python download
今天下载 python3 , 从官网下 速度 平均 十几K,网上 搜了下.提供的下载地址 几乎都是 官网的. 于是 下了个 百度同步盘,做 公开分享. 提供给 大家下载,速度 有 300 多K,提高了 ...
- linux shell 常用表达式汇总
1. linux shell 逻辑运算符.逻辑表达式详解: http://www.cnblogs.com/chengmo/archive/2010/10/01/1839942.html
- js获取项目根目录的方法
getRootPath = function(){ //获取当前网址,如: http://localhost:8080/ems/Pages/Basic/Person.jsp var curWwwPat ...
- Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键?
本文主要介绍WebRTC端到端监控(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信I ...