diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2012-12-10 23:41:09 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2012-12-10 23:41:09 (GMT) |
commit | 79ec14ee5c1cea5c4ad345a7047b47b9205fc29e (patch) | |
tree | 0596bb4b7910964ef96c3705c80ec5dba677eeb0 /plugins/androhelpers | |
parent | 42420cfa1f406a5f0a9f062b258ece72098635b5 (diff) |
Took care of Dalvik switch cases.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@299 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'plugins/androhelpers')
-rw-r--r-- | plugins/androhelpers/Makefile.am | 3 | ||||
-rw-r--r-- | plugins/androhelpers/androhelpers.c | 13 | ||||
-rw-r--r-- | plugins/androhelpers/params.c | 3 | ||||
-rw-r--r-- | plugins/androhelpers/switch.c | 360 | ||||
-rw-r--r-- | plugins/androhelpers/switch.h | 37 | ||||
-rw-r--r-- | plugins/androhelpers/try_n_catch.c | 7 |
6 files changed, 414 insertions, 9 deletions
diff --git a/plugins/androhelpers/Makefile.am b/plugins/androhelpers/Makefile.am index d5618d1..acf4a4e 100644 --- a/plugins/androhelpers/Makefile.am +++ b/plugins/androhelpers/Makefile.am @@ -4,7 +4,8 @@ lib_LTLIBRARIES = libandrohelpers.la libandrohelpers_la_SOURCES = \ androhelpers.h androhelpers.c \ params.h params.c \ - try_n_catch.h try_n_catch.c + try_n_catch.h try_n_catch.c \ + switch.h switch.c libandrohelpers_la_LDFLAGS = -L../../src/.libs -L../../src/gui/.libs -lchrysagui \ -lchrysadisass -lchrysagtkext \ diff --git a/plugins/androhelpers/androhelpers.c b/plugins/androhelpers/androhelpers.c index f7360f8..c61ce02 100644 --- a/plugins/androhelpers/androhelpers.c +++ b/plugins/androhelpers/androhelpers.c @@ -27,7 +27,11 @@ #include <string.h> +#include <format/dex/dex.h> + + #include "params.h" +#include "switch.h" #include "try_n_catch.h" @@ -92,16 +96,25 @@ bool execute_action_on_binary(GPluginModule *plugin, GLoadedBinary *binary, Plug { bool result; /* Bilan à retourner */ + if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary))) + return false; + result = true; if (action == PGA_BINARY_DISASSEMBLED) result &= replace_parameters(binary); else if (action == PGA_BINARY_LINKED) + { + result &= extract_switch_info(binary, true); result &= process_exception_handlers(binary, true); + } else if (action == PGA_BINARY_PRINTED) + { + result &= extract_switch_info(binary, false); result &= process_exception_handlers(binary, false); + } return result; diff --git a/plugins/androhelpers/params.c b/plugins/androhelpers/params.c index bbd254a..5b47aef 100644 --- a/plugins/androhelpers/params.c +++ b/plugins/androhelpers/params.c @@ -189,9 +189,6 @@ bool replace_parameters(GLoadedBinary *binary) size_t j; /* Boucle de parcours #2 */ GDexMethod *method; /* Méthode à parcourir */ - if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary))) - return false; - instrs = g_loaded_binary_get_instructions(binary); format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c new file mode 100644 index 0000000..a6f6f5b --- /dev/null +++ b/plugins/androhelpers/switch.c @@ -0,0 +1,360 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * switch.c - apport de précisions sur les aiguillages Dalvik + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "switch.h" + + +#include <string.h> + + +#include <arch/dalvik/instruction.h> +#include <arch/dalvik/instruction-def.h> +#include <arch/dalvik/operands/target.h> +#include <format/dex/dex-int.h> +#include <../i18n.h> + + + +/* Récupère les détails d'un aiguillage. */ +static bool load_dex_switch(const GArchInstruction *, GArchInstruction *, const GDexFormat *, dex_switch *); + +/* Lie les instructions selon les cas d'un aiguillage. */ +static void link_all_switch_cases(GArchInstruction *, const dex_switch *, GArchInstruction *, vmpa_t, vmpa_t); + +/* Insère des indications dans le texte humainement lisibles. */ +static void mark_all_switch_cases(const GArchInstruction *, const dex_switch *, GArchInstruction *, const GLoadedBinary *, vmpa_t, vmpa_t); + +/* Recherche des aiguillages dans chaque instruction. */ +static void look_for_switch_instructions(const GDexMethod *, GArchInstruction *, const GLoadedBinary *, const GDexFormat *, bool); + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'aiguillage rencontrée. * +* instrs = liste des instructions pour tout le binaire. * +* format = format du binaire Dex. * +* dswitch = détails de l'aiguillage à reconstituer. [OUT] * +* * +* Description : Récupère les détails d'un aiguillage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_dex_switch(const GArchInstruction *instr, GArchInstruction *instrs, const GDexFormat *format, dex_switch *dswitch) +{ + bool result; /* Bilan à retourner */ + GArchOperand *operand; /* Operande à manipuler */ + const GImmOperand *imm; /* Valeur concrête */ + vmpa_t addr; /* Adresse du corps des infos */ + GArchInstruction *info; /* Corps des infos brutes */ + off_t pos; /* Position dans le binaire */ + uint32_t *targets; /* Cibles relatives à corriger */ + uint16_t i; /* Boucle de parcours */ + + /* Récupération de l'opérande */ + + operand = g_arch_instruction_get_operand(instr, 1); + + if (!G_IS_DALVIK_TARGET_OPERAND(operand)) + return false; + + imm = g_dalvik_target_operand_get_value(G_DALVIK_TARGET_OPERAND(operand)); + + if (!g_imm_operand_to_vmpa_t(imm, &addr)) + return false; + + /* Lecture des détails */ + + info = g_arch_instruction_find_by_address(instrs, addr, true); + if (info == NULL) + return false; + + g_arch_instruction_get_location(info, &pos, NULL, NULL); + + result = read_dex_switch(format, &pos, dswitch); + + /* Ajustement relatif */ + + if (result) + { + g_arch_instruction_get_location(instr, NULL, NULL, &addr); + + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + targets = dswitch->packed.targets; + else + targets = dswitch->sparse.targets; + + for (i = 0; i < dswitch->packed.size; i++) + targets[i] = ((uint32_t)addr) + targets[i] * sizeof(uint16_t); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'aiguillage rencontrée. * +* dswitch = détails de l'aiguillage à reconstituer. * +* instrs = liste des instructions pour tout le binaire. * +* start = début de la zone théoriquement couverte. * +* end = fin de la zone théoriquement couverte. * +* * +* Description : Lie les instructions selon les cas d'un aiguillage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dswitch, GArchInstruction *instrs, vmpa_t start, vmpa_t end) +{ + uint32_t *targets; /* Cibles relatives à corriger */ + uint16_t i; /* Boucle de parcours */ + GArchInstruction *next; /* Instruction suivante */ + + /* Valeurs définies */ + + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + targets = dswitch->packed.targets; + else + targets = dswitch->sparse.targets; + + for (i = 0; i < dswitch->packed.size; i++) + { + if (!(start <= targets[i] && targets[i] < end)) + continue; + + next = g_arch_instruction_find_by_address(instrs, (vmpa_t)targets[i], true); + + if (next != NULL) + g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP); + + } + + /* Cas du défaut */ + + next = g_arch_instruction_get_next_iter(instrs, instr, end); + + if (next != NULL) + g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'aiguillage rencontrée. * +* dswitch = détails de l'aiguillage à reconstituer. * +* instrs = liste des instructions pour tout le binaire. * +* binary = représentation binaire à traiter. * +* start = début de la zone théoriquement couverte. * +* end = fin de la zone théoriquement couverte. * +* * +* Description : Insère des indications dans le texte humainement lisibles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mark_all_switch_cases(const GArchInstruction *instr, const dex_switch *dswitch, GArchInstruction *instrs, const GLoadedBinary *binary, vmpa_t start, vmpa_t end) +{ + GCodeBuffer *buffer; /* Contenu textuel à modifier */ + uint32_t *targets; /* Cibles relatives à corriger */ + uint16_t i; /* Boucle de parcours */ + uint16_t index; /* Véritable indice recalculé */ + uint32_t value; /* Valeur à indiquer */ + GBufferLine *line; /* Nouvelle ligne à compléter */ + size_t len; /* Taille de la description */ + char *fulldesc; /* Description complète */ + GArchInstruction *next; /* Instruction suivante */ + vmpa_t addr; /* Adresse de cette instruction*/ + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + + /* Valeurs définies */ + + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + targets = dswitch->packed.targets; + else + targets = dswitch->sparse.targets; + + for (i = dswitch->packed.size; i > 0; i--) + { + index = i - 1; + + if (!(start <= targets[index] && targets[index] < end)) + continue; + + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + value = dswitch->packed.first_key + index; + else + value = dswitch->sparse.keys[index]; + + line = g_code_buffer_insert_at(buffer, (vmpa_t)targets[index], true); + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + + len = strlen(_("; Case for value 0x%08x (%d)")) + 8 + strlen("4294967295U") /* UINT_MAX */; + fulldesc = (char *)calloc(len + 1, sizeof(char)); + len = snprintf(fulldesc, len + 1, _("; Case for value 0x%08x (%d)"), value, value); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION); + + free(fulldesc); + + } + + /* Cas du défaut */ + + next = g_arch_instruction_get_next_iter(instrs, instr, end); + + if (next != NULL) + { + g_arch_instruction_get_location(next, NULL, NULL, &addr); + + line = g_code_buffer_insert_at(buffer, addr, true); + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); + + fulldesc = _("; Default case"); + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, + fulldesc, strlen(fulldesc), RTT_INDICATION); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : method = routine à venir parcourir. * +* instrs = liste des instructions pour tout le binaire. * +* binary = représentation binaire à traiter. * +* format = format du binaire Dex. * +* link = édition de liens ou impression de commentaires ? * +* * +* Description : Recherche des aiguillages dans chaque instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void look_for_switch_instructions(const GDexMethod *method, GArchInstruction *instrs, const GLoadedBinary *binary, const GDexFormat *format, bool link) +{ + GBinRoutine *routine; /* Abstraction de la méthode */ + vmpa_t start; /* Début de la zone couverte */ + vmpa_t end; /* Fin de la zone couverte */ + GArchInstruction *iter; /* Boucle de parcours */ + DalvikOpcodes opcode; /* Type d'instruction Dalvik */ + dex_switch dswitch; /* Infos d'aiguillage */ + + routine = g_dex_method_get_routine(method); + + start = g_binary_routine_get_address(routine); + end = start + g_binary_routine_get_size(routine); + + for (iter = g_arch_instruction_find_by_address(instrs, start, true); + iter != NULL; + iter = g_arch_instruction_get_next_iter(instrs, iter, end)) + { + opcode = g_dalvik_instruction_get_opcode(G_DALVIK_INSTRUCTION(iter)); + + if (opcode != DOP_PACKED_SWITCH && opcode != DOP_SPARSE_SWITCH) + continue; + + if (!load_dex_switch(iter, instrs, format, &dswitch)) + continue; + + if (link) + link_all_switch_cases(iter, &dswitch, instrs, start, end); + else + mark_all_switch_cases(iter, &dswitch, instrs, binary, start, end); + + reset_dex_switch(&dswitch); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : binary = représentation binaire à traiter. * +* link = édition de liens ou impression de commentaires ? * +* * +* Description : Traite les données binaires associées aux switchs. * +* * +* Retour : true si une action a été menée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool extract_switch_info(GLoadedBinary *binary, bool link) +{ + GArchInstruction *instrs; /* Instructions Dalvik */ + GDexFormat *format; /* Format du binaire chargé */ + size_t cls_count; /* Nombre de classes trouvées */ + size_t i; /* Boucle de parcours #1 */ + GDexClass *class; /* Classe à analyser */ + size_t meth_count; /* Nombre de méthodes trouvées */ + size_t j; /* Boucle de parcours #2 */ + GDexMethod *method; /* Méthode à parcourir */ + + instrs = g_loaded_binary_get_instructions(binary); + format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); + + cls_count = g_dex_format_count_classes(format); + for (i = 0; i < cls_count; i++) + { + class = g_dex_format_get_class(format, i); + + meth_count = g_dex_class_count_methods(class, false); + for (j = 0; j < meth_count; j++) + { + method = g_dex_class_get_method(class, false, j); + look_for_switch_instructions(method, instrs, binary, format, link); + } + + meth_count = g_dex_class_count_methods(class, true); + for (j = 0; j < meth_count; j++) + { + method = g_dex_class_get_method(class, true, j); + look_for_switch_instructions(method, instrs, binary, format, link); + } + + } + + return true; + +} diff --git a/plugins/androhelpers/switch.h b/plugins/androhelpers/switch.h new file mode 100644 index 0000000..4d0754a --- /dev/null +++ b/plugins/androhelpers/switch.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * switch.h - prototypes pour l'apport de précisions sur les aiguillages Dalvik + * + * Copyright (C) 2012 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_SWITCH_H +#define _PLUGINS_SWITCH_H + + +#include <analysis/binary.h> + + + +/* Traite les données binaires associées aux switchs. */ +bool extract_switch_info(GLoadedBinary *, bool); + + + +#endif /* _PLUGINS_SWITCH_H */ diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c index d2ab4a9..2543641 100644 --- a/plugins/androhelpers/try_n_catch.c +++ b/plugins/androhelpers/try_n_catch.c @@ -51,7 +51,7 @@ static bool check_covered_area(const try_item *, const GBinRoutine *); /* Rattache les gestionnaires d'exception à leur code couvert. */ 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. */ +/* Insère des indications dans le texte humainement lisibles. */ static void mark_exception_handlers(const GLoadedBinary *, uleb128_t, caught_exception **, size_t *); /* Construit des listes pointant sur les différentes gestions. */ @@ -172,7 +172,7 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r * 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. * +* Description : Insère des indications dans le texte humainement lisibles. * * * * Retour : - * * * @@ -409,9 +409,6 @@ bool process_exception_handlers(GLoadedBinary *binary, bool link) size_t j; /* Boucle de parcours #2 */ GDexMethod *method; /* Méthode à parcourir */ - if (!G_IS_DEX_FORMAT(g_loaded_binary_get_format(binary))) - return false; - format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); cls_count = g_dex_format_count_classes(format); |