当前位置:网站首页>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
边栏推荐
- Convert seconds to * * hours * * minutes
- 分析超700万个研发需求发现,这八大编程语言才是行业最需要的
- PM这样汇报工作,老板心甘情愿给你加薪
- exness:美GDP终值意外加速萎缩1.6%
- Torchdrug -- drug attribute prediction
- [try to hack] windows system account security
- 新出生的机器狗,打滚1小时后自己掌握走路,吴恩达开山大弟子最新成果
- matlab 将三角剖分结果保存为STL文件
- Is it safe to open an account in Guangzhou stock exchange by mobile phone?
- Data intelligence - dtcc2022! China database technology conference is about to open
猜你喜欢

如何快速通过PMP考试?

【1175. 质数排列】

小学期,第三场-下午:WEB_sessionlfi

杰理之触摸按键识别流程【篇】

Jenkins打包拉取不到最新的jar包

Taihu Lake "China's healthy agricultural products · mobile phone live broadcast" enters Taihu Lake
![Network planning | [five transport layers and six application layers] knowledge points and examples](/img/4f/31acce51b584bed5ef56b2093c4db3.png)
Network planning | [five transport layers and six application layers] knowledge points and examples

太湖 “中国健康农产品·手机直播万里行”走进太湖

CADD course learning (1) -- basic knowledge of drug design

What is the difference between tolocal8bit and toutf8() in QT
随机推荐
Go language learning tutorial (13)
Qt:qaxobject operation Excel
如何做好测试用例设计
GeoServer安装
QQmlApplicationEngine failed to load component qrc:/main.qml:-1 No such file or directory
一文读懂目标检测:R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD「建议收藏」
Audio and video architecture construction in the super video era | science and Intel jointly launched the second season of "architect growth plan"
DNS服务器搭建、转发、主从配置
composer
如何使用robots.txt及其详解
文件包含&条件竞争
项目经理是领导吗?可以批评指责成员吗?
PostgreSQL heap堆表 存储引擎实现原理
Tensorflow2.4实现RepVGG
25: Chapter 3: developing pass service: 8: [registration / login] interface: receiving and verifying "mobile number and verification code" parameters; (it is important to know the application scenario
十分之坑,tar命令解压文件的时候竟然不能解析英文括号“()”
Exness: the final value of US GDP unexpectedly accelerated to shrink by 1.6%
小学期,第三场-下午:WEB_xxe
神经网络入门(上)
GeoServer installation