授人与鱼不如授人与渔,作为初学者,最重要的是学会查看官方文档,自主学习。
首先放上google官方文档对dex解释的链接,里面相当详细的介绍了dex的格式的组成。
https://source.android.google.cn/devices/tech/dalvik/dex-format#header-item
上一篇文章解析了type_ids,今天来解析dex中的proto_id_item、field_id_item、method_id_item,为什么这三个放在一起呢?因为有了前面的基础,这三个就没有一点难度了,老规矩,先来看官方文档的介绍。
proto_id_item
shorty_idx uint 此原型的简短式描述符字符串的 string_ids 列表中的索引。该字符串必须符合上文定义的 ShortyDescriptor 的语法,而且必须与该项的返回类型和参数相对应。
return_type_idx uint 此原型的返回类型的 type_ids 列表中的索引
parameters_off uint 从文件开头到此原型的参数类型列表的偏移量;如果此原型没有参数,则该值为 0。该偏移量(如果为非零值)应该位于 data 区段,且其中的数据应采用下文中“"type_list"”指定的格式。此外,不得对列表中的类型 void 进行任何引用。
定义结构体
typedef struct _IMAGE_PROTO_ID_ITEM
{
DWORD shorty_idx;
DWORD return_type_idx;
DWORD parameters_off;
}IMAGE_PROTO_ID_ITEM, * PIMAGE_PROTO_ID_ITEM;
field_id_item
class_idx ushort 此字段的定义符的 type_ids 列表中的索引。此项必须是“类”类型,而不能是“数组”或“基元”类型。
type_idx ushort 此字段的类型的 type_ids 列表中的索引
name_idx uint 此字段的名称的 string_ids 列表中的索引。该字符串必须符合上文定义的 MemberName 的语法。
定义结构体
typedef struct _IMAGE_FIELD_ID_ITEM
{
WORD class_idx;
WORD type_idx;
DWORD name_idx;
}IMAGE_FIELD_ID_ITEM, * PIMAGE_FIELD_ID_ITEM;
method_id_item
class_idx ushort 此方法的定义符的 type_ids 列表中的索引。此项必须是“类”或“数组”类型,而不能是“基元”类型。
proto_idx ushort 此方法的原型的 proto_ids 列表中的索引
name_idx uint 此方法的名称的 string_ids 列表中的索引。该字符串必须符合上文定义的 MemberName 的语法。
定义结构体
typedef struct _IMAGE_METHOD_ID_ITEM
{
WORD class_idx;
WORD proto_idx;
DWORD name_idx;
}IMAGE_METHOD_ID_ITEM, * PIMAGE_METHOD_ID_ITEM;
浅析:
看到上面的type_ids索引、string_ids索引有没有觉得很眼熟?没错,就是前几天的解析函数,只需要把参数和索引传进去,就可以成功的获取到字符串了。同时,这两个列表也要写成函数的形式,因为解析class_ids的时候要用到。
virtualAddress_proto解析函数
//其他参数不在解释了,这里只解释一下char**,二级指针用于接收合成的新字符串
void getString(PIMAGE_DEX_HEADER IpParameter, PDWORD virtualAddress_string, PIMAGE_TYPE_ITEM virtualAddress_type, PIMAGE_PROTO_ID_ITEM virtualAddress_proto, char** m_str, DWORD index)
{
char* str_id = getString(IpParameter, virtualAddress_string, (virtualAddress_proto + index)->shorty_idx);
char* str_id2 = getString(IpParameter, virtualAddress_string, virtualAddress_type, (virtualAddress_proto + index)->return_type_idx);
//这里要判断一下参数是否为0
if ((virtualAddress_proto + index)->parameters_off)
{
PIMAGE_TYPE_LIST type_list = (PIMAGE_TYPE_LIST)((DWORD)IpParameter + (virtualAddress_proto + index)->parameters_off);
PWORD list = &(type_list->list);
LPSTR* str_list = (LPSTR*)malloc(sizeof(int) * type_list->size);
memset(str_list, 0, sizeof(int) * type_list->size);
DWORD index = 0;
if (str_list)
{
for (size_t j = 0; j < type_list->size; j++)
{
str_list[j] = getString(IpParameter, virtualAddress_string, virtualAddress_type, *(list + j));
index += strlen(str_list[j]);
}
}
char* str = (char*)malloc(strlen(str_id) + strlen(str_id2) + index + 61);
sprintf(str, "\t%s \t", str_id2);
for (size_t i = 0; i < type_list->size; i++)
{
strcat(str, str_list[i]);
}
if (str_list)
{
free(str_list);
}
strcat(str, "\t");
*m_str = str;
return;
}
char* str = (char*)malloc(strlen(str_id) + strlen(str_id2) + 61);
memset(str, 0, strlen(str_id) + strlen(str_id2) + 61);
if (str)
{
sprintf(str, "\t%s \t ", str_id2);
*m_str = str;
return;
}
return;
}
field_id_item
void getString(PIMAGE_DEX_HEADER IpParameter, PDWORD virtualAddress_string, PIMAGE_TYPE_ITEM virtualAddress, PIMAGE_FIELD_ID_ITEM virtualAddress_field, char** m_str, DWORD index)
{
char* str_id3 = getString(IpParameter, virtualAddress_string, (virtualAddress_field + index)->name_idx);
char* str_id1 = getString(IpParameter, virtualAddress_string, virtualAddress, (virtualAddress_field+index)->class_idx);
char* str_id2 = getString(IpParameter, virtualAddress_string, virtualAddress, (virtualAddress_field + index)->type_idx);
char* str = (char*)malloc(strlen(str_id3) + strlen(str_id1) + strlen(str_id2) + 41);
if (str)
{
sprintf(str, "字段定义\t%s\t 字段类型\t%s \t列表的名称\t%s \n", str_id1, str_id2,str_id3);
*m_str = str;
return;
}
return;
}
method_id_item
getString(IpParameter, virtualAddress_string, virtualAddress, virtualAddress_proto, &str_id2, str_id3, strlen(str_id3), (virtualAddress_method + index)->proto_idx);
char* str_id1 = getString(IpParameter, virtualAddress_string, virtualAddress, (virtualAddress_method + index)->class_idx);
if (!str_id2)
{
return;
}
char* str = (char*)malloc(strlen(str_id3) + strlen(str_id1) + strlen(str_id2) + 41);
if (str)
{
sprintf(str, "方法的定义\t%s\t 方法名称\t%s \t方法原型\t%s ", str_id1, str_id3, str_id2);
*m_str = str;
free(str_id2);
return;
}
return;
}
由于代码过于简单,之前都介绍过了,就不在详细介绍了。