安卓打开dex文件,android文件系统详解

当我们编写Java代码时,生成的文件是. Java文件,但JVM不知道这一点,所以首先将其转换为class文件,但在Android端,Android上的Davlik虚拟机可以执行. dex 因此,dex文件包含所有app代码,并且可以使用反编译工具检索java代码。

也就是说,dex文件是Android Dalvik虚拟机运行的程序。

为了加深图像,首先创建dex文件。

公共类dex { int a=0; 静态字符串b=’ hellodalvik ‘; 公共int getnumber (inti,int j ) ) inte=3; return e i j; } publicstaticvoidmain (字符串[ ] args ) { int c=1; int d=2; DEX dex=new DEX (; stringsaynumber=string.value of (dex.getnumber (c,d ) ); system.out.println (hellodalvik ‘ say number ); }先运行javac DEX.java

这将生成. class文件,并在SDK中找到dx.bat。

运行xx\XXX\XXX\dx– dex– output=dex.Java dex.class

这将生成DEX.dex文件,如果发生does not match path错误,则执行以下操作:

d :\SDK\build-tools\27.0.1\dx– dex– output=dex.dexcom _ example _ ASUS1_ rexiu fu _ dex.ccoom

DEX文件结构

让我们先看看Header :

文件头包含dex文件的信息,所有数据的大致分布情况

接下来,我们来看看Header的数据图。 让我们打个满意的电话看看:

可以看到第一个。 是magic[8]。 这表示dex文件中的文件标记,一般称为魔数。 用于识别名为dex的文件,可以确定当前dex文件是否有效。 可以看到,它由8字节的1字节无符号数表示。 我们在满意的电话中看到“64 65 78 0A 30 33 35 00字节。 所有这些字节都用十六进制表示。 这8个字节通过ASCII码转换为dex.035。 “.”不是转换的。 现在,德克斯的魔数固定在德克斯. 035

第二个是checksum,这是dex文件的校验和,从而可以确定dex文件是否损坏或篡改。 占用4个字节

可以看到,该值及其对应的4字节正好相反。 这是因为dex文件采用了小字节顺序的编码方法,低阶比特中存储的是低字节的内容。

第三个字段SHA1 signature[20],signature用于验证dex文件,实际上是整个dex文件在SHA-1上签名的值。 这里占用了20字节。

第四个是fileSize,表示整个文件的大小,占用4个字节

第五个是headerSize,表示DexHeader报头结构的大小,占用4个字节。

第六个是endianTag,表示端序符号,用于dex运行环境中的cpu。 默认值为0x 12345678,101满意的电话支持“78 56 34 12”

以下两个分别是linkSizelinkOff,这是用于指定链接段大小和文件偏移的字段,通常均为0 : 如果linkSize为0,则表示静态连接。

接下来是mapOff字段。 这指定DexMapList的文件偏移,也就是dex文件映射的最后一个层次。

以下两个3358www.Sina.com/和StringIdsSize:这些字段指定在dex文件中使用的所有字符串的数量和位置偏移。 首先,让我们看看StringIdsSize。 目前,十进制值为28。 也就是说,这个dex文件共有28个字符串。 StringIdsOff的值为700000,表示字符串的偏移位置为70h。 然后,找到70h的位置。

第四个字符串是” HelloDalVik “,

让我们来看看dex的结构图:

然后我们继续看

接下来是StringIdsOfftypeIdsSize,它们表示类类型的数量和位置的偏差,均占4个字节,为类型大小

的的值为9,表示dex文件中用到的类的类型一共有9个,typeIdsOff的值为“E0 00 00 00 ”,即偏移位置在E0:

接下来两个是protoIdsSizeprotoIdsOff,它们表示dex文件中方法原型的个数和位置偏移,现在protoIdsSize的值为7,说明有7个方法原型,然后位置偏移是104h

这里涉及到一个数据结构:

struct DexProtoId{u4 shortyIdx;/*指向DexStringId列表的索引*/u4 returnTypeIdx;/*指向DexTypeId列表的索引*/u4 parametersOff;/*指向DexTypeList的位置偏移*/}

可以看到,这个数据结构由三个变量组成。第一个shortyIdx,它指向我们上面分析的DexStringId列表的索引,代表的是方法声明字符串。第二个returnTypeIdx它指向的是我们上班分析的DexTypeId列表索引,代表的是方法返回类型字符串。第三个parameterOff指向的是DexTypeList的位置索引,这又是一个新的数据结构,这里面存储的是方法的参数类别。
可以看到这三个参数,方法声明字符串,返回类型,参数列表,这基本上确定了我们一个方法的大体内容。

struct DexTypeList{u4 size;/*DexTypeItem的个数*/DexTypeItem list[1];/*DexTypeItem结构*/}struct DexTypeItem{u2 typeIdx;/*指向DexTypeId列表的索引*/}

这样的话,我们可以看到,第一个方法为 int(int,int)

我们继续看下面的两个,fieldIdsSizefieldIdsOff,指向的是dex文件中字段名的信息。这里fieldIdsSize的大小为3,fieldIdsOff的值为“58 01 00 00 ”:

又涉及到有个数据结构:

struct DexFieldId{u2 classIdx;/*类的类型,指向DexTypeId列表的索引*/u2 typeIdx;/*字段类型,指向DexTypeId列表的索引*/u4 nameIdx;/*字段名,指向DexStringId列表的索引*/}

我们可以看到第一个DexFieldId是Dex中的a

继续继续,methodIdsSizemethodIdsOff,指明了方法所在的类,方法的声明以及方法名,现在methodIdsSize的值为10,methodIdsOff的值为“70 01 00 00”,

它涉及到的数据结构:

struct DexMethodId{u2 classIdx;/*类的类型,指向DexTypeId列表的索引*/u2 protoIdx;/*声明类型,指向DexProtoId列表的索引*/u4 nameIdx;/*方法名,指向DexStringId列表的索引*/}

分析可以得到,第一个方法为 void DEX.<clinit>()

接下来是classDefsSizeclassDefsOff,这两个字段指明的是dex文件中类的定义的相关信息,在这里,classDefsSize的值是1,classDefsOff的是“C0 01 00 00”,

这里涉及的数据结构:

struct DexClassDef{u4 classIdx;/*类的类型,指向DexTypeId列表的索引*/u4 accessFlags;/*访问标志*/u4 superclassIdx;/*父类类型,指向DexTypeId列表的索引*/u4 interfacesOff;/*接口,指向DexTypeList的偏移*/u4 sourceFileIdx;/*源文件名,指向DexStringId列表的索引*/u4 annotationsOff;/*注解,指向DexAnnotationsDirectoryItem结构*/u4 classDataOff;/*指向DexClassData结构的偏移*/u4 staticValuesOff;/*指向DexEncodedArray结构的偏移*/}

我们可以看到,这个找到的类是DEX

接下来是DataSizeDataOff,这里DataOff的值是“E0 01 00 00 ”,找到01E0h,这里存放的是DexCode。

dex文件的加载流程

https://blog.csdn.net/jsqfengbao/article/details/52103439
https://www.jianshu.com/p/c9fd64e0b934

参考:
https://blog.csdn.net/sinat_18268881/article/details/55832757

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注