DEX文件解析 - field_ids解析
在上一篇中介绍了proto_ids的解析,那么接下来就要学习field_ids
的解析。
1. field_ids结构
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_;
....
....
};
从fieldId
的结构可以看出以下几点:
dex::TypeIndex class_idx_
:无符号int
类型,占2
个字节,类型索引列表的索引/下标
,表示的是字段所在的类dex::TypeIndex type_idx_
:无符号int
类型,占2
个字节,类型索引列表的索引/下标
,表示的是字段的类型dex::StringIndex name_idx_
:无符号int
类型,占4
个字节,字符串索引列表的索引/下标
,表示的是字段的名称(标识符)
2. 010Editor解析
如图,仔细观察
3. field_ids解析
java
语言解析field_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
分类:
Android常见格式解析
标签:
格式解析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!