13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

DEX文件格式分析

前段时间忙于破解移动和电信的 apk ,挺久没有更新博客了,最近在写个工具,主要功能是通过配置对 dex 文件中的类型、函数、属性进行隐藏,达到防止被静态分析的效果。所以在写工具前必须对 dex 的文件格式有个清晰的认识,相对于 elf 文件格式 dex 文件格式会简单一些。

成都创新互联是一家集网站建设,济源企业网站建设,济源品牌网站建设,网站定制,济源网站建设报价,网络营销,网络优化,济源网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

原文链接: DEX文件格式分析

0x00 前言

分析 dex 文件格式最好的方式是找个介绍文档,自己再写一个简单的 demo 然后用 010Editor 对照着分析。文档可以参考官方文档http://source.Android.com/devices/tech/dalvik/dex-format.html,英文差的也可以找个中文的,比如说我。。。。。。

010Editor 这个工具比较好用,之前分析 elf 文件也是用的它。其实只要装了模板,可以分析很多文件。虽然是收费软件,有30天免费试用。但是如果你用的是 mac 试用期到了, 删一下这个文件 ~/.config/SweetScape/010 Editor.ini。

0x01 文件布局

dex 文件可以分为3个模块,头文件(header)、索引区(xxxx_ids)、数据区(data)。头文件概况的描述了整个 dex 文件的分布,包括每一个索引区的大小跟偏移。索引区的ids 是 identifiers 的缩写,表示每个数据的标识,索引区主要是指向数据区的偏移。 

010Editor 中除了数据区(data)没有显示出来,其他区段都有显示,另外 link_data 在模板中被定为 map_list 

0x02 header

header 描述了 dex 文件信息,和其他各个区的索引。010Editor(写010Editor 有点麻烦下面直接写010)中用结构体 struct header_item 来描述 header。 

其中用到了两种数据类型char、uint。这里的 char 是 C/C++ 中的char 占 8-bit, java 中的 char 是占 16-bit 有点区别,但是我们可以他来表示 short/ushort 这个以后介绍最近写的工具会介绍。官方文档是用 ubyte来定义的,那还是按官方的来吧。结构体描述:

 
 
 
 
  1. ubyte 8-bit unsinged int 
  2. uint  32-bit unsigned int, little-endian 
  3.  
  4. struct header_item  
  5.     ubyte[8]  magic; 
  6.     unit      checksum;  
  7.     ubyte[20] signature;  
  8.     uint      file_size;  
  9.     uint      header_size;  
  10.     unit      endian_tag;  
  11.     uint      link_size;  
  12.     uint      link_off;  
  13.     uint      map_off; 
  14.     uint      string_ids_size;  
  15.     uint      string_ids_off;  
  16.     uint      type_ids_size;  
  17.     uint      type_ids_off;  
  18.     uint      proto_ids_size;  
  19.     uint      proto_ids_off;  
  20.     uint      method_ids_size;  
  21.     uint      method_ids_off;  
  22.     uint      class_defs_size;  
  23.     uint      class_defs_off;  
  24.     uint      data_size; 
  25.     uint      data_off;  

 除了 magic、checksum、signature、file_size、endian_tag、map_off 其他元素都是成对出现的。_off 表示元素的偏移量,_size 表示元素的个数。其余的6个描述主要是 dex 文件的信息。

 
 
 
 
  1. {0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00} = "dex\n035\0" 

中间是一个换行,后面035是版本号。

0x03 string_ids

string_ids 区段描述了 dex 文件中所有的字符串。格式很简单只有一个偏移量,偏移量指向了 string_data 区段的一个字符串: 

上述描述里提到了 LEB128 ( little endian base 128 ) 格式,是基于 1 个 byte 的一种不定长度的编码方式。若第一个 byte 的最高位为1,则表示还需要下一个 byte 来描述,直至最后一个 byte 的最高位为 0。每个 byte 的其余 bit 用来表示数据,如下表所示。实际中 LEB128 最大只能达到 32-bit 可以阅读 dalvik 中的Leb128.h源码看出来。 

