当前位置:网站首页>DEX文件解析 - method_ids解析
DEX文件解析 - method_ids解析
2022-06-30 19:52:00 【asjhan】
在上一篇中介绍了field_ids的解析,那么接下来就要学习method_ids的解析。
1. method_ids结构
在android的aosp源码中,method_ids的结构如下:
aosp源码位置:art/libdexfile/dex/dex_file.h
// Raw method_id_item.
struct MethodId {
dex::TypeIndex class_idx_; // index into type_ids_ array for defining class
uint16_t proto_idx_; // index into proto_ids_ array for method prototype
dex::StringIndex name_idx_; // index into string_ids_ array for method name
private:
DISALLOW_COPY_AND_ASSIGN(MethodId);
};
StringIndex
class StringIndex {
public:
uint32_t index_;
....
....
};
TypeIndex
class TypeIndex {
public:
uint16_t index_;
....
....
};
从method的结构可以看出以下几点:
dex::TypeIndex class_idx_: 无符号int类型,占2个字节。类型索引列表的索引/下标,表示的是方法所在的类uint16_t proto_idx_:无符号int类型,占2个字节。原型索引列表的索引/下标,表示的是方法的原型(签名)dex::StringIndex name_idx_:无符号int类型,占4个字节。字符串索引列表的索引/下标,表示的是方法的名称
2.010Editor解析

3.method_ids解析
/** * 解析MethodIds * @param raf * @return */
private static List<MethodId> toParseDexMethodIds(RandomAccessFile raf) {
try {
List<MethodId> methodIdList = new ArrayList<>();
//获取到方法索引列表的文件偏移量
int method_ids_off = mDexHeader.getMethod_ids_off();
//获取到方法索引列表的大小
int method_ids_size = mDexHeader.getMethod_ids_size();
//偏移到方法索引列表位置
raf.seek(method_ids_off);
for (int i = 0; i < method_ids_size; i++) {
//获取 这个字段所在的类的类名,类名idx在类型索引列表中
int class_idx = NumConversion.byteToInt(readData(raf, 2), false);
//获取 这个字段的原型(方法签名),原型idx在原型索引列表中
int proto_idx = NumConversion.byteToInt(readData(raf,2),false);
//获取 这个字段的方法名称,方法名称idx在字符串索引列表中
int name_idx = NumConversion.byteToInt(readData(raf,4),false);
//打印数据
//获取方法名称
StringId name_string_id = mStringIds.get(name_idx);
String name_string = new String(name_string_id.getData());
//获取类
TypeId class_type_id = mTypeIds.get(class_idx);
StringId class_type_string_id = mStringIds.get(class_type_id.getTypeDescriptorIdx());
String class_type_string = new String(class_type_string_id.getData());
//获取返回值类型
ProtoId proto_id = mProtyIds.get(proto_idx);
TypeId return_type_id = mTypeIds.get(proto_id.getReturnIdx());
StringId return_type_string_id = mStringIds.get(return_type_id.getTypeDescriptorIdx());
String return_type_string = new String(return_type_string_id.getData());
//获取方法参数列表
StringBuilder sb = new StringBuilder("(");
for (int j=0;j<proto_id.getParameter_size();j++) {
int parame_idx = proto_id.getParameterIdxs()[j];
TypeId parame_type_id = mTypeIds.get(parame_idx);
StringId parame_string_id = mStringIds.get(parame_type_id.getTypeDescriptorIdx());
sb.append(new String(parame_string_id.getData()));
if (j == proto_id.getParameter_size()-1) {
sb.append(")");
}else if (proto_id.getParameter_size() != 1) {
sb.append(", ");
}
}
if (proto_id.getParameter_size() == 0) sb.append(")");
//创建实体类
MethodId methodId = new MethodId();
methodId.setClass_idx(class_idx);
methodId.setProto_idx(proto_idx);
methodId.setName_idx(name_idx);
methodIdList.add(methodId);
System.out.println(i+" 在 " + class_type_string + "类中, 方法:" +return_type_string+" "+name_string+sb.toString());
}
return methodIdList;
}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;
}
实体类MethodId
public class MethodId {
private int class_idx;
private int proto_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 getProto_idx() {
return proto_idx;
}
public void setProto_idx(int proto_idx) {
this.proto_idx = proto_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
边栏推荐
- mysql主从同步
- 信息学奥赛一本通 1362:家庭问题(family)
- 项目经理是领导吗?可以批评指责成员吗?
- 【ICCV 2019】特征超分检测:Towards Precise Supervision of Feature Super-Resolution for Small Object Detection
- Qt:qaxobject operation Excel
- 【论文阅读】Trajectory-guided Control Prediction for End-to-end Autonomous Driving: A Simple yet Strong Baseline
- QT :QAxObject操作Excel
- Meeting, onemeeting, OK!
- SM2246EN+闪迪15131
- 一文读懂目标检测:R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD「建议收藏」
猜你喜欢
随机推荐
屏幕显示技术进化史
Transport layer uses sliding window to realize flow control
Detailed explanation of specific methods and steps for TCP communication between s7-1500 PLCs (picture and text)
传输层 使用滑动窗口实现流量控制
Warmup预热学习率「建议收藏」
Filebeat自定义index和fields
杰理之检测灵敏度级别确定【篇】
Why must a digital transformation strategy include continuous testing?
originpro 2021 附安装教程
昨晚 Spark Summit 重要功能发布全在这里(附超清视频)
【ICLR 2021】半监督目标检测:Unbiased Teacher For Semi-Supervised Object Detection
Build document editor based on slate
Kubevela 1.4: make application delivery safer, easier to use, and more transparent
WeakSet
Character class of regular series
CADD课程学习(1)-- 药物设计基础知识
WeakSet
Data intelligence - dtcc2022! China database technology conference is about to open
qt中toLocal8Bit和toUtf8()有什么区别
DNS服务器搭建、转发、主从配置









