From eca08119377ce38232581d444f48e28e0d02692b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 10 Jul 2018 20:08:17 +0200 Subject: Linked all used Dalvik strings with their origin. --- plugins/dalvik/link.c | 65 +++++++++++++++ plugins/dalvik/link.h | 4 + plugins/dalvik/v35/opdefs/const_1a.d | 6 ++ plugins/dalvik/v35/opdefs/const_1b.d | 6 ++ plugins/dex/dex-int.c | 6 +- plugins/dex/dex-int.h | 3 +- plugins/dex/format.c | 3 + plugins/dex/pool.c | 148 ++++++++++++++++++++++++++++------- plugins/dex/pool.h | 7 +- plugins/readdex/ids.c | 14 +--- 10 files changed, 216 insertions(+), 46 deletions(-) diff --git a/plugins/dalvik/link.c b/plugins/dalvik/link.c index aaed263..c37abb8 100644 --- a/plugins/dalvik/link.c +++ b/plugins/dalvik/link.c @@ -34,8 +34,10 @@ #include #include #include +#include +#include "operands/pool.h" #include "pseudo/switch.h" @@ -63,6 +65,69 @@ typedef struct _case_comment #define COMMENT_LINE_SEP "\n" + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* * +* Description : Etablit une référence entre utilisation et origine de chaîne.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void handle_links_for_dalvik_string(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GExeFormat *format) +{ + GArchOperand *op; /* Opérande numérique en place */ + uint32_t index; /* Indice dans la table Dex */ + GBinSymbol *string; /* Emplacement de la chaîne */ + const mrange_t *range; /* Zone d'occupation */ + GArchInstruction *target; /* Ligne visée par la référence*/ + + g_arch_instruction_lock_operands(instr); + + assert(_g_arch_instruction_count_operands(instr) == 2); + + op = _g_arch_instruction_get_operand(instr, 1); + + g_arch_instruction_unlock_operands(instr); + + assert(G_IS_DALVIK_POOL_OPERAND(op)); + + assert(g_dalvik_pool_operand_get_pool_type(G_DALVIK_POOL_OPERAND(op)) == DPT_STRING); + + index = g_dalvik_pool_operand_get_index(G_DALVIK_POOL_OPERAND(op)); + + string = get_string_symbol_from_dex_pool(G_DEX_FORMAT(format), index); + + if (string != NULL) + { + range = g_binary_symbol_get_range(string); + + target = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); + + if (target != NULL) + { + g_arch_instruction_link_with(instr, target, ILT_REF); + + g_object_unref(G_OBJECT(target)); + + } + + g_object_unref(G_OBJECT(string)); + + } + + g_object_unref(G_OBJECT(op)); + +} + + /****************************************************************************** * * * Paramètres : instr = instruction ARMv7 à traiter. * diff --git a/plugins/dalvik/link.h b/plugins/dalvik/link.h index 38dfd46..3b4a91f 100644 --- a/plugins/dalvik/link.h +++ b/plugins/dalvik/link.h @@ -29,6 +29,10 @@ +/* Etablit une référence entre utilisation et origine de chaîne. */ +void handle_links_for_dalvik_string(GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); + + static inline void handle_dalvik_if_branch_as_link(GArchInstruction *ins, GArchProcessor *proc, GProcContext *ctx, GExeFormat *fmt) { handle_branch_as_link(ins, proc, ctx, fmt, 2); diff --git a/plugins/dalvik/v35/opdefs/const_1a.d b/plugins/dalvik/v35/opdefs/const_1a.d index 54101cd..ff01dbc 100644 --- a/plugins/dalvik/v35/opdefs/const_1a.d +++ b/plugins/dalvik/v35/opdefs/const_1a.d @@ -35,4 +35,10 @@ @format 21c | pool_string + @hooks { + + link = handle_links_for_dalvik_string + + } + } diff --git a/plugins/dalvik/v35/opdefs/const_1b.d b/plugins/dalvik/v35/opdefs/const_1b.d index 0aef637..9153206 100644 --- a/plugins/dalvik/v35/opdefs/const_1b.d +++ b/plugins/dalvik/v35/opdefs/const_1b.d @@ -35,4 +35,10 @@ @format 31c | pool_string + @hooks { + + link = handle_links_for_dalvik_string + + } + } diff --git a/plugins/dex/dex-int.c b/plugins/dex/dex-int.c index e3121b6..287ec7a 100644 --- a/plugins/dex/dex-int.c +++ b/plugins/dex/dex-int.c @@ -145,6 +145,7 @@ bool read_dex_string_id_item(const GDexFormat *format, vmpa2t *pos, string_id_it * * * Paramètres : format = informations chargées à consulter. * * pos = position de début de lecture. [OUT] * +* inter = position intermédiaire à conserver. [OUT] * * str_data = structure lue à retourner. [OUT] * * * * Description : Procède à la lecture de proriétés de chaîne DEX. * @@ -155,7 +156,7 @@ bool read_dex_string_id_item(const GDexFormat *format, vmpa2t *pos, string_id_it * * ******************************************************************************/ -bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *pos, string_data_item *str_data) +bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *pos, vmpa2t *inter, string_data_item *str_data) { bool result; /* Bilan à retourner */ GBinContent *content; /* Contenu binaire à lire */ @@ -166,6 +167,9 @@ bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *pos, string_dat if (result) { + if (inter != NULL) + copy_vmpa(inter, pos); + str_data->data = g_binary_content_get_raw_access(content, pos, str_data->utf16_size); result = (str_data->data != NULL); } diff --git a/plugins/dex/dex-int.h b/plugins/dex/dex-int.h index 4016b1c..5180b58 100644 --- a/plugins/dex/dex-int.h +++ b/plugins/dex/dex-int.h @@ -41,6 +41,7 @@ struct _GDexFormat dex_header header; /* En-tête du programme */ + GBinSymbol **strings; /* Symboles pour les chaînes */ GDataType **types; /* Types partagés pour Dalvik */ GBinVariable **fields; /* Champs de données partagés */ GDexClass **classes; /* Classes retrouvées */ @@ -80,7 +81,7 @@ bool read_dex_header(const GDexFormat *, vmpa2t *, dex_header *); bool read_dex_string_id_item(const GDexFormat *, vmpa2t *, string_id_item *); /* Procède à la lecture de proriétés de chaîne DEX. */ -bool read_dex_string_data_item(const GDexFormat *, vmpa2t *, string_data_item *); +bool read_dex_string_data_item(const GDexFormat *, vmpa2t *, vmpa2t *, string_data_item *); /* Procède à la lecture d'un identifiant de type DEX. */ bool read_dex_type_id_item(const GDexFormat *, vmpa2t *, type_id_item *); diff --git a/plugins/dex/format.c b/plugins/dex/format.c index f185cc3..b69cc76 100644 --- a/plugins/dex/format.c +++ b/plugins/dex/format.c @@ -396,6 +396,9 @@ static bool g_dex_format_analyze(GDexFormat *format, wgroup_id_t gid, GtkStatusS /* TODO : vérifier que les *_id ne se chevauchent pas */ + if (!load_all_dex_string_symbols(format, gid, status)) + goto gdfa_error; + if (!load_all_dex_types(format, gid, status)) goto gdfa_error; diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c index 8c740bc..8a421b2 100644 --- a/plugins/dex/pool.c +++ b/plugins/dex/pool.c @@ -41,9 +41,11 @@ /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à analyser. * +* Paramètres : format = description de l'exécutable à compléter. * +* gid = groupe de travail impliqué. * + status = barre de statut à tenir informée. * * * -* Description : Charge en mémoire toutes les chaînes trouvées. * +* Description : Charge en mémoire l'ensemble des chaînes du format DEX. * * * * Retour : Bilan de l'opération. * * * @@ -51,38 +53,58 @@ * * ******************************************************************************/ -bool find_all_dex_strings(GDexFormat *format) +bool load_all_dex_string_symbols(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status) { - GBinFormat *base; /* Autre version du format */ + bool result; /* Bilan à retourner */ uint32_t count; /* Nombre d'éléments présents */ - uint32_t i; /* Boucle de parcours */ - mrange_t range; /* Couverture associée */ - const char *text; /* Texte issu du binaire */ - GBinSymbol *symbol; /* Nouveau symbole construit */ - char *label; /* Désignation de la chaîne */ + guint runs_count; /* Qté d'exécutions parallèles */ + uint32_t run_size; /* Volume réparti par exécution*/ + GWorkQueue *queue; /* Gestionnaire de différés */ + activity_id_t msg; /* Message de progression */ + guint i; /* Boucle de parcours */ + uint32_t begin; /* Début de bloc de traitement */ + uint32_t end; /* Fin d'un bloc de traitement */ + GDexLoading *loading; /* Tâche de chargement à lancer*/ - base = G_BIN_FORMAT(format); + result = true; + + /* Préparation du réceptacle */ count = count_strings_in_dex_pool(format); - for (i = 0; i < count; i++) - { - text = get_string_from_dex_pool(format, i, &range); - if (text == NULL) continue; + format->strings = (GBinSymbol **)calloc(count, sizeof(GBinSymbol *)); - symbol = g_binary_symbol_new(&range, STP_STRING); + /* Lancement des chargements */ - label = create_string_label(base, get_mrange_addr(&range), get_mrange_length(&range)); + runs_count = get_max_online_threads(); - g_binary_symbol_set_alt_label(symbol, label); + run_size = count / runs_count; - free(label); + queue = get_work_queue(); + + msg = gtk_status_stack_add_activity(status, _("Loading all strings from the Dex pool..."), count); + + for (i = 0; i < runs_count; i++) + { + begin = i * run_size; + + if ((i + 1) == runs_count) + end = count; + else + end = begin + run_size; + + loading = g_dex_loading_new(format, begin, end, msg, + (dex_loading_cb)get_string_symbol_from_dex_pool, &result); - g_binary_format_add_symbol(base, symbol); + g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid); } - return true; + g_work_queue_wait_for_completion(queue, gid); + + gtk_status_stack_remove_activity(status, msg); + + return result; } @@ -113,12 +135,12 @@ uint32_t count_strings_in_dex_pool(const GDexFormat *format) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * -* index = index du type recherchée. * +* index = index de la chaîne recherchée. * * range = éventuelle couverture à renseigner ou NULL. [OUT] * * * * Description : Extrait une chaîne de caractères d'une table DEX. * * * -* Retour : Chaîne de caractères trouvées ou NULL en cas d'erreur. * +* Retour : Chaîne de caractères trouvée ou NULL en cas d'erreur. * * * * Remarques : - * * * @@ -130,8 +152,8 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m off_t pos; /* Tête de lecture */ vmpa2t addr; /* Tête de lecture générique */ string_id_item str_id; /* Identifiant de chaîne */ + vmpa2t inter; /* Position intermédiaire */ string_data_item str_data; /* Description de chaîne */ - vmpa2t start; /* Début de la chaîne */ phys_t diff; /* Avancée de tête de lecture */ count = count_strings_in_dex_pool(format); @@ -148,15 +170,14 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m pos = str_id.string_data_off; init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_data_item(format, &addr, &str_data)) + if (!read_dex_string_data_item(format, &addr, &inter, &str_data)) return NULL; if (range != NULL) { - init_vmpa(&start, pos, VMPA_NO_VIRTUAL); - diff = compute_vmpa_diff(&start, &addr); + diff = compute_vmpa_diff(&inter, &addr); - init_mrange(range, &start, diff); + init_mrange(range, &inter, diff); } @@ -167,6 +188,75 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m /****************************************************************************** * * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la chaîne recherchée. * +* * +* Description : Extrait un symbole de chaîne d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *get_string_symbol_from_dex_pool(GDexFormat *format, uint32_t index) +{ + GBinSymbol *result; /* Instance à retourner */ + uint32_t count; /* Nombre d'éléments présents */ + mrange_t range; /* Emplacement de la chaîne */ + const char *string; /* Chaîne de caractères liée */ + GBinSymbol *new; /* Nouveau symbol créé */ + GBinFormat *base; /* Autre version du format */ + char *label; /* Désignation de la chaîne */ + bool inserted; /* Bilan d'une insertion */ + + result = NULL; + + count = count_strings_in_dex_pool(format); + + if (index >= count) + goto gssfdp_error; + + if (format->strings[index] == NULL) + { + string = get_string_from_dex_pool(format, index, &range); + if (string == NULL) goto gssfdp_error; + + new = g_binary_symbol_new(&range, STP_RO_STRING); + + base = G_BIN_FORMAT(format); + + label = create_string_label(base, get_mrange_addr(&range), get_mrange_length(&range)); + + g_binary_symbol_set_alt_label(new, label); + + free(label); + + g_object_ref(G_OBJECT(new)); + inserted = g_binary_format_add_symbol(base, new); + + if (inserted) + format->strings[index] = new; + + else + g_object_unref(G_OBJECT(new)); + + } + + result = format->strings[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + gssfdp_error: + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = description de l'exécutable à compléter. * * gid = groupe de travail impliqué. * status = barre de statut à tenir informée. * @@ -261,7 +351,7 @@ uint32_t count_types_in_dex_pool(const GDexFormat *format) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * -* index = index du type recherchée. * +* index = index du type recherché. * * * * Description : Extrait une représentation de type d'une table DEX. * * * @@ -305,7 +395,7 @@ GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) pos = str_id.string_data_off; init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_data_item(format, &addr, &str_data)) + if (!read_dex_string_data_item(format, &addr, NULL, &str_data)) goto gtfdp_error; format->types[index] = g_binary_format_decode_type(G_BIN_FORMAT(format), (char *)str_data.data); diff --git a/plugins/dex/pool.h b/plugins/dex/pool.h index ed5b447..ac7db60 100644 --- a/plugins/dex/pool.h +++ b/plugins/dex/pool.h @@ -35,8 +35,8 @@ -/* Charge en mémoire toutes les chaînes trouvées. */ -bool find_all_dex_strings(GDexFormat *); +/* Charge en mémoire l'ensemble des chaînes du format DEX. */ +bool load_all_dex_string_symbols(GDexFormat *, wgroup_id_t, GtkStatusStack *); /* Compte le nombre de chaînes de caractères dans une table DEX. */ uint32_t count_strings_in_dex_pool(const GDexFormat *); @@ -44,6 +44,9 @@ uint32_t count_strings_in_dex_pool(const GDexFormat *); /* Extrait une chaîne de caractères d'une table DEX. */ const char *get_string_from_dex_pool(const GDexFormat *, uint32_t, mrange_t *); +/* Extrait un symbole de chaîne d'une table DEX. */ +GBinSymbol *get_string_symbol_from_dex_pool(GDexFormat *, uint32_t); + /* Charge en mémoire l'ensemble des types du format DEX. */ bool load_all_dex_types(GDexFormat *, wgroup_id_t, GtkStatusStack *); diff --git a/plugins/readdex/ids.c b/plugins/readdex/ids.c index 82d17f4..702e071 100644 --- a/plugins/readdex/ids.c +++ b/plugins/readdex/ids.c @@ -253,9 +253,6 @@ bool annotate_dex_string_ids(const GDexFormat *format, GPreloadInfo *info, GtkSt vmpa2t item_pos; /* Position d'un élément */ uleb128_t length; /* Taille de la chaîne en cours*/ GArchInstruction *instr; /* Instruction décodée */ - bool inserted; /* Bilan d'une insertion */ - const mrange_t *range; /* Espace occupé par une chaîne*/ - GBinSymbol *symbol; /* Symbole à intégrer */ content = g_binary_format_get_content(G_BIN_FORMAT(format)); @@ -333,16 +330,7 @@ bool annotate_dex_string_ids(const GDexFormat *format, GPreloadInfo *info, GtkSt { g_raw_instruction_mark_as_string(G_RAW_INSTRUCTION(instr), true); - inserted = g_preload_info_add_instruction(info, instr); - - if (inserted) - { - range = g_arch_instruction_get_range(instr); - - symbol = g_binary_symbol_new(range, STP_RO_STRING); - g_binary_format_add_symbol(bformat, symbol); - - } + g_preload_info_add_instruction(info, instr); } -- cgit v0.11.2-87-g4458