/* Chrysalide - Outil d'analyse de fichiers binaires * ids.c - annotation des références aux chaînes de caractères et identifiants * * Copyright (C) 2016-2018 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Chrysalide is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Chrysalide. If not, see . */ #include "ids.h" #include #include #include #include #include #include #include #include /* Définition des champs */ /* Récupère la taille d'une chaîne de caractères. */ static bool get_dex_string_length_value(const fmt_field_def *, GBinContent *, vmpa2t *, SourceEndian, uleb128_t *); static fmt_field_def _dex_string_ids_length[] = { { .name = "length", .get_value = (get_fdef_value_cb)get_dex_string_length_value, .is_uleb128 = true, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("String length")) } }; static fmt_field_def _dex_type_ids[] = { { .name = "descriptor_idx", .size = MDS_32_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the descriptor string of this type")) } }; static fmt_field_def _dex_proto_ids[] = { { .name = "shorty_idx", .size = MDS_32_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the short-form descriptor string of this prototype")) }, { .name = "return_type_idx", .size = MDS_32_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the return type of this prototype")) }, { .name = "parameters_off", .size = MDS_32_BITS, .repeat = 1, PLAIN_COMMENT(__("Offset to the list of parameter types for this prototype")) } }; static fmt_field_def _dex_field_ids[] = { { .name = "class_idx", .size = MDS_16_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the definer of this field")) }, { .name = "type_idx", .size = MDS_16_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the type of this field")) }, { .name = "name_idx", .size = MDS_32_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the name of this field")) } }; static fmt_field_def _dex_method_ids[] = { { .name = "class_idx", .size = MDS_16_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the definer of this field")) }, { .name = "proto_idx", .size = MDS_16_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the prototype of this method")) }, { .name = "name_idx", .size = MDS_32_BITS, .repeat = 1, DISPLAY_RULES(IOD_DEC), PLAIN_COMMENT(__("Index for the name of this method")) } }; /****************************************************************************** * * * Paramètres : def = définition à l'origine de l'appel. * * content = contenu binaire à venir lire. * * pos = position de la tête de lecture. * * endian = ordre des bits dans la source. * * data = lieu d'enregistrement de la lecture. [OUT] * * * * Description : Récupère la taille d'une chaîne de caractères. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static bool get_dex_string_length_value(const fmt_field_def *def, GBinContent *content, vmpa2t *pos, SourceEndian endian, uleb128_t *length) { bool result; /* Bilan à retourner */ result = g_binary_content_read_uleb128(content, pos, length); return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * info = informations à constituer en avance de phase. * * status = barre de statut à tenir informée. * * * * Description : Commente les définitions des chaînes de caractères. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_string_ids(const GDexFormat *format, GPreloadInfo *info, GtkStatusStack *status) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ const dex_header *header; /* En-tête principale */ SourceEndian endian; /* Boutisme utilisé */ vmpa2t pos; /* Tête de lecture des symboles*/ activity_id_t msg; /* Message de progression */ GBinFormat *bformat; /* Autre version du format */ uint32_t i; /* Boucle de parcours */ fmt_field_def field; /* Définition de position */ comment_part parts[2]; /* Mise en place des parties */ phys_t loc; /* Localisation physique */ vmpa2t item_pos; /* Position d'un élément */ uleb128_t length; /* Taille de la chaîne en cours*/ GArchInstruction *instr; /* Instruction décodée */ content = g_known_format_get_content(G_KNOWN_FORMAT(format)); header = g_dex_format_get_header(format); endian = g_binary_format_get_endianness(G_BIN_FORMAT(format)); result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), header->string_ids_off, &pos); if (!result) goto adsi_exit; msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Dex strings..."), header->string_ids_size); bformat = G_BIN_FORMAT(format); bool get_string_offset_value(const fmt_field_def *d, GBinContent *c, vmpa2t *p, SourceEndian e, phys_t *val) { bool status; /* Bilan à retourner */ uint32_t offset; /* Position trouvée */ status = g_binary_content_read_u32(c, p, e, &offset); if (status) *val = offset; return status; } for (i = 0; i < header->string_ids_size && result; i++) { /* Saut vers la définition */ memset(&field, 0, sizeof(field)); field.name = "p_flags"; field.get_value = (get_fdef_value_cb)get_string_offset_value; field.size = MDS_32_BITS; field.repeat = 1; parts[0].is_static = true; parts[0].avoid_i18n = false; parts[0].static_text = __("Offset for string item #"); parts[1].is_static = false; parts[1].avoid_i18n = true; asprintf(&parts[1].dynamic_text, "%u/%u", i, header->string_ids_size - 1); field.ctype = FCT_MULTI; field.comment.parts = parts; field.comment.pcount = ARRAY_SIZE(parts); result = parse_field_definitions(&field, 1, bformat, info, &pos, &loc); if (!result) break; /* Description de la chaîne : taille */ if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), loc, &item_pos)) continue; result = parse_field_definitions(PARSING_DEFS(_dex_string_ids_length), bformat, info, &item_pos, &length); /* Description de la chaîne : contenu */ if (result && length > 0) { instr = g_raw_instruction_new_array(content, MDS_8_BITS, length, &item_pos, endian); if (instr != NULL) { g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); g_preload_info_add_instruction(info, instr); } } gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); g_object_unref(G_OBJECT(content)); adsi_exit: return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * info = informations à constituer en avance de phase. * * status = barre de statut à tenir informée. * * * * Description : Commente les définitions des identifiants de types. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_type_ids(const GDexFormat *format, GPreloadInfo *info, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const dex_header *header; /* En-tête principale */ vmpa2t pos; /* Tête de lecture des symboles*/ activity_id_t msg; /* Message de progression */ GBinFormat *bformat; /* Autre version du format */ uint32_t i; /* Boucle de parcours */ header = g_dex_format_get_header(format); result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), header->type_ids_off, &pos); if (!result) goto adti_exit; msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Dex types..."), header->type_ids_size); bformat = G_BIN_FORMAT(format); for (i = 0; i < header->type_ids_size && result; i++) { result = parse_field_definitions(PARSING_DEFS(_dex_type_ids), bformat, info, &pos, NULL); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); adti_exit: return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * info = informations à constituer en avance de phase. * * status = barre de statut à tenir informée. * * * * Description : Commente les définitions des identifiants de prototypes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_proto_ids(const GDexFormat *format, GPreloadInfo *info, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const dex_header *header; /* En-tête principale */ vmpa2t pos; /* Tête de lecture des symboles*/ activity_id_t msg; /* Message de progression */ GBinFormat *bformat; /* Autre version du format */ uint32_t i; /* Boucle de parcours */ header = g_dex_format_get_header(format); result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), header->proto_ids_off, &pos); if (!result) goto adpi_exit; msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Dex prototypes..."), header->proto_ids_size); bformat = G_BIN_FORMAT(format); for (i = 0; i < header->proto_ids_size && result; i++) { result = parse_field_definitions(PARSING_DEFS(_dex_proto_ids), bformat, info, &pos, NULL); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); adpi_exit: return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * info = informations à constituer en avance de phase. * * status = barre de statut à tenir informée. * * * * Description : Commente les définitions des identifiants de champs. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_field_ids(const GDexFormat *format, GPreloadInfo *info, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const dex_header *header; /* En-tête principale */ vmpa2t pos; /* Tête de lecture des symboles*/ activity_id_t msg; /* Message de progression */ GBinFormat *bformat; /* Autre version du format */ uint32_t i; /* Boucle de parcours */ header = g_dex_format_get_header(format); result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), header->field_ids_off, &pos); if (!result) goto adfi_exit; msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Dex fields..."), header->field_ids_size); bformat = G_BIN_FORMAT(format); for (i = 0; i < header->field_ids_size && result; i++) { result = parse_field_definitions(PARSING_DEFS(_dex_field_ids), bformat, info, &pos, NULL); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); adfi_exit: return result; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * * info = informations à constituer en avance de phase. * * status = barre de statut à tenir informée. * * * * Description : Commente les définitions des identifiants de méthodes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool annotate_dex_method_ids(const GDexFormat *format, GPreloadInfo *info, GtkStatusStack *status) { bool result; /* Bilan à retourner */ const dex_header *header; /* En-tête principale */ vmpa2t pos; /* Tête de lecture des symboles*/ activity_id_t msg; /* Message de progression */ GBinFormat *bformat; /* Autre version du format */ uint32_t i; /* Boucle de parcours */ header = g_dex_format_get_header(format); result = g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), header->method_ids_off, &pos); if (!result) goto admi_exit; msg = gtk_status_stack_add_activity(status, _("Writing annotations for all Dex methods..."), header->method_ids_size); bformat = G_BIN_FORMAT(format); for (i = 0; i < header->method_ids_size && result; i++) { result = parse_field_definitions(PARSING_DEFS(_dex_method_ids), bformat, info, &pos, NULL); gtk_status_stack_update_activity_value(status, msg, 1); } gtk_status_stack_remove_activity(status, msg); admi_exit: return result; }