今日科技简讯
近日,有消息称“从5月1日起,银行将全面关闭芯片磁条复合卡的磁条交易”。业内人士表示:这个消息可以简单理解为只有磁条+芯片的复合银行卡磁条无效,但不会影响卡的使用;另外,普通的纯磁条卡还是可以正常使用的。
作者简介
Tryking的这篇贡献仔细分析了如何理解DEX文件的内容。由于其长度较长,处理十六进制数据,需要大家耐心阅读。
Tryking的博客地址:
http://blog.csdn.net/sinat_18268881
前言
DEX文件是Android Dalvik虚拟机运行的程序,关于DEX文件结构的重要性我就不多说了。接下来,开始练习!
建议:不要光看,跟着我。再看不如自己练靠谱。别问我为什么知道。撕裂塌陷.....
首先,我们需要自己构造一个dex文件,因为它构造简单,易于分析。当你简单地了解它时,你就会自然地理解困难的部分。
构建DEX文件
首先,我们编写一个简单的Java程序,如下所示:
看,这是DexTypeId数据结构,只包含一个数据deorIdx,它的值内容是DexStringId列表的索引。
还记得DexStringId是什么吗?当我们分析上面的字符串时,字符串的偏移位置由数据结构DexStringId描述,这意味着deorIdx指向由所有DEXstringid组成的列表的索引。
我们整理了上面所有的字符串,所以你可以把它们翻过来看看图片。然后我们来看看九类的类型代表了什么。看第一个“05 00 00 00”,也就是05h,也就是小数5。然后让我们看看上面排序的所有字符串,看看用5索引的是什么。调大一点就能看到“我”。接下来,我们依次整理这些类的类型,我们还可以得到类的类型列表
还好,里面只有一个参数。它也比较简单,就是一个指向DexTypeId列表的索引,也就是表示参数列表中某个特定参数的位置。
分析完这些数据结构,我们来详细分析一个类。不要分心,要从上面的104h开始。
在104h中,因为都是带有dexptoid数据结构的数据,所以一个dexptoid总共占用12个字节。因此,我们取前12个字节进行分析。“06 00 00 00,00 00 00 00,94 02 00 00”,这是12个字节。首先,“06 00 00 00”代表shortyIdx,它的值是一个指向DexStringId列表的索引。我们在DexStringId列表中找到第六个对应的值,也就是III,说明这个方法中声明的字符串是三个int。然后,“00 00 00 00”代表returnTypeIdx,它的值指向DexTypeId列表的索引。我们找到对应的值,也就是I,说明这个方法的返回值是int类型。最后我们看“94 02 00 00”,代表DexTypeList的位置偏移量,它的值是294h,我们找到这个位置
下面是DexTypeList的结构。首先看前4个字节,代表DexTypeItems的个数。“02 00 00 00”为2,表示有2个DexTypeItems,每个占2字节,即两者都为“00 00”,其值为DexTypeId列表的索引。我们来找出0对应的是I,也就是因此,我们确认了这个方法的说法。那就是int(int,int),你可以看看我们的源代码,getNumber方法真的是这样的。好了,第一种方法已经这样分析过了。现在我们还在把这些方法的声明整理成一个列表,以后可能会有数据指向它们的索引。
最后又完成了一个。我们准备继续以下工作。累了就先听点音乐,休息一下再看-_-
12.fieldIdsSize和fieldIdsOff字段。这两个字段指向索引文件中的字段名信息。我们看到这里
可以看到fieldIdsSize是3h,表示有3个字段。fieldIdsOff为158h,表示偏移量为158h。我们在这里继续看到158h:
咳咳,是时候建立新的数据结构了。忍忍就好。下一个数据结构是DexFieldId。让我们来看看
如你所见,这三个数据都是有针对性的指标值,我就不详细说了,看下面的备注即可。我们还是分析第一个字段,“01 00,00 00,13 00 00 00”,类类型是DexTypeId列表的index 1,也就是HelloWorld,字段类型是DexTypeId列表的index 0,也就是int,字段名是DexStringId列表的index 13h,也就是decimal 19。寻找它,它是A,也就是我们的,这不是我们在HelloWorld.java文件中定义的变量A吗?然后我们依次列出我们的三个领域:
int HelloWorld.a
java.lang.String HelloWorld.b
Java . io . PrintStream Java . lang . System . out
好了,先告一段落。继续分析下一个
13.methodIdsSize和methodIdsOff字段。这些字段指示方法所在的类、方法的声明和方法的名称。让我看看
第一,methodIdsSize是Ah,也就是十进制的10,表示有10个方法。MethodIdsOff,170h,表示它们的位置在170h偏移。我们看到这里
是的,是的,这是一个新的数据结构,但是这个和上一个一样简单,请参见索引方法
正确这个也简单。所有三个数据都是指向相应结构的索引值。我们直接分析第一个数据,“01 00,04 00,00 00 00 00 00”。第一,classIdx为1,对应于DexTypeId列表的索引1,即HelloWorld;其次,protoIdx是4,对应于DexProtoId列表中的索引4,即void();最后nameIdx为0,对应于DexStringId列表中的索引0,即,
好了,分析到此结束。让我们真正开始我们的精彩部分。让我们等一会儿再继续。
14.classDefsSize和classDefsOff字段。这两个字段指示关于索引文件中类定义的信息。让我们先找到他们的位置。
ClassDefsSize字段为1,即只有一个类定义,classDefsOff为1C0h,我们找到它的偏移位置。
在这里。到现在,你应该知道有了一个新的数据结构。是的,下一个数据结构是DexClassDef,请参见:
不用说了,直接根据结构开始分析吧。反正只有一个类定义。ClassIdx为1,对应于DexTypeId列表的索引1。它是HelloWorld,这是我们源程序中的类类型。
访问标志为1,是类的访问标志。对应的值是以ACC_开头的枚举值,1对应ACC_PUBLIC。你可以在010Editor里面看一下,说明我们班是公办的。
superclassIdx的值是3,找到了DexTypeId列表中的索引3,对应的是java.lang.Object,表示我们这个类的父类类型是Object。InterfaceOff指向了DexTypeList结构,这里我们有0,表示没有接口。如果有接口,直接对应DexTypeList,和之前分析的一样。这里不多解释。如果有兴趣,可以写一个带接口的类来验证。
接下来,sourceFileIdx指向代表源文件名的DexStringId列表的索引。我们这里有第4位,寻找字符串“HelloWorld.java”,表示我们的类程序的源文件名是HelloWorld.java。
注释关闭字段指向注释目录接口。根据不同的类型,会有注释类、注释方法、注释字段和注释参数。我们这里的值是0,这意味着没有注释。这里没有解释。如果你感兴趣,你可以自己试试。
接下来是classDataOff,指向DexClassData结构的位置偏移量,将类的数据部分存储在DexClassData中,我们来详细分析一下。首先,先找到偏移位置3F8h。
接下来,让我们看看索引类数据结构:
正如您所看到的,在DexClassData结构中引入了另外三种结构。让我们一起写出来看看
代码里的注释也很清楚,就不多说了。但是请注意,这些结构中的u4并不意味着它们占用4个字节,而是uleb128类型的数据(占用1~5个字节)。我还是不怎么说uleb128。想知道可以自己查。
好,那就开始分析。对于DexClassData,第一个是DexClassDataHeader,我们找到对应的位置。其实第一个staticFieldsSize只占用一个字节,也就是01h是它的值,也就是说有一个静态字段,然后instanceFieldsSize、DirectMethodsSize、virtualMethodsSize也只占用一个字节,也就是实例字段数为1,直接方法数为3,虚拟方法数为1。(刚好他们都占用一个字节,不一定只有一个字节。可以自己了解uleb128的数据类型。).
然后是staticFields,它对应的数据结构是DexField。你可以看到第一个fieldIdx是一个指向DexFieldId的索引,值为1,对应的索引值是java.lang.String HelloWorld.b第二个accessFlags的值是8,ACC_STATIC开头对应的数据是ACC _ STATIC(可以在010Editor中对应检查),说明我们的静态字段是STATIC Java . lang . string hello world . B .看我们的源代码,我们确实定义了一个static B变量。
然后看instanceFields,它的数据结构和staticFields一样。我们直接分析第一个fieldIdx的值为0,对应的DexField的索引值在elloworld.a .第二个accessFlags的值为0,ACC_ is 空开头对应的数据,也就是什么都没有。我们例子的字段是int HelloWorld.a..看看我们的源代码,我们确实定义了一个实例变量。
然后根据directMethodsSize,有三种直接方法。我们来看第一个,它对应的数据结构是DexMethod。首先,methodIdx指向值为0的DexMethodId的索引,发现对应的索引值是void hello world。clinit>。()。那么访问标志是...对于...对于...对于...我的天呐。本来以为可以这样蒙混过关,没想到遇到一个不占一个字节的uleb128数据。对应于此访问标志的值占用了三个字节,“88 80 04”。为什么?因为是按照uleb128格式的数据读取的(自己检查一下,先不要填这个坑,其实这种数据并不麻烦,就是前一个字节的最高位指定下一个字节的内容是否需要)。ACC_开头对应“88 80 04”的数据是ACC_STATIC ACC_CONSTRUCTOR,说明这个方法是静态的,是一个构造方法。
最后看codeOff,对应的是DexCode结构的偏移量。DexCode存储方法的指令集等信息,是真正的代码。暂时不分析DexCode,我们来看看它的偏移位置为“E0 03”。这等于什么?uleb128转换成十六进制数的结果是1E0h。即,索引代码存储在偏移位置1E0h。
具体的DexCode我们就不第一次分析了,因为里面存储的一些指令局需要根据相关数据逐一查找,有兴趣的可以自己去找数据。剩下的两种直接方法我们就不分析了。
接下来,我们看到根据virtualMethodsSize,有一个虚拟方法。我们直接看。首先methodIdx的值是2,对应的DexMethodId的索引值是in tello world . getnumber(int,int)。那么accessFlags为1,对应的值为ACC_PUBLIC,表示这是一个公共类。CodeOff为“FC 04”,对应位置为27Ch,此处不显示,自行查找。
好了,我们整个DEX文件的结构基本上已经从DexHeader分析出来了,很累,但是再分析一遍,我们会对DEX文件的格式有更深的理解。总比自己过来看别人的道理好!
参考:安卓软件安全与逆向分析。非蠕虫
更多的
厌倦了每天学习,看一些搞笑的段子放松一下。关注最具娱乐性的微信官方账号,每天都感觉不错。
如果你有好的技术文章可以分享给你,请提交到我的微信官方账号。详情请点击微信官方账号首页的“提交”菜单。
欢迎按图长->:识别图片中的二维码或扫描我的微信官方账号:
1.《dex 一篇文章带你搞懂DEX文件的结构》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《dex 一篇文章带你搞懂DEX文件的结构》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/caijing/804017.html