summaryrefslogtreecommitdiff
path: root/plugins/androhelpers
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2012-12-10 23:41:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2012-12-10 23:41:09 (GMT)
commit79ec14ee5c1cea5c4ad345a7047b47b9205fc29e (patch)
tree0596bb4b7910964ef96c3705c80ec5dba677eeb0 /plugins/androhelpers
parent42420cfa1f406a5f0a9f062b258ece72098635b5 (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.am3
-rw-r--r--plugins/androhelpers/androhelpers.c13
-rw-r--r--plugins/androhelpers/params.c3
-rw-r--r--plugins/androhelpers/switch.c360
-rw-r--r--plugins/androhelpers/switch.h37
-rw-r--r--plugins/androhelpers/try_n_catch.c7
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);