DEX file parsing - field_ids parsing

In the previous article, the analysis of proto_ids was introduced , so the next step is to learn field_idsthe analysis.

1. field_ids structure

FieldId

 // Raw field_id_item.
struct FieldId {
    
    
   dex::TypeIndex class_idx_;   // index into type_ids_ array for defining class
   dex::TypeIndex type_idx_;    // index into type_ids_ array for field type
   dex::StringIndex name_idx_;  // index into string_ids_ array for field name

   private:
   DISALLOW_COPY_AND_ASSIGN(FieldId);
 };

StringIndex

class StringIndex {
    
    
 public:
  uint32_t index_;
  ....  
  ....
};

TypeIndex

class TypeIndex {
    
    
 public:
  uint16_t index_;
  ....  
  ....
};

The following points can be seen from fieldIdthe structure:

  1. dex::TypeIndex class_idx_: Unsigned inttype, occupying 2bytes, type index list 索引/下标, indicating the class where the field is located
  2. dex::TypeIndex type_idx_: Unsigned inttype, occupying 2bytes, type index list 索引/下标, indicating the type of the field
  3. dex::StringIndex name_idx_: Unsigned inttype, occupying 4bytes, string index list 索引/下标, representing the name (identifier) ​​of the field

2. Analysis of 010Editor

As shown in the picture, observe carefully
insert image description here

3. field_ids parsing

javalanguage analysisfield_ids

/**
 * 解析FieldIds
 * @param raf
 * @return
 */
 private static List<FieldId> toParseDexFieldIds(RandomAccessFile raf) {
    
    
     try {
    
    
         List<FieldId> fieldIdList = new ArrayList<>();
         //获取字段索引列表的文件偏移量
         int field_ids_off = mDexHeader.getField_ids_off();
         //获取字段索引列表大小
         int field_ids_size = mDexHeader.getField_ids_size();
         //偏移到字段索引列表位置
         raf.seek(field_ids_off);
         for (int i = 0; i < field_ids_size; i++) {
    
    
             //获取 这个字段所在的类的类名,类名idx在类型索引列表中
             int class_idx = NumConversion.byteToInt(readData(raf, 2), false);
             //获取 字段的类型,字段类型idx在类型索引列表中
             int type_idx = NumConversion.byteToInt(readData(raf, 2), false);
             //获取 字段的名字,字段的名字idx在字符串索引类中
             int field_name_idx = NumConversion.byteToInt(readData(raf, 4), false);
             //获取数据
             TypeId class_type_id = mTypeIds.get(class_idx);
             TypeId field_type_id = mTypeIds.get(type_idx);
             StringId class_type_string_id = mStringIds.get(class_type_id.getTypeDescriptorIdx());
             StringId field_type_string_id = mStringIds.get(field_type_id.getTypeDescriptorIdx());
             StringId field_name_string_id = mStringIds.get(field_name_idx);
             String class_type_string = new String(class_type_string_id.getData());
             String field_type_string = new String(field_type_string_id.getData());
             String field_name_string = new String(field_name_string_id.getData());

             FieldId fieldId = new FieldId();
             fieldId.setClass_idx(class_idx);
             fieldId.setType_idx(type_idx);
             fieldId.setName_idx(field_name_idx);
             fieldIdList.add(fieldId);

             System.out.println("在 " + class_type_string + "类中,存在 " + field_type_string + " " + field_name_string);

         }
         return fieldIdList;
     } catch (Exception e) {
    
    
          e.printStackTrace();
     }

     return null;
 }
 
 public static byte[] readData(RandomAccessFile raf,int limit) {
    
    
     byte[] buff = new byte[limit];
     try {
    
    
         raf.read(buff);
     } catch (IOException e) {
    
    
         e.printStackTrace();
     } 
     return buff;
 }

实体类FieldId

public class FieldId {
    
    
    private int class_idx;
    private int type_idx;
    private int name_idx;

    public int getClass_idx() {
    
    
        return class_idx;
    }

    public void setClass_idx(int class_idx) {
    
    
        this.class_idx = class_idx;
    }

    public int getType_idx() {
    
    
        return type_idx;
    }

    public void setType_idx(int type_idx) {
    
    
        this.type_idx = type_idx;
    }

    public int getName_idx() {
    
    
        return name_idx;
    }

    public void setName_idx(int name_idx) {
    
    
        this.name_idx = name_idx;
    }
}

工具类NumConversion

public class NumConversion {
    
    

    public static int byteToInt(byte[] bytes,boolean isBigEndian) {
    
    
        if (bytes.length <=0 || bytes.length > 4) return -1;
        int result = 0;
        for (int i=0;i<bytes.length;i++) {
    
    
            int b ;
            if(isBigEndian){
    
    
                b = (bytes[i] & 0xFF) << (8*(bytes.length-1-i));
            }else {
    
    
                b = (bytes[i] & 0xFF) << (8*i);
            }
            result = result | b;
        }
        return result;
    }
}

asjhan for Android reverse

Guess you like

Origin blog.csdn.net/qq_35993502/article/details/123906889