数据结构为:

 
 
 
 
  1. ubyte    8-bit unsinged int 
  2. uint     32-bit unsigned int, little-endian 
  3. uleb128  unsigned LEB128, valriable length 
  4.  
  5. struct string_ids_item 
  6.     uint string_data_off; 
  7.  
  8. struct string_data_item  
  9.     uleb128 utf16_size; 
  10.     ubyte   data;  

 其中 data 保存的就是字符串的值。string_ids 是比较关键的,后续的区段很多都是直接指向 string_ids 的 index。在写工具进行比较的时候也需要提取到 string_id

0x04 type_ids

type_ids 区索引了 dex 文件里的所有数据类型,包括 class 类型,数组类型(array types)和基本类型(primitive types)。区段里的元素格式为 type_ids_item,结构描述如下 :

 
 
 
 
  1. uint 32-bit unsigned int, little-endian 
  2.  
  3. struct type_ids_item 
  4.     uint descriptor_idx;  //-->string_ids 

 type_ids_item 里面 descriptor_idx 的值的意思,是 string_ids 里的 index 序号,是用来描述此 type 的字符串。

0x05 proto_ids

proto 的意思是 method prototype 代表 java 语言里的一个 method 的原型 。proto_ids 里的元素为 proto_id_item,结构如下:

 
 
 
 
  1. uint 32-bit unsigned int, little-endian  
  2.  
  3. struct proto_id_item 
  4.     uint shorty_idx;        //-->string_ids 
  5.     uint return_type_idx;    //-->type_ids 
  6.     uint parameters_off; 
  7. }  

0x06 field_ids

filed_ids 区里面有 dex 文件引用的所有的 field。区段的元素格式是 field_id_item,结构如下:

 
 
 
 
  1. ushort 16-bit unsigned int, little-endian  
  2. uint   32-bit unsigned int, little-endian  
  3.  
  4. struct filed_id_item 
  5.     ushort class_idx;  //-->type_ids 
  6.     ushort type_idx;   //-->type_ids 
  7.     uint   name_idx;   //-->string_ids 
  8. }  

0x07 method_ids

method_ids 是索引区的最后一个条目,描述了 dex 文件里的所有的 method。method_ids 的元素格式是 method_id_item,结构跟 fields_ids 很相似:

 
 
 
 
  1. ushort 16-bit unsigned int, little-endian  
  2. uint   32-bit unsigned int, little-endian  
  3.  
  4. struct filed_id_item 
  5.     ushort class_idx;  //-->type_ids 
  6.     ushort proto_idx;   //-->proto_ids 
  7.     uint   name_idx;   //-->string_ids 
  8. }  

0x08 class_defs

class_def 区段主要是对 class 的定义,它的结构很复杂,看的我有点晕,一层套一层。先看一张 010 的结构图: 

看着都晕,别说解析的时候了。

class_def_item

class_def_item 结构描述如下:

 
 
 
 
  1. uint   32-bit unsigned int, little-endian 
  2.  
  3. struct class_def_item 
  4.     uint class_idx;         //-->type_ids    
  5.     uint access_flags;         
  6.     uint superclass_idx;    //-->type_ids 
  7.     uint interface_off;     //-->type_list 
  8.     uint source_file_idx;    //-->string_ids 
  9.     uint annotations_off;    //-->annotation_directory_item 
  10.     uint class_data_off;    //-->class_data_item 
  11.     uint static_value_off;    //-->encoded_array_item 
  12. }  

type_list

type_list 在 data 区段,class_def_item->interface_off 就是指的这里的数据。数据结构如下:

 
 
 
 
  1. uint   32-bit unsigned int, little-endian 
  2.  
  3. struct type_list 
  4.     uint       size; 
  5.     type_item  list [size]  
  6.  
  7. struct type_item 
  8.     ushort type_idx   //-->type_ids 
  9. }  

annotations_directory_item

