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 | |
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
-rw-r--r-- | ChangeLog | 32 | ||||
-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 | ||||
-rw-r--r-- | src/analysis/disass/links.c | 6 | ||||
-rw-r--r-- | src/arch/instruction.h | 1 | ||||
-rw-r--r-- | src/format/dex/dex-int.c | 273 | ||||
-rwxr-xr-x | src/format/dex/dex-int.h | 23 | ||||
-rwxr-xr-x | src/format/dex/dex_def.h | 109 | ||||
-rw-r--r-- | src/gtkext/graph/layout.c | 1 |
13 files changed, 787 insertions, 81 deletions
@@ -1,3 +1,35 @@ +12-12-11 Cyrille Bagard <nocbos@gmail.com> + + * plugins/androhelpers/androhelpers.c: + Check for Dex format and handle a new process. + + * plugins/androhelpers/Makefile.am: + Add the 'switch.[ch]' files to libandrohelpers_la_SOURCES. + + * plugins/androhelpers/params.c: + Remove the check of the processed format. + + * plugins/androhelpers/switch.c: + * plugins/androhelpers/switch.h: + New entries: take care of Dalvik switch cases. + + * plugins/androhelpers/try_n_catch.c: + Typo. Remove the check of the processed format. + + * src/analysis/disass/links.c: + Update code for the new link. + + * src/arch/instruction.h: + Create a new kind of link, for switch cases. + + * src/format/dex/dex_def.h: + * src/format/dex/dex-int.c: + * src/format/dex/dex-int.h: + Support the data relative to Dalvik switches. + + * src/gtkext/graph/layout.c: + Update code for the new link. + 12-12-10 Cyrille Bagard <nocbos@gmail.com> * src/glibext/gbufferline.c: 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); diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 0ba3fc6..df0c77f 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -108,9 +108,9 @@ void establish_links_between_lines(GArchInstruction *list, GBinRoutine **routine default: /** - * Note pour GCC : à ce stade du désassemblage, ILT_CATCH_EXCEPTION - * ne peut être présente, car ne provenant que de greffons. - * Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas. + * Note pour GCC : à ce stade du désassemblage, ILT_CASE_JUMP et + * ILT_CATCH_EXCEPTION ne peuvent être présentes, car ne provenant + * que de greffons. Pour ILT_EXEC_FLOW, sa seule insertion est ici, plus bas. */ break; diff --git a/src/arch/instruction.h b/src/arch/instruction.h index ae0bd68..8963284 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -45,6 +45,7 @@ typedef enum _InstructionLinkType ILT_NONE, /* Aucune instruction visée */ ILT_EXEC_FLOW, /* Raccord attendu entre blocs */ ILT_JUMP, /* Saut inconditionnel */ + ILT_CASE_JUMP, /* Saut suite à aiguillage */ ILT_JUMP_IF_TRUE, /* Saut conditionnel (si vrai) */ ILT_JUMP_IF_FALSE, /* Saut conditionnel (si faux) */ ILT_CALL, /* Appel d'une fonction */ diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c index 200b01f..58211e5 100644 --- a/src/format/dex/dex-int.c +++ b/src/format/dex/dex-int.c @@ -27,11 +27,80 @@ #include <malloc.h> +#include "../../arch/dalvik/instruction-def.h" #include "../../common/endianness.h" /* ---------------------------------------------------------------------------------- */ +/* DESCRIPTION DU FORMAT DALVIK */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* header = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une en-tête de programme DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + size_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) + result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + + for (i = 0; i < 20 && result; i++) + result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + + result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* ELEMENTS DE TABLE DES CONSTANTES */ /* ---------------------------------------------------------------------------------- */ @@ -840,18 +909,87 @@ void reset_dex_code_item(code_item *item) +/* ---------------------------------------------------------------------------------- */ +/* AIGUILLAGES DIVERS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* packed = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage compact. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_packed_switch(const GDexFormat *format, off_t *pos, packed_switch *packed) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + packed->targets = NULL; + + result &= read_u16(&packed->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&packed->size, content, pos, length, SRE_LITTLE); + result &= read_u32(&packed->first_key, content, pos, length, SRE_LITTLE); + if (result && packed->size > 0) + { + packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t)); + + for (i = 0; i < packed->size && result; i++) + result &= read_u32(&packed->targets[i], content, pos, length, SRE_LITTLE); + + } + + if (!result) + reset_dex_packed_switch(packed); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : packed = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +void reset_dex_packed_switch(packed_switch *packed) +{ + if (packed->targets != NULL) + free(packed->targets); +} /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * pos = position de début de lecture. [OUT] * -* header = structure lue à retourner. [OUT] * +* sparse = structure lue à retourner. [OUT] * * * -* Description : Procède à la lecture d'une en-tête de programme DEX. * +* Description : Procède à la lecture d'un contenu d'aiguillage dispersé. * * * * Retour : Bilan de l'opération. * * * @@ -859,54 +997,131 @@ void reset_dex_code_item(code_item *item) * * ******************************************************************************/ -bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch *sparse) { bool result; /* Bilan à retourner */ const bin_t *content; /* Contenu binaire à lire */ off_t length; /* Taille totale du contenu */ - size_t i; /* Boucle de parcours */ + uint16_t i; /* Boucle de parcours */ result = true; content = G_BIN_FORMAT(format)->content; length = G_BIN_FORMAT(format)->length; - for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) - result = read_u8(&header->magic[i], content, pos, length, SRE_LITTLE); + sparse->keys = NULL; + sparse->targets = NULL; - result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE); + result &= read_u16(&sparse->size, content, pos, length, SRE_LITTLE); - for (i = 0; i < 20 && result; i++) - result = read_u8(&header->signature[i], content, pos, length, SRE_LITTLE); + if (result && sparse->size > 0) + { + sparse->keys = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); + sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); - result &= read_u32(&header->file_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->header_size, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->endian_tag, content, pos, length, SRE_LITTLE); + for (i = 0; i < sparse->size && result; i++) + result &= read_u32(&sparse->targets[i], content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->link_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->map_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->string_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->type_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->proto_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->field_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->method_ids_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->class_defs_off, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_size, content, pos, length, SRE_LITTLE); - result &= read_u32(&header->data_off, content, pos, length, SRE_LITTLE); + } + + if (!result) + reset_dex_sparse_switch(sparse); return result; } +/****************************************************************************** +* * +* Paramètres : sparse = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_sparse_switch(sparse_switch *sparse) +{ + if (sparse->keys != NULL) + free(sparse->keys); + + if (sparse->targets != NULL) + free(sparse->targets); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* dsxitch = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu d'aiguillage Dex interne. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_switch(const GDexFormat *format, off_t *pos, dex_switch *dswitch) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uint16_t ident; /* Pseudo-code d'identification*/ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u16(&ident, content, (off_t []) { *pos }, length, SRE_LITTLE); + + if (result) + { + if (ident == DPO_PACKED_SWITCH) + result = read_dex_packed_switch(format, pos, (packed_switch *)dswitch); + + else if (ident == DPO_SPARSE_SWITCH) + result = read_dex_sparse_switch(format, pos, (sparse_switch *)dswitch); + + else + result = false; + } + + return result; +} + +/****************************************************************************** +* * +* Paramètres : dswitch = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_switch(dex_switch *dswitch) +{ + if (dswitch->packed.ident == DPO_PACKED_SWITCH) + reset_dex_packed_switch((packed_switch *)dswitch); + else + reset_dex_sparse_switch((sparse_switch *)dswitch); + +} diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h index 6a153c1..55a48b5 100755 --- a/src/format/dex/dex-int.h +++ b/src/format/dex/dex-int.h @@ -68,6 +68,13 @@ size_t g_dex_format_count_classes(const GDexFormat *); GDexClass *g_dex_format_get_class(const GDexFormat *, size_t); +/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ + + +/* Procède à la lecture d'une en-tête de programme DEX. */ +bool read_dex_header(const GDexFormat *, off_t *, dex_header *); + + /* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */ @@ -147,14 +154,26 @@ void reset_dex_code_item(code_item *); +/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */ -/* Procède à la lecture d'une en-tête de programme DEX. */ -bool read_dex_header(const GDexFormat *, off_t *, dex_header *); +/* Procède à la lecture d'un contenu d'aiguillage compact. */ +bool read_dex_packed_switch(const GDexFormat *, off_t *, packed_switch *); + +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_packed_switch(packed_switch *); +/* Procède à la lecture d'un contenu d'aiguillage dispersé. */ +bool read_dex_sparse_switch(const GDexFormat *, off_t *, sparse_switch *); +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_sparse_switch(sparse_switch *); +/* Procède à la lecture d'un contenu d'aiguillage Dex interne. */ +bool read_dex_switch(const GDexFormat *, off_t *, dex_switch *); +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_switch(dex_switch *); diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h index d21ac15..eee3574 100755 --- a/src/format/dex/dex_def.h +++ b/src/format/dex/dex_def.h @@ -29,6 +29,55 @@ +/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ + + +/* Identifiant magique "dex\n035\0" */ +#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00" +#define DEX_FILE_MAGIC_LEN 8 + +/* Types de boutisme */ +#define ENDIAN_CONSTANT 0x12345678 +#define REVERSE_ENDIAN_CONSTANT 0x78563412 + +/* Indice non valide */ +#define NO_INDEX 0xffffffff + + +/* En-tête de tout programe Dex */ +typedef struct _dex_header +{ + uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */ + + uint32_t checksum; /* Somme de contrôle adler32 */ + uint8_t signature[20]; /* Emprunte SHA-1 du reste */ + uint32_t file_size; /* Taille du fichier */ + uint32_t header_size; /* Taille de cette en-tête */ + + uint32_t endian_tag; /* Boutisme du fichier */ + + uint32_t link_size; /* Taille de section 'liaisons'*/ + uint32_t link_off; /* Position de ladite section */ + uint32_t map_off; /* Position de la cartographie */ + uint32_t string_ids_size; /* Nombre de chaînes de carac. */ + uint32_t string_ids_off; /* Position de cette liste */ + uint32_t type_ids_size; /* Nom d'identifiant de type */ + uint32_t type_ids_off; /* Position de la liste */ + uint32_t proto_ids_size; /* Nombre de prototypes */ + uint32_t proto_ids_off; /* Position de la liste */ + uint32_t field_ids_size; /* Nombre de champs */ + uint32_t field_ids_off; /* Position de la liste */ + uint32_t method_ids_size; /* Nombre de méthodes */ + uint32_t method_ids_off; /* Position de la liste */ + uint32_t class_defs_size; /* Nombre de classes déclarées */ + uint32_t class_defs_off; /* Position de la liste */ + uint32_t data_size; /* Taille des données */ + uint32_t data_off; /* Début des données */ + +} dex_header; + + + /* -------------------------- CONSTANTES POUR DEX DIVERSES -------------------------- */ @@ -240,52 +289,36 @@ typedef struct _code_item -/* -------------------------- DESCRIPTION DU FORMAT DALVIK -------------------------- */ - +/* ------------------------------- AIGUILLAGES DIVERS ------------------------------- */ -/* Identifiant magique "dex\n035\0" */ -#define DEX_FILE_MAGIC "\x64\x65\x78\x0a\x30\x33\x35\x00" -#define DEX_FILE_MAGIC_LEN 8 - -/* Types de boutisme */ -#define ENDIAN_CONSTANT 0x12345678 -#define REVERSE_ENDIAN_CONSTANT 0x78563412 -/* Indice non valide */ -#define NO_INDEX 0xffffffff +/* Aiguillage compressé */ +typedef struct _packed_switch +{ + uint16_t ident; /* Pseudo-code d'identification*/ + uint16_t size; /* Nombre d'entrées */ + uint32_t first_key; /* Première et plus petite clef*/ + uint32_t *targets; /* Cibles relatives */ +} packed_switch; -/* En-tête de tout programe Dex */ -typedef struct _dex_header +/* Aiguillage dispersé */ +typedef struct _sparse_switch { - uint8_t magic[DEX_FILE_MAGIC_LEN]; /* Valeur magique du format */ - - uint32_t checksum; /* Somme de contrôle adler32 */ - uint8_t signature[20]; /* Emprunte SHA-1 du reste */ - uint32_t file_size; /* Taille du fichier */ - uint32_t header_size; /* Taille de cette en-tête */ + uint16_t ident; /* Pseudo-code d'identification*/ + uint16_t size; /* Nombre d'entrées */ + uint32_t *keys; /* Clefs valeureuses */ + uint32_t *targets; /* Cibles relatives */ - uint32_t endian_tag; /* Boutisme du fichier */ +} sparse_switch; - uint32_t link_size; /* Taille de section 'liaisons'*/ - uint32_t link_off; /* Position de ladite section */ - uint32_t map_off; /* Position de la cartographie */ - uint32_t string_ids_size; /* Nombre de chaînes de carac. */ - uint32_t string_ids_off; /* Position de cette liste */ - uint32_t type_ids_size; /* Nom d'identifiant de type */ - uint32_t type_ids_off; /* Position de la liste */ - uint32_t proto_ids_size; /* Nombre de prototypes */ - uint32_t proto_ids_off; /* Position de la liste */ - uint32_t field_ids_size; /* Nombre de champs */ - uint32_t field_ids_off; /* Position de la liste */ - uint32_t method_ids_size; /* Nombre de méthodes */ - uint32_t method_ids_off; /* Position de la liste */ - uint32_t class_defs_size; /* Nombre de classes déclarées */ - uint32_t class_defs_off; /* Position de la liste */ - uint32_t data_size; /* Taille des données */ - uint32_t data_off; /* Début des données */ +/* Manipulation interne */ +typedef union _dex_switch +{ + packed_switch packed; /* Modèle compact */ + sparse_switch sparse; /* Modèle dispersé */ -} dex_header; +} dex_switch; diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 3a2f4e3..45e3a82 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -169,6 +169,7 @@ static char *complete_graph_links(const GtkGraphView *view, GtkViewPanel **views { case ILT_EXEC_FLOW: case ILT_JUMP: + case ILT_CASE_JUMP: snprintf(cmd, LINKS_DESC_LEN, "_%p:s -> _%p:n [ltail=cluster_%p, lhead=cluster_%p];\n", views[i], views[k], views[i], views[k]); |