diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/androhelpers/try_n_catch.c | 297 |
1 files changed, 191 insertions, 106 deletions
diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c index fc7b2bb..7db0f70 100644 --- a/plugins/androhelpers/try_n_catch.c +++ b/plugins/androhelpers/try_n_catch.c @@ -25,6 +25,7 @@ #include <malloc.h> +#include <stdio.h> #include <format/dex/dex-int.h> @@ -36,6 +37,7 @@ /* Mémorisation d'un lien vers un gestionnaire */ typedef struct _caught_exception { + vmpa_t addr; /* Adresse du code de gestion */ GArchInstruction *instr; /* Première instruction visée */ char *desc; /* Nom de l'exception */ @@ -46,14 +48,17 @@ typedef struct _caught_exception /* Valide la zone couverte par le gestionnaire d'exceptions. */ static bool check_covered_area(const try_item *, const GBinRoutine *); -/* Construit une liste pointant sur les différentes gestions. */ -static caught_exception *build_destinations_list(GLoadedBinary *, const try_item *, const encoded_catch_handler_list *, const GBinRoutine *, size_t *); - /* Rattache les gestionnaires d'exception à leur code couvert. */ -static void attach_caught_code(GLoadedBinary *, const try_item *, const encoded_catch_handler_list *, const GBinRoutine *); +static void attach_caught_code(const GLoadedBinary *, const GBinRoutine *, const try_item *, const caught_exception *, size_t); + +/* Insère des indications dans le texte humainement lisible. */ +static void mark_exception_handlers(const GLoadedBinary *, uleb128_t, caught_exception **, size_t *); + +/* Construit des listes pointant sur les différentes gestions. */ +static caught_exception **build_all_destinations_list(const GLoadedBinary *, const GBinRoutine *, const encoded_catch_handler_list *, size_t **); /* Recherche et met en avant tous les gestionnaires d'exception. */ -static void look_for_exception_handlers(GLoadedBinary *, const GDexFormat *, GDexMethod *); +static void look_for_exception_handlers(const GLoadedBinary *, const GDexFormat *, GDexMethod *); @@ -88,169 +93,210 @@ static bool check_covered_area(const try_item *try, const GBinRoutine *routine) /****************************************************************************** * * -* Paramètres : binary = représentation binaire à traiter. * -* try = informations sur la gestion à consulter. * -* hlist = liste de tous les gestionnaires en place. * -* routine = routine associée, pour l'accès au instructions. * -* count = quantité de destinations trouvées. [OUT] * +* Paramètres : binary = représentation binaire à traiter. * +* routine = routine associée, pour l'accès au instructions. * +* try = informations sur la gestion à consulter. * +* handlers = arrivées des liens vers les gestionnaires. * +* count = nombre de ces arrivées. * * * -* Description : Construit une liste pointant sur les différentes gestions. * +* Description : Rattache les gestionnaires d'exception à leur code couvert. * * * -* Retour : Adresse des codes à lier systématiquement. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static caught_exception *build_destinations_list(GLoadedBinary *binary, const try_item *try, const encoded_catch_handler_list *hlist, const GBinRoutine *routine, size_t *count) +static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *routine, const try_item *try, const caught_exception *handlers, size_t count) { - caught_exception *result; /* Liste à retourner */ - GDexFormat *format; /* Format du binaire chargé */ - vmpa_t start; /* Début du code de la routine */ + vmpa_t start; /* Début de la zone couverte */ + vmpa_t end; /* Début de la zone couverte */ GArchInstruction *instrs; /* Instructions Dalvik */ - uleb128_t index; /* Indice du bon gestionnaire */ - encoded_catch_handler *handlers; /* Groupe de gestionnaires */ - leb128_t max; /* Quantité d'exception */ - leb128_t i; /* Boucle de parcours */ - vmpa_t handler_addr; /* Adresse du code de gestion */ - GDataType *type; /* Type de l'exception */ - - format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); + GArchInstruction *first; /* Première instruction */ + GArchInstruction *next; /* Dernière instruction + 1 */ + GArchInstruction *prev; /* Instruction à détacher */ + GArchInstruction *iter; /* Boucle de parcours */ + size_t i; /* Boucle de parcours */ start = g_binary_routine_get_address(routine); + start += try->start_addr * sizeof(uint16_t); + + end = start + try->insn_count * sizeof(uint16_t); instrs = g_loaded_binary_get_instructions(binary); - instrs = g_arch_instruction_find_by_address(instrs, start, true); + first = g_arch_instruction_find_by_address(instrs, start, true); + next = g_arch_instruction_find_by_address(instrs, end, true); - for (index = 0; index < hlist->size; index++) - if (try->handler_off == hlist->list[index].offset) - break; + /* Si des détachements sont nécessaires... */ - if (index == hlist->size) + if (!g_arch_instruction_has_sources(first)) { - *count = 0; - return NULL; + prev = g_arch_instruction_get_prev_iter(instrs, first); + g_arch_instruction_link_with(prev, first, ILT_EXEC_FLOW); } - handlers = &hlist->list[index]; - max = leb128_abs(handlers->size); - - *count = max + (handlers->size < 0 ? 1 : 0); - result = (caught_exception *)calloc(*count, sizeof(caught_exception)); + if (!g_arch_instruction_has_sources(next)) + { + prev = g_arch_instruction_get_prev_iter(instrs, next); + g_arch_instruction_link_with(prev, next, ILT_EXEC_FLOW); + } - *count = 0; + /* Rattachements ? */ - for (i = 0; i < max; i++) + if (handlers != NULL) { - handler_addr = start + handlers->handlers[i].addr * sizeof(uint16_t); - result[*count].instr = g_arch_instruction_find_by_address(instrs, handler_addr, true); - - if (result[*count].instr == NULL) - continue; + for (iter = first; + iter != NULL; + iter = g_arch_instruction_get_next_iter(instrs, iter, end)) + { + if (!g_arch_instruction_has_destinations(iter)) + continue; - type = get_type_from_dex_pool(format, handlers->handlers[i].type_idx); - result[*count].desc = g_data_type_to_string(type); + for (i = 0; i < count; i++) + g_arch_instruction_link_with(iter, handlers[i].instr, ILT_CATCH_EXCEPTION); - (*count)++; + } } - if (handlers->size < 0) - { - handler_addr = start + handlers->catch_all_addr * sizeof(uint16_t); - result[*count].instr = g_arch_instruction_find_by_address(instrs, handler_addr, true); +} - if (result[*count].instr != NULL) + +/****************************************************************************** +* * +* Paramètres : binary = représentation binaire à traiter. * +* size = nombre de groupe à parcourir. * +* handlers = ensemble des groupes de gestionnaires. * +* count = liste des quantités de gestionnaires groupés. * +* * +* Description : Insère des indications dans le texte humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mark_exception_handlers(const GLoadedBinary *binary, uleb128_t size, caught_exception **handlers, size_t *count) +{ + GCodeBuffer *buffer; /* Contenu textuel à modifier */ + uleb128_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + GBufferLine *line; /* Nouvelle ligne à compléter */ + size_t len; /* Taille de la description */ + char *fulldesc; /* Description complète */ + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + + for (i = 0; i < size; i++) + for (j = 0; j < count[i]; j++) { - result[*count].desc = strdup(_("default")); - (*count)++; - } + line = g_code_buffer_insert_at(buffer, handlers[i][j].addr, true); + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - } + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_INDICATION); - return result; + len = strlen(_("Handler for caught '%s'")) + strlen(handlers[i][j].desc); + fulldesc = (char *)calloc(len + 1, sizeof(char)); + snprintf(fulldesc, len + 1, _("Handler for caught '%s'"), handlers[i][j].desc); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION); + + free(fulldesc); + + } } /****************************************************************************** * * -* Paramètres : binary = représentation binaire à traiter. * -* try = informations sur la gestion à consulter. * -* handlers = liste de tous les gestionnaires en place. * -* routine = routine associée, pour l'accès au instructions. * +* Paramètres : binary = représentation binaire à traiter. * +* routine = routine associée, pour l'accès au instructions. * +* hlist = liste de tous les gestionnaires en place. * +* count = quantité de destinations trouvées. [OUT] * * * -* Description : Rattache les gestionnaires d'exception à leur code couvert. * +* Description : Construit des listes pointant sur les différentes gestions. * * * -* Retour : - * +* Retour : Adresses des codes à lier systématiquement. * * * * Remarques : - * * * ******************************************************************************/ -static void attach_caught_code(GLoadedBinary *binary, const try_item *try, const encoded_catch_handler_list *handlers, const GBinRoutine *routine) +static caught_exception **build_all_destinations_list(const GLoadedBinary *binary, const GBinRoutine *routine, const encoded_catch_handler_list *hlist, size_t **count) { - vmpa_t start; /* Début de la zone couverte */ - vmpa_t end; /* Début de la zone couverte */ + caught_exception **result; /* Liste de listes à retourner */ + GDexFormat *format; /* Format du binaire chargé */ + vmpa_t start; /* Début du code de la routine */ GArchInstruction *instrs; /* Instructions Dalvik */ - GArchInstruction *first; /* Première instruction */ - GArchInstruction *next; /* Dernière instruction + 1 */ - GArchInstruction *prev; /* Instruction à détacher */ - GArchInstruction *iter; /* Boucle de parcours */ - size_t dests_count; /* Nombre de points d'arrivée */ - caught_exception *dests; /* Points d'arrivée */ - size_t i; /* Boucle de parcours */ + uleb128_t i; /* Boucle de parcours #1 */ + encoded_catch_handler *handlers; /* Groupe de gestionnaires */ + leb128_t max; /* Quantité d'exception */ + leb128_t j; /* Boucle de parcours #2 */ + caught_exception *excep; /* Raccourci confortable */ + GDataType *type; /* Type de l'exception */ - start = g_binary_routine_get_address(routine); - start += try->start_addr * sizeof(uint16_t); + format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); - end = start + try->insn_count * sizeof(uint16_t); + start = g_binary_routine_get_address(routine); instrs = g_loaded_binary_get_instructions(binary); - first = g_arch_instruction_find_by_address(instrs, start, true); - next = g_arch_instruction_find_by_address(instrs, end, true); + instrs = g_arch_instruction_find_by_address(instrs, start, true); - /* Si des détachements sont nécessaires... */ + /* Création d'un espace mémoire pour les listes */ - if (!g_arch_instruction_has_sources(first)) - { - prev = g_arch_instruction_get_prev_iter(instrs, first); - g_arch_instruction_link_with(prev, first, ILT_EXEC_FLOW); - } + result = (caught_exception **)calloc(hlist->size, sizeof(caught_exception *)); + *count = (size_t *)calloc(hlist->size, sizeof(size_t)); - if (!g_arch_instruction_has_sources(next)) + /* Parcours de chaque groupe de gestionnaires */ + + for (i = 0; i < hlist->size; i++) { - prev = g_arch_instruction_get_prev_iter(instrs, next); - g_arch_instruction_link_with(prev, next, ILT_EXEC_FLOW); - } + handlers = &hlist->list[i]; + max = leb128_abs(handlers->size); - /* Détermination du code des exceptions */ - dests = build_destinations_list(binary, try, handlers, routine, &dests_count); + (*count)[i] = max + (handlers->size < 0 ? 1 : 0); + result[i] = (caught_exception *)calloc((*count)[i], sizeof(caught_exception)); - if (dests != NULL) - { - /* Rattachements */ - for (iter = first; - iter != NULL; - iter = g_arch_instruction_get_next_iter(instrs, iter, end)) + (*count)[i] = 0; + + for (j = 0; j < max; j++) { - if (!g_arch_instruction_has_destinations(iter)) + excep = &result[i][(*count)[i]]; + + excep->addr = start + handlers->handlers[j].addr * sizeof(uint16_t); + excep->instr = g_arch_instruction_find_by_address(instrs, excep->addr, true); + + if (excep->instr == NULL) continue; - for (i = 0; i < dests_count; i++) - g_arch_instruction_link_with(iter, dests[i].instr, ILT_CATCH_EXCEPTION); + type = get_type_from_dex_pool(format, handlers->handlers[j].type_idx); + excep->desc = g_data_type_to_string(type); + + (*count)[i]++; } - /* Libération de la mémoire utilisée */ + if (handlers->size < 0) + { + excep = &result[i][(*count)[i]]; - for (i = 0; i < dests_count; i++) - free(dests[i].desc); + excep->addr = start + handlers->catch_all_addr * sizeof(uint16_t); + excep->instr = g_arch_instruction_find_by_address(instrs, excep->addr, true); - free(dests); + if (excep->instr != NULL) + { + excep->desc = strdup(_("default")); + (*count)[i]++; + } + + } } + return result; + } @@ -268,11 +314,17 @@ static void attach_caught_code(GLoadedBinary *binary, const try_item *try, const * * ******************************************************************************/ -static void look_for_exception_handlers(GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method) +static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method) { const code_item *body; /* Description du corps */ GBinRoutine *routine; /* Abstraction globale */ - uint16_t i; /* Boucle de parcours */ + encoded_catch_handler_list *hlist; /* Confort vers la liste brute */ + caught_exception **handlers; /* Interprétation des gestions */ + size_t *count; /* Tailles des groupes */ + uint16_t i; /* Boucle de parcours #1 */ + try_item *try; /* Raccourci vers une zone */ + uleb128_t index; /* Indice du bon gestionnaire */ + size_t j; /* Boucle de parcours #2 */ body = g_dex_method_get_dex_body(method); @@ -281,15 +333,48 @@ static void look_for_exception_handlers(GLoadedBinary *binary, const GDexFormat routine = g_dex_method_get_routine(method); + hlist = body->handlers; + handlers = build_all_destinations_list(binary, routine, hlist, &count); + + /* Pour chaque zone couverte... */ + for (i = 0; i < body->tries_size; i++) { - if (!check_covered_area(&body->tries[i], routine)) + try = &body->tries[i]; + + if (!check_covered_area(try, routine)) continue; - attach_caught_code(binary, &body->tries[i], body->handlers, routine); + for (index = 0; index < hlist->size; index++) + if (try->handler_off == hlist->list[index].offset) + break; + + if (index == hlist->size) + continue; + + attach_caught_code(binary, routine, try, handlers[index], count[index]); + + } + + /* Ajout des précisions */ + + mark_exception_handlers(binary, hlist->size, handlers, count); + + /* Libération de la mémoire utilisée */ + + for (index = 0; index < hlist->size; index++) + { + for (j = 0; j < count[index]; j++) + free(handlers[index][j].desc); + + if (handlers[index] != NULL) + free(handlers[index]); } + if (handlers != NULL) free(handlers); + if (count != NULL) free(count); + } |