class_def_item->annotations_off 指向的数据区段,定义了 annotation 相关的数据描述,数据结构如下:

 
 
 
 
  1. uint   32-bit unsigned int, little-endian 
  2.  
  3. struct annotation_directory_item 
  4.     uint class_annotations_off;        //-->annotation_set_item 
  5.     uint fields_size; 
  6.     uint annotated_methods_size; 
  7.     uint annotated_parameters_size; 
  8.      
  9.     field_annotation field_annotations[fields_size]; 
  10.     method_annotation method_annotations[annotated_methods_size]; 
  11.     parameter_annotation parameter_annotations[annotated_parameters_size]; 
  12.  
  13. struct field_annotation 
  14.     uint field_idx; 
  15.     uint annotations_off;    //-->annotation_set_item 
  16.  
  17. struct method_annotation 
  18.     uint method_idx; 
  19.     uint annotations_off;    //-->annotation_set_item 
  20.  
  21. struct parameter_annotation 
  22.     uint method_idx; 
  23.     uint annotations_off;    //-->annotation_set_ref_list 
  24. }  

class_data_item

class_data_off 指向 data 区里的 class_data_item 结构,class_data_item 里存放着本 class 使用到的各种数据,下面是 class_data_item 的结构 :

 
 
 
 
  1. uleb128 unsigned little-endian base 128  
  2.  
  3. struct class_data_item 
  4.     uleb128 static_fields_size; 
  5.     uleb128 instance_fields_size; 
  6.     uleb128 direct_methods_size; 
  7.     uleb128 virtual_methods_size; 
  8.  
  9.     encoded_field  static_fields[static_fields_size]; 
  10.     encoded_field  instance_fields[instance_fields_size]; 
  11.     encoded_method direct_methods[direct_methods_size]; 
  12.     encoded_method virtual_methods[virtual_methods_size]; 
  13.  
  14. struct encoded_field 
  15.     uleb128 filed_idx_diff;  
  16.     uleb128 access_flags;   
  17.  
  18. struct encoded_method 
  19.     uleb128 method_idx_diff;  
  20.     uleb128 access_flags;  
  21.     uleb128 code_off; 
  22. }  

class_data_item

下面几个就是对于的描述

encoded_field

code_item

code_item 结构里描述着某个 method 的具体实现,它的结构描述如下:

 
 
 
 
  1. struct code_item  
  2.     ushort                         registers_size; 
  3.     ushort                         ins_size; 
  4.     ushort                         outs_size; 
  5.     ushort                         tries_size; 
  6.     uint                         debug_info_off; 
  7.     uint                         insns_size; 
  8.     ushort                         insns [insns_size];  
  9.     ushort                         paddding;             // optional 
  10.     try_item                     tries [tyies_size]; // optional 
  11.     encoded_catch_handler_list  handlers;             // optional 
  12. }  

末尾的 3 项标志为 optional , 表示可能有 ,也可能没有 ,根据具体的代码来。

encoded_array_item

class_def_item->static_value_off 偏移指向该区段数据。

 
 
 
 
  1. uleb128  unsigned LEB128, valriable length 
  2.  
  3. struct encoded_array_item 
  4.     encoded_array value; 
  5.  
  6. struct encoded_array 
  7. {     
  8.     uleb128 size; 
  9.     encoded_value values[size]; 
  10. }  

0x09 map_list

map_list 中大部分 item 跟 header 中的相应描述相同,都是介绍了各个区的偏移和大小,但是 map_list 中描述的更加全面,包括了 HEADER_ITEM 、TYPE_LIST、STRING_DATA_ITEM、DEBUG_INFO_ITEM 等信息。

010 中map_list 表示为: 

数据结构为:

 
 
 
 
  1. ushort 16-bit unsigned int, little-endian 
  2. uint   32-bit unsigned int, little-endian 
  3.  
  4. struct map_list  
  5.     uint     size; 
  6.     map_item list [size];  
  7. struct map_item  
  8.     ushort type;  
  9.     ushort unuse;  
  10.     uint   size;  
  11.     uint   offset; 
  12. }  

map_list 里先用一个 uint 描述后面有 size 个 map_item,后续就是对应的 size 个 map_item 描述。 map_item 结构有 4 个元素: type 表示该 map_item 的类型,Dalvik Executable Format 里 Type Code 的定义; size 表示再细分此 item,该类型的个数;offset 是第一个元素的针对文件初始位置的偏移量; unuse 是用对齐字节的,无实际用处。 


网站题目:DEX文件格式分析
转载来源:http://cdbrznjsb.com/article/djsehsd.html

其他资讯

让你的专属顾问为你服务