20210408-学习随笔
DEX文件结构
dex文件整体结构
结构名称 | 解释 |
---|---|
dex header |
dex文件头部,记录整个dex文件的相关属性 |
string_ids |
字符串数据索引,记录了每个字符串的偏移量 |
type_ids |
数据类型数组,记录了每个类型在string_ids 数组中的的字符串索引 |
proto_ids |
方法声明的偏移量,记录了方法声明的字符串,返回类型字符串,参数列表 |
field_ids |
字段数据索引,记录了所属类,类型以及方法名 |
method_ids |
类方法索引,记录方法所属类名,方法声明以及方法名等信息 |
class_defs |
类定义数据索引,记录指定类各类信息,包括接口,超类,类数据偏移量 |
data |
数据区,保存了各个类的真实数据 |
link_data |
静态链接数据区 |
dex header
struct DexHeader {
u1 magic[8]; /* 版本标识 */
u4 checksum; /* adler32 检验 */
u1 signature[kSHA1DigestLen]; /* SHA-1 哈希值 */
u4 fileSize; /* 整个文件大小 */
u4 headerSize; /* DexHeader 大小 */
u4 endianTag; /* 字节序标记 */
u4 linkSize; /* 链接段大小 */
u4 linkOff; /* 链接段偏移 */
u4 mapOff; /* DexMapList 的文件偏移 */
u4 stringIdsSize; /* DexStringId 的个数 */
u4 stringIdsOff; /* DexStringId 的文件偏移 */
u4 typeIdsSize; /* DexTypeId 的个数 */
u4 typeIdsOff; /* DexTypeId 的文件偏移 */
u4 protoIdsSize; /* DexProtoId 的个数 */
u4 protoIdsOff; /* DexProtoId 的文件偏移 */
u4 fieldIdsSize; /* DexFieldId 的个数 */
u4 fieldIdsOff; /* DexFieldId 的文件偏移 */
u4 methodIdsSize; /* DexMethodId 的个数 */
u4 methodIdsOff; /* DexMethodId 的文件偏移 */
u4 classDefsSize; /* DexClassDef 的个数 */
u4 classDefsOff; /* DexClassDef 的文件偏移 */
u4 dataSize; /* 数据段的大小 */
u4 dataOff; /* 数据段的文件偏移 */
};
-
magic
:dex.035
-
checksum
:dex文件的校验和,用来判断dex文件是否损坏或被篡改 -
signature
: SHA校验 -
fileSize
:整个dex文件的大小(byte) -
headerSize
: 记录了Header占用的字节数 -
endianTag
:指定CPU字节序,默认为ENDIAN_CONSTANT
0x12345678
(小端序) -
mapOff
: 指定了map_list
结构的文件便宜 -
stringIdsSize
:string_ids
结构的字节数 -
stringIdsOff
:string_ids
结构的文件偏移 - 其余同...
string_ids
存放字符串所在位置的偏移
其中字符串第一个字节保存着字符串的长度,之后是一个char数组,以00
结尾
type_ids
是用到的类型数组,每个元素为用到的类型(类),存放的数据为在string_ids
数组中的索引
proto_ids
方法原型声明的数组
struct DexProtoId {
u4 shortyIdx; // 返回类型 string_ids 的索引
u4 returnTypeIdx; // 返回类型 type_ids 的索引
u4 parametersOff; /* 指向参数类型列表的文件偏移量
没有参数则为0 非0则指向的数据应满足type_item格式*/
}
field_ids
struct filed_id_item{
ushort class_idx; // 字段所属的class type_ids的索引
ushort type_idx; // 字段的类型 type_ids的索引
uint name_idx; // 字段的名称 string_ids的索引
}
method_ids
struct method_id_item{
ushort class_idx; // 方法所属的class type_ids的索引
ushort proto_idx; // 方法的原型 proto_ids的索引
uint name_idx; // 方法的名称 string_ids的索引
}
class_defs
struct class_def_item {
uint class_idx; // 类的类型,type_ids的索引
uint access_flags; // 访问标志
uint superclass_idx; // 父类类型 type_ids的索引
uint interfaces_off; // 接口 之想type_list的偏移,没有为0
uint source_file_idx; // 源文件名 string_ids的索引
uint annotations_off; // 注解
uint class_data_off; // 指向 class_data结构的文件偏移
uint static_value_off; //
}
struct class_data_item{
uleb128 static_fields_size; //静态字段
uleb128 instance_fields_size; //实例字段
uleb128 direct_methods_size; //直接方法(private或者构造方法)
uleb128 virtual_methods_size; //虚方法(非private、static、final,非构造方法)
encoded_field static_fields[static_fields_size]; //静态字段
encoded_field instance_fields[instance_fields_size]; //实例字段
encoded_method direct_methods[direct_method_size]; //直接方法
encoded_method virtual_methods[virtual_methods_size]; //虚方法
}
struct encoded_field{
uleb128 filed_idx_diff;
uleb128 access_flags;
}
struct encoded_method{
uleb128 method_idx_diff; // method_ids的索引
uleb128 access_flags; // 访问权限
uleb128 code_off; // 本方法的代码实现,指向data区
}
map_list
// map_list 结构
struct DexMapList {
u4 size; // DexMapItem结构的个数
DexMapItem list[l]; // DexMapItem结构
}
size表明 DexMapItem结构的个数
struct DexMapItem {
u2 type; // 整体结构中的结构类型
u2 unused; // 用于字节对齐
u4 size; // 类型的个数
u4 offset; // 类型数据的文件偏移
}
Q&A
安装APK报错Failure [INSTALL_FAILED_TEST_ONLY]
安装APK报错Failure [INSTALL_FAILED_TEST_ONLY]
安装失败!调用者不被允许测试的测试程序
修改AndroidManifest.xml
application
标签中删去 android:testOnly="true"
属性
AndroidStudio使用smaliidea
安装smaliidea插件后
然后在Android Studio -> Preference(windows是File -> setting) -> Editor -> file Types 里面找smali,给图标为【黑色S】的smali添加.smali
,去掉自带的smali的.smali