当前位置:网站首页>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
边栏推荐
- Basic syntax of VB
- Warmup预热学习率「建议收藏」
- CADD课程学习(1)-- 药物设计基础知识
- “更福特、更中国”拨云见日,长安福特王牌产品订单过万
- 杰理之检测灵敏度级别确定【篇】
- Taiwan SSS Xinchuang sss1700 replaces cmedia cm6533 24bit 96KHz USB audio codec chip
- 解决arm_release_ver of this libmali is ‘g2p0-01eac0‘,rk_so_ver is ‘4‘,libgl1-mesa-dev不会被安装,存在未满足的依赖关系
- 开会,OneMeeting,OK!
- SM2246EN+闪迪15131
- Meeting, onemeeting, OK!
猜你喜欢

MySQL master-slave synchronization
MySQL数据库误删回滚的解决

消灭Bug,开发者不可不知的几款Bug探索测试神器。
Django上传excel表格并将数据写入数据库的详细步骤

【论文阅读】Trajectory-guided Control Prediction for End-to-end Autonomous Driving: A Simple yet Strong Baseline

Spark - 一文搞懂 Partitioner

MySQL billing Statistics (Part 1): MySQL installation and client dbeaver connection

1. 爬虫之Beautifulsoup解析库&在线解析图片验证码

8 - 函数

数据智能——DTCC2022!中国数据库技术大会即将开幕
随机推荐
MySQL master-slave synchronization
【ICLR 2021】半监督目标检测:Unbiased Teacher For Semi-Supervised Object Detection
QT QStringList用法
c语言数组截取,C# 字符串按数组截取方法(C/S)
1. 爬虫之Beautifulsoup解析库&在线解析图片验证码
SecureCRTPortable的安装和使用(图文详解)
Heartbeat 与DRBD 配置过程
25:第三章:开发通行证服务:8:【注册/登录】接口:接收并校验“手机号和验证码”参数;(重点需要知道【利用redis来暂存数据,获取数据的】的应用场景)(使用到了【@Valid注解】参数校验)
Django上传excel表格并将数据写入数据库的详细步骤
yolo 目标检测
Web主机iptables防火墙安全脚本
neo4j load csv 配置和使用
This morning, investors began to travel collectively
【LeetCode】【SQL】刷题笔记
黑苹果 服务器系统安装教程,黑苹果安装教程,详细教您黑苹果怎么安装[通俗易懂]
Cv+deep learning network architecture pytoch recurrence series basenets (backbones) (I)
The prospectus of pelt medical was "invalid" for the second time in the Hong Kong stock exchange, and the listing plan was substantially delayed
SM2246EN+闪迪15131
VB的基本语法
WeakSet