summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/androhelpers/try_n_catch.c297
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);
+
}