diff options
69 files changed, 6495 insertions, 130 deletions
@@ -1,3 +1,127 @@ +10-05-13 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + Add the new Makefiles from the 'src/arch/dalvik' and 'src/format/dex' + directories to AC_CONFIG_FILES. + + * src/analysis/binary.c: + Print a messsage when Dalvik VM is detected. + + * src/analysis/exporter.c: + * src/analysis/exporter.h: + Add a new rendering attributes type: RTT_SECTION. + + * src/analysis/routine.c: + * src/analysis/routine.h: + * src/analysis/type.c: + * src/analysis/type.h: + Handle namespaces in types/routines name. + + * src/arch/archbase.h: + Handle 4-bit sizes. + + * src/arch/artificial.c: + Fix a bug: 'db' is not a 'ret' keyword and it must be known. + + * src/arch/dalvik/instruction.c: + * src/arch/dalvik/instruction.h: + * src/arch/dalvik/Makefile.am: + * src/arch/dalvik/opcodes.h: + * src/arch/dalvik/op_const.c: + * src/arch/dalvik/operand.c: + * src/arch/dalvik/operand.h: + * src/arch/dalvik/op_invoke.c: + * src/arch/dalvik/op_mul.c: + * src/arch/dalvik/op_nop.c: + * src/arch/dalvik/op_ret.c: + * src/arch/dalvik/op_sget.c: + * src/arch/dalvik/processor.c: + * src/arch/dalvik/processor.h: + * src/arch/dalvik/register.c: + * src/arch/dalvik/register.h: + Support the Dalvik Virtual Machine (partially). + + * src/arch/immediate.c: + * src/arch/immediate.h: + Handle 4-bit values. Use MemoryDataSize instead of the dying AsmOperandSize. + + * src/arch/jvm/processor.c: + Typo. + + * src/arch/Makefile.am: + Add dalvik/libarchdalvik.la to libarch_la_LIBADD and dalvik to SUBDIRS. + + * src/arch/processor.c: + * src/arch/processor.h: + Register Dalvik VM as a new architecture. + + * src/arch/x86/opcodes.h: + * src/arch/x86/operand.c: + * src/arch/x86/processor.h: + Typo. + + * src/common/endianness.c: + * src/common/endianness.h: + Read 4-bit values. Use MemoryDataSize instead of the dying AsmOperandSize. + + * src/common/leb128.c: + * src/common/leb128.h: + Load LEB128 values here. + + * src/common/Makefile.am: + Add the leb128.[ch] files to libcommon_la_SOURCES. + + * src/format/dex/class.c: + * src/format/dex/class.h: + * src/format/dex/dex.c: + * src/format/dex/dex_def.h: + * src/format/dex/dex.h: + * src/format/dex/dex-int.c: + * src/format/dex/dex-int.h: + * src/format/dex/Makefile.am: + * src/format/dex/method.c: + * src/format/dex/method.h: + * src/format/dex/pool.c: + * src/format/dex/pool.h: + Support the Dalvik Executable file format (partially). + + * src/format/executable.h: + Add Dalvik as a legal architecture for formats. + + * src/format/format.c: + * src/format/format.h: + Add 'Dalvik Executable' as a new supported format. + + * src/format/format-int.h: + Remove a gcc warnings about discarding qualifiers ('const'). + + * src/format/java/java-int.h: + Typo. + + * src/format/Makefile.am: + Add dex/libformatdex.la to libformat_la_LIBADD and dex to SUBDIRS. + Dwarf support is currently disabled. + + * src/format/mangling/context.c: + * src/format/mangling/context.h: + * src/format/mangling/context-int.h: + * src/format/mangling/demangler.c: + * src/format/mangling/demangler.h: + Change the way demangling is processed: use now contexts to memorize + per session states. Get able to decode only types. + + * src/format/mangling/java_gram.y: + * src/format/mangling/java.h: + * src/format/mangling/java_tok.l: + Add a Java/DEX demangler. + + * src/format/mangling/Makefile.am: + Update the name of the output files in order to be able to have several + analysers in the same program. + + * src/main.c: + Update code. + 10-04-24 Cyrille Bagard <nocbos@gmail.com> * src/arch/jvm/operand.c: diff --git a/configure.ac b/configure.ac index 98d60c5..bba9fdf 100644 --- a/configure.ac +++ b/configure.ac @@ -242,6 +242,7 @@ AC_CONFIG_FILES([Makefile src/Makefile src/analysis/Makefile src/arch/Makefile + src/arch/dalvik/Makefile src/arch/jvm/Makefile src/arch/mips/Makefile src/arch/x86/Makefile @@ -251,6 +252,7 @@ AC_CONFIG_FILES([Makefile src/debug/remgdb/Makefile src/dialogs/Makefile src/format/Makefile + src/format/dex/Makefile src/format/dwarf/Makefile src/format/elf/Makefile src/format/java/Makefile diff --git a/src/analysis/binary.c b/src/analysis/binary.c index d518328..10acfb6 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -719,8 +719,12 @@ GOpenidaBinary *g_openida_binary_new_from_file(const char *filename) goto lbf_error; } + /* FIXME : à déplacer dans arch/... */ switch (g_exe_format_get_target_machine(result->format)) { + case FTM_DALVIK: + log_simple_message(LMT_INFO, _("Detected architecture: Dalvik Virtual Machine")); + break; case FTM_JVM: log_simple_message(LMT_INFO, _("Detected architecture: Java Virtual Machine")); break; diff --git a/src/analysis/exporter.c b/src/analysis/exporter.c index 9de5fbc..edff9d8 100644 --- a/src/analysis/exporter.c +++ b/src/analysis/exporter.c @@ -129,6 +129,23 @@ static void g_content_exporter_class_init(GContentExporterClass *klass) klass->attribs[RTT_LTGT] = pango_attr_list_new(); + /* RTT_SECTION */ + + klass->attribs[RTT_SECTION] = pango_attr_list_new(); + + attrib = pango_attr_foreground_new(51200, 2560, 2560); + pango_attr_list_insert(klass->attribs[RTT_SECTION], attrib); + + /* + attrib = pango_attr_foreground_new(56832, 26880, 43008); + pango_attr_list_insert(klass->attribs[RTT_SECTION], attrib); + + attrib = pango_attr_weight_new(PANGO_WEIGHT_BOLD); + pango_attr_list_insert(klass->attribs[RTT_SECTION], attrib); + */ + + /* RTT_SEGMENT */ + klass->attribs[RTT_SEGMENT] = pango_attr_list_new(); klass->attribs[RTT_STRING] = pango_attr_list_new(); diff --git a/src/analysis/exporter.h b/src/analysis/exporter.h index 7c90cad..56ad2ab 100644 --- a/src/analysis/exporter.h +++ b/src/analysis/exporter.h @@ -52,6 +52,7 @@ typedef enum _RenderingTagType RTT_SIGNS, /* Signes '+', '-' et '*' */ RTT_LTGT, /* Caractères '<' et '>' */ + RTT_SECTION, /* Identifiant de section */ RTT_SEGMENT, /* Indication de segment */ RTT_STRING, /* Chaîne de caractères avec " */ diff --git a/src/analysis/routine.c b/src/analysis/routine.c index cfa7cd5..c5bf056 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -45,6 +45,7 @@ struct _GBinRoutine GOpenidaType *ret_type; /* Type retourné */ + GOpenidaType *namespace; /* Espace de noms / classe */ char *name; /* Désignation humaine */ GOpenidaType *full_name; /* Désignation très complète */ @@ -319,6 +320,26 @@ void g_binary_routine_set_type(GBinRoutine *routine, RoutineType type) /****************************************************************************** * * +* Paramètres : routine = routine à mettre à jour. * +* namespace = instance d'appartenance. * +* * +* Description : Définit le groupe d'appartenance d'une routine donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_routine_set_namespace(GBinRoutine *routine, GOpenidaType *namespace) +{ + routine->namespace = namespace; + +} + + +/****************************************************************************** +* * * Paramètres : routine = routine à mettre à jour. * * name = désignation humainement lisible. * * * @@ -575,6 +596,7 @@ size_t g_binary_routine_get_var_index_from_offset(const GBinRoutine *routine, si char *g_binary_routine_to_string(const GBinRoutine *routine) { char *result; /* Chaîne à renvoyer */ + char *namespace; /* Groupe d'appartenance */ size_t i; /* Boucle de parcours */ char *typestr; /* Stockage de nom temporaire */ @@ -607,6 +629,17 @@ char *g_binary_routine_to_string(const GBinRoutine *routine) /* Nom de la routine */ + if (routine->namespace != NULL) + { + namespace = g_openida_type_to_string(routine->namespace); + + result = stradd(result, namespace); + result = stradd(result, "::"); + + free(namespace); + + } + result = stradd(result, g_binary_routine_get_name(routine)); /* Liste des arguments */ diff --git a/src/analysis/routine.h b/src/analysis/routine.h index 1a2b493..0b673f7 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -85,6 +85,9 @@ off_t g_binary_routine_get_size(const GBinRoutine *); /* Définit le type d'une routine. */ void g_binary_routine_set_type(GBinRoutine *, RoutineType); +/* Définit le groupe d'appartenance d'une routine donnée. */ +void g_binary_routine_set_namespace(GBinRoutine *, GOpenidaType *); + /* Définit le nom humain d'une routine. */ void g_binary_routine_set_name(GBinRoutine *, char *); diff --git a/src/analysis/type.c b/src/analysis/type.c index c113499..3282e2b 100644 --- a/src/analysis/type.c +++ b/src/analysis/type.c @@ -52,6 +52,7 @@ struct _GOpenidaType type_dup_fc dup; /* Copie d'instance existante */ type_to_string_fc to_string; /* Conversion au format texte */ + GOpenidaType *namespace; /* Espace de noms / classe */ TypeQualifier qualifiers; /* Eventuels qualificatifs */ GTypesManager *manager; /* Gestionnaire global */ @@ -343,6 +344,28 @@ GOpenidaType *g_openida_type_dup(const GOpenidaType *type) /****************************************************************************** * * +* Paramètres : type = type à mettre à jour. * +* namespace = instance d'appartenance. * +* * +* Description : Définit le groupe d'appartenance d'un type donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_openida_type_set_namespace(GOpenidaType *type, GOpenidaType *namespace) +{ + g_object_ref(G_OBJECT(namespace)); + + type->namespace = namespace; + +} + + +/****************************************************************************** +* * * Paramètres : type = type à convertir. * * * * Description : Décrit le type fourni sous forme de caractères. * @@ -356,17 +379,29 @@ GOpenidaType *g_openida_type_dup(const GOpenidaType *type) char *g_openida_type_to_string(const GOpenidaType *type) { char *result; /* Chaîne à retourner */ + char *namespace; /* Groupe d'appartenance */ result = type->to_string(type); + if (type->namespace != NULL) + { + namespace = g_openida_type_to_string(type->namespace); + + result = strprep(result, "::"); + result = strprep(result, namespace); + + free(namespace); + + } + if (type->qualifiers & TQF_RESTRICT) - strprep(result, "restrict "); + result = strprep(result, "restrict "); if (type->qualifiers & TQF_VOLATILE) - strprep(result, "volatile "); + result = strprep(result, "volatile "); if (type->qualifiers & TQF_CONST) - strprep(result, "const "); + result = strprep(result, "const "); return result; diff --git a/src/analysis/type.h b/src/analysis/type.h index b127eb3..2662235 100644 --- a/src/analysis/type.h +++ b/src/analysis/type.h @@ -68,6 +68,9 @@ GType g_openida_type_get_type(void); /* Crée un copie d'un type existant. */ GOpenidaType *g_openida_type_dup(const GOpenidaType *); +/* Définit le groupe d'appartenance d'un type donné. */ +void g_openida_type_set_namespace(GOpenidaType *, GOpenidaType *); + /* Décrit le type fourni sous forme de caractères. */ char *g_openida_type_to_string(const GOpenidaType *); diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index ce37874..a968d6f 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -13,6 +13,7 @@ libarch_la_SOURCES = \ processor.h processor.c libarch_la_LIBADD = \ + dalvik/libarchdalvik.la \ jvm/libarchjvm.la \ mips/libarchmips.la \ x86/libarchx86.la @@ -27,4 +28,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = jvm mips x86 +SUBDIRS = dalvik jvm mips x86 diff --git a/src/arch/archbase.h b/src/arch/archbase.h index 330e194..61de861 100644 --- a/src/arch/archbase.h +++ b/src/arch/archbase.h @@ -45,11 +45,13 @@ typedef enum _MemoryDataSize { MDS_UNDEFINED, /* Taille non définie */ + MDS_4_BITS_UNSIGNED, /* Opérande sur 4 bits n.-s. */ MDS_8_BITS_UNSIGNED, /* Opérande sur 8 bits n.-s. */ MDS_16_BITS_UNSIGNED, /* Opérande sur 16 bits n.-s. */ MDS_32_BITS_UNSIGNED, /* Opérande sur 32 bits n.-s. */ MDS_64_BITS_UNSIGNED, /* Opérande sur 64 bits n.-s. */ + MDS_4_BITS_SIGNED, /* Opérande sur 4 bits signés */ MDS_8_BITS_SIGNED, /* Opérande sur 8 bits signés */ MDS_16_BITS_SIGNED, /* Opérande sur 16 bits signés */ MDS_32_BITS_SIGNED, /* Opérande sur 32 bits signés */ @@ -58,6 +60,7 @@ typedef enum _MemoryDataSize } MemoryDataSize; +#define MDS_4_BITS MDS_4_BITS_UNSIGNED #define MDS_8_BITS MDS_8_BITS_UNSIGNED #define MDS_16_BITS MDS_16_BITS_UNSIGNED #define MDS_32_BITS MDS_32_BITS_UNSIGNED diff --git a/src/arch/artificial.c b/src/arch/artificial.c index 16e95bc..65d917e 100644 --- a/src/arch/artificial.c +++ b/src/arch/artificial.c @@ -59,6 +59,9 @@ static const char *g_db_instruction_get_text(const GDbInstruction *, const GExeF /* Informe sur une éventuelle référence à une autre instruction. */ static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *, vmpa_t *); +/* Indique si l'instruction correspond à un retour de fonction. */ +static bool g_db_instruction_is_return(const GDbInstruction *); + /* ---------------------------------------------------------------------------------- */ @@ -108,6 +111,7 @@ static void g_db_instruction_init(GDbInstruction *instr) parent->get_text = (get_instruction_text_fc)g_db_instruction_get_text; parent->get_link = (get_instruction_link_fc)g_db_instruction_get_link; + parent->is_return = (is_instruction_return_fc)g_db_instruction_is_return; } @@ -191,3 +195,22 @@ static InstructionLinkType g_db_instruction_get_link(const GDbInstruction *instr return ILT_NONE; } + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* * +* Description : Indique si l'instruction correspond à un retour de fonction. * +* * +* Retour : true si l'instruction est un 'return' quelconque ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_instruction_is_return(const GDbInstruction *instr) +{ + return false; + +} diff --git a/src/arch/dalvik/Makefile.am b/src/arch/dalvik/Makefile.am new file mode 100644 index 0000000..855d287 --- /dev/null +++ b/src/arch/dalvik/Makefile.am @@ -0,0 +1,27 @@ + +noinst_LTLIBRARIES = libarchdalvik.la + +libarchdalvik_la_SOURCES = \ + instruction.h instruction.c \ + op_const.c \ + op_invoke.c \ + op_mul.c \ + op_nop.c \ + op_ret.c \ + op_sget.c \ + opcodes.h \ + operand.h operand.c \ + processor.h processor.c \ + register.h register.c + +libarchdalvik_la_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS = diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c new file mode 100644 index 0000000..8bd4894 --- /dev/null +++ b/src/arch/dalvik/instruction.c @@ -0,0 +1,286 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions de la VM Dalvik + * + * Copyright (C) 2010 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 "instruction.h" + + +#include "../instruction-int.h" + + + +/* Définition générique d'une instruction d'architecture Dalvik (instance) */ +struct _GDalvikInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + + DalvikOpcodes type; /* Position dans la liste */ + +}; + +/* Définition générique d'une instruction d'architecture Dalvik (classe) */ +struct _GDalvikInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des instructions pour Dalvik. */ +static void g_dalvik_instruction_class_init(GDalvikInstructionClass *); + +/* Initialise une instance d'opérande d'architecture Dalvik. */ +static void g_dalvik_instruction_init(GDalvikInstruction *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions Dalvik */ +typedef struct _dalvik_instruction +{ + bin_t opcode; /* Opcode de l'instruction */ + + const char *keyword; /* Mot clef de la commande */ + +} dalvik_instruction; + + +static dalvik_instruction _instructions[DOP_COUNT] = { + + [DOP_NOP] = { 0x00, "nop" }, + + [DOP_CONST_4] = { 0x12, "const/4" }, + [DOP_CONST_16] = { 0x13, "const/16" }, + + + [DOP_CONST_HIGH16] = { 0x15, "const/high16" }, + + [DOP_CONST_STRING] = { 0x1a, "const-string" }, + + + [DOP_RETURN_VOID] = { 0x0e, "return-void" }, + [DOP_RETURN] = { 0x0f, "return" }, + + + [DOP_SGET] = { 0x60, "sget" }, + [DOP_SGET_WIDE] = { 0x61, "sget-wide" }, + [DOP_SGET_OBJECT] = { 0x62, "sget-object" }, + + + + [DOP_INVOKE_VIRTUAL] = { 0x6e, "invoke-virtual" }, + [DOP_INVOKE_SUPER] = { 0x6f, "invoke-static" }, + [DOP_INVOKE_DIRECT] = { 0x70, "invoke-direct" }, + [DOP_INVOKE_STATIC] = { 0x71, "invoke-static" }, + [DOP_INVOKE_INTERFACE] = { 0x72, "invoke-interface" }, + + + + [DOP_MUL_INT_2ADDR] = { 0xb2, "mul-int/2addr" } + + +}; + + +/* Traduit une instruction en version humainement lisible. */ +static const char *dalvik_get_instruction_text(const GDalvikInstruction *, const GExeFormat *, AsmSyntax); + +/* Informe sur une éventuelle référence à une autre instruction. */ +static InstructionLinkType dalvik_get_instruction_link(const GDalvikInstruction *, vmpa_t *); + +/* Indique si l'instruction correspond à un retour de fonction. */ +static bool dalvik_instruction_is_return(const GDalvikInstruction *); + + + +/* Indique le type défini pour une instruction d'architecture Dalvik. */ +G_DEFINE_TYPE(GDalvikInstruction, g_dalvik_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_instruction_class_init(GDalvikInstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_instruction_init(GDalvikInstruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text; + parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link; + parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'instruction à représenter. * +* * +* Description : Crée une instruction pour l'architecture Dalvik. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_dalvik_instruction_new(DalvikOpcodes type) +{ + GArchInstruction *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_INSTRUCTION, NULL); + + G_DALVIK_INSTRUCTION(result)->type = type; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA MISE EN PLACE D'INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* * +* Description : Recherche l'identifiant de la prochaine instruction. * +* * +* Retour : Identifiant de la prochaine instruction à tenter de charger. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DalvikOpcodes dalvik_guess_next_instruction(const bin_t *data, off_t pos, off_t len) +{ + DalvikOpcodes result; /* Identifiant à retourner */ + bin_t opcode; /* Opcode à trouver */ + + opcode = data[pos]; + + for (result = 0; result < DOP_COUNT; result++) + { + if (_instructions[result].opcode == opcode) + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit une instruction en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *dalvik_get_instruction_text(const GDalvikInstruction *instr, const GExeFormat *format, AsmSyntax syntax) +{ + return _instructions[instr->type].keyword; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* addr = eventuelle adresse associée à faire connaître. [OUT] * +* * +* Description : Informe sur une éventuelle référence à une autre instruction.* +* * +* Retour : Type de lien trouvé ou ILT_NONE si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static InstructionLinkType dalvik_get_instruction_link(const GDalvikInstruction *instr, vmpa_t *addr) +{ + return ILT_NONE/*instr->get_link(instr, addr)*/; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* * +* Description : Indique si l'instruction correspond à un retour de fonction. * +* * +* Retour : true si l'instruction est un 'return' quelconque ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool dalvik_instruction_is_return(const GDalvikInstruction *instr) +{ + return (instr->type == DOP_RETURN_VOID); + +} diff --git a/src/arch/dalvik/instruction.h b/src/arch/dalvik/instruction.h new file mode 100644 index 0000000..2bd77a3 --- /dev/null +++ b/src/arch/dalvik/instruction.h @@ -0,0 +1,98 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions de la VM Dalvik + * + * Copyright (C) 2010 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 _ARCH_DALVIK_INSTRUCTION_H +#define _ARCH_DALVIK_INSTRUCTION_H + + +#include "../instruction.h" + + + + + +/* Enumération de tous les opcodes */ +typedef enum _DalvikOpcodes +{ + DOP_NOP, /* nop (0x00) */ + + DOP_CONST_4, /* const/4 (0x12) */ + DOP_CONST_16, /* const/16 (0x13) */ + + DOP_CONST_HIGH16, /* const/high16 (0x15) */ + + DOP_CONST_STRING, /* const-string (0x1a) */ + + + DOP_RETURN_VOID, /* return-void (0x0e) */ + DOP_RETURN, /* return (0x0f) */ + + + DOP_SGET, /* sget (0x60) */ + DOP_SGET_WIDE, /* sget-wide (0x61) */ + DOP_SGET_OBJECT, /* sget-object (0x62) */ + + + DOP_INVOKE_VIRTUAL, /* invoke-virtual (0x6e) */ + DOP_INVOKE_SUPER, /* invoke-super (0x6f) */ + DOP_INVOKE_DIRECT, /* invoke-direct (0x70) */ + DOP_INVOKE_STATIC, /* invoke-static (0x71) */ + DOP_INVOKE_INTERFACE, /* invoke-interface (0x72) */ + + DOP_MUL_INT_2ADDR, /* mul-int/2addr (0xb2) */ + + DOP_COUNT + +} DalvikOpcodes; + + +#define G_TYPE_DALVIK_INSTRUCTION g_dalvik_instruction_get_type() +#define G_DALVIK_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_instruction_get_type(), GDalvikInstruction)) +#define G_IS_DALVIK_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_instruction_get_type())) +#define G_DALVIK_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_instruction_get_type(), GDalvikInstructionIface)) + + +/* Définition générique d'une instruction d'architecture Dalvik (instance) */ +typedef struct _GDalvikInstruction GDalvikInstruction; + +/* Définition générique d'une instruction d'architecture Dalvik (classe) */ +typedef struct _GDalvikInstructionClass GDalvikInstructionClass; + + +/* Indique le type défini pour une instruction d'architecture Dalvik. */ +GType g_dalvik_instruction_get_type(void); + +/* Crée une instruction pour l'architecture Dalvik. */ +GArchInstruction *g_dalvik_instruction_new(DalvikOpcodes); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Recherche l'identifiant de la prochaine instruction. */ +DalvikOpcodes dalvik_guess_next_instruction(const bin_t *, off_t, off_t); + + + +#endif /* _ARCH_DALVIK_INSTRUCTION_H */ diff --git a/src/arch/dalvik/op_const.c b/src/arch/dalvik/op_const.c new file mode 100644 index 0000000..e8c720e --- /dev/null +++ b/src/arch/dalvik/op_const.c @@ -0,0 +1,173 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_const.c - décodage des chargements de constantes + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'const/16'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_const_16(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_CONST_16); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21S)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'const/4'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_const_4(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_CONST_4); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_11N)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'const/high16'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_const_high16(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_CONST_HIGH16); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21H)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'const-string'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_const_string(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_CONST_STRING); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21C | DALVIK_OP_POOL(DPT_STRING))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/op_invoke.c b/src/arch/dalvik/op_invoke.c new file mode 100644 index 0000000..913fb1a --- /dev/null +++ b/src/arch/dalvik/op_invoke.c @@ -0,0 +1,209 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_invoke.c - décodage des appels de méthode + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'invoke-direct'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_invoke_direct(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_INVOKE_DIRECT); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_35C | DALVIK_OP_POOL(DPT_METHOD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'invoke-interface'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_invoke_interface(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_INVOKE_INTERFACE); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_35C | DALVIK_OP_POOL(DPT_METHOD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'invoke-static'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_invoke_static(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_INVOKE_STATIC); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_35C | DALVIK_OP_POOL(DPT_METHOD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'invoke-super'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_invoke_super(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_INVOKE_SUPER); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_35C | DALVIK_OP_POOL(DPT_METHOD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'invoke-virtual'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_invoke_virtual(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_INVOKE_VIRTUAL); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_35C | DALVIK_OP_POOL(DPT_METHOD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/op_mul.c b/src/arch/dalvik/op_mul.c new file mode 100644 index 0000000..1e2b584 --- /dev/null +++ b/src/arch/dalvik/op_mul.c @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_mul.c - décodage des opérations de multiplications + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'mul-int/2addr'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_mul_int_2addr(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_MUL_INT_2ADDR); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_12X)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/op_nop.c b/src/arch/dalvik/op_nop.c new file mode 100644 index 0000000..39f37d9 --- /dev/null +++ b/src/arch/dalvik/op_nop.c @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_ret.c - décodage de l'instruction nulle + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'nop'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_nop(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_NOP); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_10X)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/op_ret.c b/src/arch/dalvik/op_ret.c new file mode 100644 index 0000000..baba5e3 --- /dev/null +++ b/src/arch/dalvik/op_ret.c @@ -0,0 +1,101 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_ret.c - décodage des ordres de retour + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'return'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_return(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_RETURN); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_11X)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'return-void'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_return_void(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_RETURN_VOID); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_10X)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/op_sget.c b/src/arch/dalvik/op_sget.c new file mode 100644 index 0000000..6b44700 --- /dev/null +++ b/src/arch/dalvik/op_sget.c @@ -0,0 +1,137 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_sget.c - décodage des chargements de champs statiques + * + * Copyright (C) 2010 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 "opcodes.h" + + +#include "instruction.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sget'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_sget(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_SGET); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21C | DALVIK_OP_POOL(DPT_FIELD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sget-object'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_sget_object(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_SGET_OBJECT); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21C | DALVIK_OP_POOL(DPT_FIELD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sget-wide'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *dalvik_read_instr_sget_wide(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GDalvikProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + SourceEndian endian; /* Boutisme lié au binaire */ + + result = g_dalvik_instruction_new(DOP_SGET_WIDE); + + endian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc)); + + if (!dalvik_read_operands(result, data, pos, len, endian, DALVIK_OPT_21C | DALVIK_OP_POOL(DPT_FIELD))) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + return result; + +} diff --git a/src/arch/dalvik/opcodes.h b/src/arch/dalvik/opcodes.h new file mode 100644 index 0000000..3a90d6f --- /dev/null +++ b/src/arch/dalvik/opcodes.h @@ -0,0 +1,110 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * opcodes.h - prototypes pour la liste de tous les opcodes de l'architecture Dalvik + * + * Copyright (C) 2010 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 _ARCH_DALVIK_OPCODES_H +#define _ARCH_DALVIK_OPCODES_H + + +#include "instruction.h" +#include "processor.h" + + + +/* Prototype de décodage d'une instruction Dalvik. */ +typedef GArchInstruction * (* dalvik_read_instr) (const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +/* Décode une instruction de type 'nop'. */ +GArchInstruction *dalvik_read_instr_nop(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +/* Décode une instruction de type 'const/16'. */ +GArchInstruction *dalvik_read_instr_const_16(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'const/4'. */ +GArchInstruction *dalvik_read_instr_const_4(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + + +/* Décode une instruction de type 'const/high16'. */ +GArchInstruction *dalvik_read_instr_const_high16(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + + +/* Décode une instruction de type 'const-string'. */ +GArchInstruction *dalvik_read_instr_const_string(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + + + + + + + +/* Décode une instruction de type 'sget'. */ +GArchInstruction *dalvik_read_instr_sget(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'sget-object'. */ +GArchInstruction *dalvik_read_instr_sget_object(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'sget-wide'. */ +GArchInstruction *dalvik_read_instr_sget_wide(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +/* Décode une instruction de type 'invoke-direct'. */ +GArchInstruction *dalvik_read_instr_invoke_direct(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'invoke-interface'. */ +GArchInstruction *dalvik_read_instr_invoke_interface(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'invoke-static'. */ +GArchInstruction *dalvik_read_instr_invoke_static(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'invoke-super'. */ +GArchInstruction *dalvik_read_instr_invoke_super(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'invoke-virtual'. */ +GArchInstruction *dalvik_read_instr_invoke_virtual(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +/* Décode une instruction de type 'mul-int/2addr'. */ +GArchInstruction *dalvik_read_instr_mul_int_2addr(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +/* Décode une instruction de type 'return'. */ +GArchInstruction *dalvik_read_instr_return(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + +/* Décode une instruction de type 'return-void'. */ +GArchInstruction *dalvik_read_instr_return_void(const bin_t *, off_t *, off_t, vmpa_t, const GDalvikProcessor *); + + + +#endif /* _ARCH_DALVIK_OPCODES_H */ diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c new file mode 100644 index 0000000..cc36cb5 --- /dev/null +++ b/src/arch/dalvik/operand.c @@ -0,0 +1,1127 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * operand.c - gestion des operandes de l'architecture Dalvik + * + * Copyright (C) 2010 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 "operand.h" + + +#include <malloc.h> + + +#include "register.h" +#include "../immediate.h" +#include "../operand-int.h" + + + +/* ----------------------- COQUILLE VIDE POUR OPERANDE DALVIK ----------------------- */ + + +/* Définition d'un opérande de Dalvik (instance) */ +struct _GDalvikOperand +{ + GArchOperand parent; /* Instance parente */ + +}; + + +/* Définition d'un opérande de Dalvik (classe) */ +struct _GDalvikOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes Dalvik de base. */ +static void g_dalvik_operand_class_init(GDalvikOperandClass *); + +/* Initialise une instance d'opérande de base pour Dalvik. */ +static void g_dalvik_operand_init(GDalvikOperand *); + + + +/* --------------------- OPERANDES VISANT UN REGISTRE DE DALVIK --------------------- */ + + +/* Définition d'un opérande visant un registre Dalvik (instance) */ +struct _GDalvikRegisterOperand +{ + GDalvikOperand parent; /* Instance parente */ + + GDalvikRegister *reg; /* Registre représenté */ + +}; + + +/* Définition d'un opérande visant un registre Dalvik (classe) */ +struct _GDalvikRegisterOperandClass +{ + GDalvikOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de registre Dalvik. */ +static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *); + +/* Initialise une instance d'opérande de registre Dalvik. */ +static void g_dalvik_register_operand_init(GDalvikRegisterOperand *); + +/* Ajoute du texte simple à un fichier ouvert en écriture. */ +static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *, GRenderingOptions *, MainRendering, FILE *); + +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +static void g_dalvik_register_operand_to_buffer(const GDalvikRegisterOperand *, GBufferLine *, GRenderingOptions *); + + + +/* -------------------- LISTE D'OPERANDES RASSEMBLES EN ARGUMENT -------------------- */ + + + +/* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */ +struct _GDalvikArgsOperand +{ + GDalvikOperand parent; /* Instance parente */ + + GArchOperand **args; /* Liste d'arguments */ + size_t count; /* Taille de cette liste */ + +}; + + +/* Définition d'un opérande visant une liste d'opérandes Dalvik (classe) */ +struct _GDalvikArgsOperandClass +{ + GDalvikOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des listes d'opérandes Dalvik. */ +static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *); + +/* Initialise une instance de liste d'opérandes Dalvik. */ +static void g_dalvik_args_operand_init(GDalvikArgsOperand *); + +/* Ajoute du texte simple à un fichier ouvert en écriture. */ +static void g_dalvik_args_operand_add_text(const GDalvikArgsOperand *, GRenderingOptions *, MainRendering, FILE *); + +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +static void g_dalvik_args_operand_to_buffer(const GDalvikArgsOperand *, GBufferLine *, GRenderingOptions *); + + + +/* ----------------- OPERANDES POINTANT VERS LA TABLE DE CONSTANTES ----------------- */ + + +/* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */ +struct _GDalvikPoolOperand +{ + GDalvikOperand parent; /* Instance parente */ + + DalvikPoolType type; /* Type de table visée */ + uint32_t index; /* Indice de l'élément visé */ + +}; + + +/* Définition d'un opérande visant un élément de table de constantes Dalvik (classe) */ +struct _GDalvikPoolOperandClass +{ + GDalvikOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de constante Dalvik. */ +static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *); + +/* Initialise une instance d'opérande de constante Dalvik. */ +static void g_dalvik_pool_operand_init(GDalvikPoolOperand *); + +/* Ajoute du texte simple à un fichier ouvert en écriture. */ +static void g_dalvik_pool_operand_add_text(const GDalvikPoolOperand *, GRenderingOptions *, MainRendering, FILE *); + +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +static void g_dalvik_pool_operand_to_buffer(const GDalvikPoolOperand *, GBufferLine *, GRenderingOptions *); + + + +/* ------------------------- AIDE A LA CREATION D'OPERANDES ------------------------- */ + + +/* Liste de tous les types d'opérandes */ +typedef enum _DalvikOperandID +{ + DOI_INVALID, + + DOI_REGISTER_4, + DOI_REGISTER_8, + + DOI_IMMEDIATE_4, + DOI_IMMEDIATE_16, + DOI_IMMEDIATE_H16, + + DOI_POOL_CONST + + +} DalvikOperandID; + + +/* Procède à la lecture d'opérandes pour une instruction. */ +static bool dalvik_read_basic_operands(GArchInstruction *, const bin_t *, off_t *, off_t, bool *, SourceEndian, DalvikOperandType); + +/* Procède à la lecture d'opérandes pour une instruction. */ +static bool dalvik_read_fixed_operands(GArchInstruction *, const bin_t *, off_t *, off_t, bool *, SourceEndian, DalvikOperandType); + + + +/* ---------------------------------------------------------------------------------- */ +/* COQUILLE VIDE POUR OPERANDE DALVIK */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de Dalvik. */ +G_DEFINE_TYPE(GDalvikOperand, g_dalvik_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes Dalvik de base. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_operand_class_init(GDalvikOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de base pour Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_operand_init(GDalvikOperand *operand) +{ + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES VISANT UN REGISTRE DE DALVIK */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ +G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_DALVIK_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de registre Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de registre Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand) +{ + GContentExporter *parent; /* Instance parente */ + + parent = G_CONTENT_EXPORTER(operand); + + parent->add_text = (add_text_fc)g_dalvik_register_operand_add_text; + parent->export_buffer = (export_buffer_fc)g_dalvik_register_operand_to_buffer; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * +* size = taille de l'opérande, et donc du registre. * +* endian = ordre des bits dans la source. * +* * +* Description : Crée un opérande visant un registre Dalvik. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_dalvik_register_operand_new(const bin_t *data, off_t *pos, off_t len, bool *low, MemoryDataSize size, SourceEndian endian) +{ + GDalvikRegisterOperand *result; /* Structure à retourner */ + uint8_t index8; /* Indice sur 8 bits */ + uint16_t index16; /* Indice sur 16 bits */ + bool test; /* Bilan de lecture */ + + switch (size) + { + case MDS_4_BITS: + test = read_u4(&index8, data, pos, len, low, endian); + break; + case MDS_8_BITS: + test = read_u8(&index8, data, pos, len, endian); + break; + case MDS_16_BITS: + test = read_u16(&index16, data, pos, len, endian); + break; + default: + test = false; + break; + } + + if (!test) + return NULL; + + result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL); + + switch (size) + { + case MDS_4_BITS: + case MDS_8_BITS: + result->reg = g_dalvik_register_new(index8); + break; + case MDS_16_BITS: + result->reg = g_dalvik_register_new(index16); + break; + default: + break; + } + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* options = options de rendu. * +* rendering = support effectif final des lignes de code. * +* stream = flux ouvert en écriture. * +* * +* Description : Ajoute du texte simple à un fichier ouvert en écriture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_operand_add_text(const GDalvikRegisterOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream) +{ + g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->reg), options, rendering, stream); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* buffer = espace où placer ledit contenu. * +* options = options de rendu. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_operand_to_buffer(const GDalvikRegisterOperand *operand, GBufferLine *buffer, GRenderingOptions *options) +{ + g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->reg), buffer, options); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* LISTE D'OPERANDES RASSEMBLES EN ARGUMENT */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */ +G_DEFINE_TYPE(GDalvikArgsOperand, g_dalvik_args_operand, G_TYPE_DALVIK_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des listes d'opérandes Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance de liste d'opérandes Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_args_operand_init(GDalvikArgsOperand *operand) +{ + GContentExporter *parent; /* Instance parente */ + + parent = G_CONTENT_EXPORTER(operand); + + parent->add_text = (add_text_fc)g_dalvik_args_operand_add_text; + parent->export_buffer = (export_buffer_fc)g_dalvik_args_operand_to_buffer; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un réceptacle pour opérandes Dalvik servant d'arguments.* +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_dalvik_args_operand_new(void) +{ + GDalvikArgsOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_ARGS_OPERAND, NULL); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à compléter. * +* arg = nouvel argument pour un appel. * +* * +* Description : Ajoute un élément à la liste d'arguments Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg) +{ + operand->args = (GArchOperand **)realloc(operand->args, ++operand->count * sizeof(GArchOperand *)); + + operand->args[operand->count - 1] = arg; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* options = options de rendu. * +* rendering = support effectif final des lignes de code. * +* stream = flux ouvert en écriture. * +* * +* Description : Ajoute du texte simple à un fichier ouvert en écriture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_args_operand_add_text(const GDalvikArgsOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream) +{ + GContentExporter *exporter; /* Autre vision de l'objet */ + size_t i; /* Boucle de parcours */ + + exporter = G_CONTENT_EXPORTER(operand); + + g_content_exporter_insert_text(exporter, stream, "{", 1, RTT_HOOK); + + if (operand->count > 0) + { + g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->args[0]), + options, rendering, stream); + + for (i = 1; i < operand->count; i++) + { + g_content_exporter_insert_text(exporter, stream, ",", 1, RTT_NONE/* FIXME */); + + g_content_exporter_insert_text(exporter, stream, " ", 1, RTT_NONE); + + g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->args[i]), + options, rendering, stream); + + } + + } + + g_content_exporter_insert_text(exporter, stream, "}", 1, RTT_HOOK); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* buffer = espace où placer ledit contenu. * +* options = options de rendu. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_args_operand_to_buffer(const GDalvikArgsOperand *operand, GBufferLine *buffer, GRenderingOptions *options) +{ + GContentExporter *exporter; /* Autre vision de l'objet */ + size_t i; /* Boucle de parcours */ + + exporter = G_CONTENT_EXPORTER(operand); + + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "{", 1, RTT_HOOK); + + if (operand->count > 0) + { + g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->args[0]), buffer, options); + + for (i = 1; i < operand->count; i++) + { + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + ",", 1, RTT_NONE/* FIXME */); + + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + " ", 1, RTT_NONE); + + g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->args[i]), buffer, options); + + } + + } + + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "}", 1, RTT_HOOK); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES POINTANT VERS LA TABLE DE CONSTANTES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */ +G_DEFINE_TYPE(GDalvikPoolOperand, g_dalvik_pool_operand, G_TYPE_DALVIK_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de constante Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de constante Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_pool_operand_init(GDalvikPoolOperand *operand) +{ + GContentExporter *parent; /* Instance parente */ + + parent = G_CONTENT_EXPORTER(operand); + + parent->add_text = (add_text_fc)g_dalvik_pool_operand_add_text; + parent->export_buffer = (export_buffer_fc)g_dalvik_pool_operand_to_buffer; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de table visée avec la référence. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* size = taille de l'opérande, et donc du registre. * +* endian = ordre des bits dans la source. * +* * +* Description : Crée un opérande visant un élément constant Dalvik. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_dalvik_pool_operand_new(DalvikPoolType type, const bin_t *data, off_t *pos, off_t len, MemoryDataSize size, SourceEndian endian) +{ + GDalvikPoolOperand *result; /* Structure à retourner */ + uint8_t index8; /* Indice sur 8 bits */ + uint16_t index16; /* Indice sur 16 bits */ + bool test; /* Bilan de lecture */ + + switch (size) + { + case MDS_8_BITS: + test = read_u8(&index8, data, pos, len, endian); + break; + case MDS_16_BITS: + test = read_u16(&index16, data, pos, len, endian); + break; + default: + test = false; + break; + } + + if (!test) + return NULL; + + result = g_object_new(G_TYPE_DALVIK_POOL_OPERAND, NULL); + + result->type = type; + result->index = (size == MDS_8_BITS ? index8 : index16); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* options = options de rendu. * +* rendering = support effectif final des lignes de code. * +* stream = flux ouvert en écriture. * +* * +* Description : Ajoute du texte simple à un fichier ouvert en écriture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_pool_operand_add_text(const GDalvikPoolOperand *operand, GRenderingOptions *options, MainRendering rendering, FILE *stream) +{ + //g_content_exporter_add_text(G_CONTENT_EXPORTER(operand->reg), options, rendering, stream); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* buffer = espace où placer ledit contenu. * +* options = options de rendu. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_pool_operand_to_buffer(const GDalvikPoolOperand *operand, GBufferLine *buffer, GRenderingOptions *options) +{ + GContentExporter *exporter; /* Autre vision de l'opérande */ + + char value[20]; /* Chaîne à imprimer */ + size_t len; /* Taille de l'élément inséré */ + + + + + exporter = G_CONTENT_EXPORTER(operand); + + switch (operand->type) + { + case DPT_NONE: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "????", 4, RTT_SECTION); + break; + case DPT_STRING: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "string", 6, RTT_SECTION); + break; + case DPT_TYPE: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "type", 4, RTT_SECTION); + break; + case DPT_PROTO: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "proto", 5, RTT_SECTION); + break; + case DPT_FIELD: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "field", 5, RTT_SECTION); + break; + case DPT_METHOD: + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "method", 6, RTT_SECTION); + break; + } + + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + "@", 1, RTT_SIGNS); + + + //g_content_exporter_to_buffer(G_CONTENT_EXPORTER(operand->reg), buffer, options); + + len = snprintf(value, 20, "%d", operand->index); + /* + strcpy(value, "12345"); + + len = 5; + */ + g_content_exporter_insert_into_buffer(exporter, buffer, BLC_ASSEMBLY, + value, len, RTT_IMMEDIATE); + +} + + + + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA CREATION D'OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont la définition est incomplète. [OUT]* +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = boutisme lié au binaire accompagnant. * +* model = type d'opérandes attendues. * +* * +* Description : Procède à la lecture d'opérandes pour une instruction. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool dalvik_read_basic_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian, DalvikOperandType model) +{ + bool result; /* Bilan à retourner */ + DalvikOperandID *types; /* Liste des chargements */ + DalvikOperandID *iter; /* Boucle de parcours */ + GArchOperand *op; /* Opérande unique décodé */ + uint16_t value16; /* Valeur sur 16 bits */ + + result = true; + + /* Choix des opérandes à charger */ + + switch (model & ~DALVIK_OP_POOL_MASK) + { + case DALVIK_OPT_12X: + types = (DalvikOperandID []) { + DOI_REGISTER_4, + DOI_REGISTER_4, + DOI_INVALID + }; + break; + + case DALVIK_OPT_11N: + types = (DalvikOperandID []) { + DOI_REGISTER_4, + DOI_IMMEDIATE_4, + DOI_INVALID + }; + break; + + case DALVIK_OPT_11X: + types = (DalvikOperandID []) { + DOI_REGISTER_8, + DOI_INVALID + }; + break; + + case DALVIK_OPT_21C: + types = (DalvikOperandID []) { + DOI_REGISTER_8, + DOI_POOL_CONST, + DOI_INVALID + }; + break; + + case DALVIK_OPT_21H: + types = (DalvikOperandID []) { + DOI_REGISTER_8, + DOI_IMMEDIATE_H16, + DOI_INVALID + }; + break; + + case DALVIK_OPT_21S: + types = (DalvikOperandID []) { + DOI_REGISTER_8, + DOI_IMMEDIATE_16, + DOI_INVALID + }; + break; + + default: + types = (DalvikOperandID []) { + DOI_INVALID + }; + break; + + } + + /* Chargement des opérandes */ + + for (iter = types; *iter != G_TYPE_INVALID && result; iter++) + { + switch (*iter) + { + case DOI_REGISTER_4: + op = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian); + break; + + case DOI_REGISTER_8: + op = g_dalvik_register_operand_new(data, pos, len, NULL, MDS_8_BITS, endian); + break; + + case DOI_IMMEDIATE_4: + op = _g_imm_operand_new_from_data(MDS_4_BITS, data, pos, len, low, endian); + break; + + case DOI_IMMEDIATE_16: + op = g_imm_operand_new_from_data(MDS_16_BITS, data, pos, len, endian); + break; + + case DOI_IMMEDIATE_H16: + result = read_u16(&value16, data, pos, len, endian); + if (result) + op = g_imm_operand_new_from_value(MDS_32_BITS_SIGNED, ((uint32_t)value16) << 16); + break; + + case DOI_POOL_CONST: + op = g_dalvik_pool_operand_new(DALVIK_OP_GET_POOL(model), data, pos, len, MDS_16_BITS, endian); + break; + + default: + op = NULL; + break; + + } + + if (op == NULL) result = false; + else g_arch_instruction_attach_extra_operand(instr, op); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont la définition est incomplète. [OUT]* +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = boutisme lié au binaire accompagnant. * +* model = type d'opérandes attendues. * +* * +* Description : Procède à la lecture d'opérandes pour une instruction. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool dalvik_read_fixed_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian, DalvikOperandType model) +{ + GArchOperand *opa; /* Opérande vA décodé */ + uint8_t b; /* Nbre. de registres utilisés */ + GArchOperand *target1; /* Opérande visant la table #1 */ + GArchOperand *target2; /* Opérande visant la table #2 */ + GArchOperand *args; /* Liste des opérandes */ + uint8_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande unique décodé */ + + + + opa = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian); + + if (!read_u4(&b, data, pos, len, low, endian)) + goto err_va; + + + target1 = g_dalvik_pool_operand_new(DALVIK_OP_GET_POOL(model), data, pos, len, MDS_16_BITS, endian); + if (target1 == NULL) goto err_target1; + + + + target2 = NULL; + + if (0) + { + if (target2 == NULL) goto err_target2; + } + + + args = g_dalvik_args_operand_new(); + g_arch_instruction_attach_extra_operand(instr, args); + + + /* Mise en place des arguments */ + + for (i = 0; i < MIN(b, 4); i++) + { + op = g_dalvik_register_operand_new(data, pos, len, low, MDS_4_BITS, endian); + if (op == NULL) goto err_registers; + + g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op); + + } + + /* Rajout des éléments finaux déjà chargés */ + + if (b < 5) g_object_unref(G_OBJECT(opa)); + else g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), opa); + + g_arch_instruction_attach_extra_operand(instr, target1); + + if (target2 != NULL) + g_arch_instruction_attach_extra_operand(instr, target2); + + return true; + + err_registers: + + if (target2 != NULL) + g_object_unref(G_OBJECT(target2)); + + err_target2: + + g_object_unref(G_OBJECT(target1)); + + err_target1: + + g_object_unref(G_OBJECT(opa)); + + err_va: + + return false; + +} + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont la définition est incomplète. [OUT]* +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* endian = boutisme lié au binaire accompagnant. * +* model = type d'opérandes attendues. * +* * +* Description : Procède à la lecture d'opérandes pour une instruction. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dalvik_read_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, SourceEndian endian, DalvikOperandType model) +{ + bool result; /* Bilan à retourner */ + + + bool low; + + off_t old_pos; + + off_t length; + + result = true; + + + old_pos = *pos; + + + low = true; + + + + switch (model & ~DALVIK_OP_POOL_MASK) + { + case DALVIK_OPT_12X: + case DALVIK_OPT_11N: + case DALVIK_OPT_11X: + case DALVIK_OPT_21C: + case DALVIK_OPT_21H: + case DALVIK_OPT_21S: + result = dalvik_read_basic_operands(instr, data, pos, len, &low, endian, model); + break; + + case DALVIK_OPT_35C: + result = dalvik_read_fixed_operands(instr, data, pos, len, &low, endian, model); + break; + + default: + break; + + } + + + + *pos = old_pos; + + + + if (*pos < len) + { + (*pos)++; + + length = DALVIK_OP_GET_LEN(model); + + if (length > 1) + *pos += (length - 1) * sizeof(uint16_t); + + } + + + + + return result; + +} diff --git a/src/arch/dalvik/operand.h b/src/arch/dalvik/operand.h new file mode 100644 index 0000000..da14aa3 --- /dev/null +++ b/src/arch/dalvik/operand.h @@ -0,0 +1,207 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * operand.h - prototypes pour la gestion des operandes de l'architecture Dalvik + * + * Copyright (C) 2010 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 _ARCH_DALVIK_OPERAND_H +#define _ARCH_DALVIK_OPERAND_H + + +#include "../instruction.h" +#include "../../common/endianness.h" + + + +/* ----------------------- COQUILLE VIDE POUR OPERANDE DALVIK ----------------------- */ + + +#define G_TYPE_DALVIK_OPERAND g_dalvik_operand_get_type() +#define G_DALVIK_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_operand_get_type(), GDalvikOperand)) +#define G_IS_DALVIK_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_operand_get_type())) +#define G_DALVIK_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_operand_get_type(), GDalvikOperandIface)) + + +/* Définition d'un opérande de Dalvik (instance) */ +typedef struct _GDalvikOperand GDalvikOperand; + +/* Définition d'un opérande de Dalvik (classe) */ +typedef struct _GDalvikOperandClass GDalvikOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de Dalvik. */ +GType g_dalvik_operand_get_type(void); + + + +/* --------------------- OPERANDES VISANT UN REGISTRE DE DALVIK --------------------- */ + + +#define G_TYPE_DALVIK_REGISTER_OPERAND g_dalvik_register_operand_get_type() +#define G_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_register_operand_get_type(), GDalvikRegisterOperand)) +#define G_IS_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_register_operand_get_type())) +#define G_DALVIK_REGISTER_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_register_operand_get_type(), GDalvikRegisterOperandIface)) + + +/* Définition d'un opérande visant un registre Dalvik (instance) */ +typedef struct _GDalvikRegisterOperand GDalvikRegisterOperand; + +/* Définition d'un opérande visant un registre Dalvik (classe) */ +typedef struct _GDalvikRegisterOperandClass GDalvikRegisterOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ +GType g_dalvik_register_operand_get_type(void); + +/* Crée un opérande visant un registre Dalvik. */ +GArchOperand *g_dalvik_register_operand_new(const bin_t *, off_t *, off_t, bool *, MemoryDataSize, SourceEndian); + + + +/* -------------------- LISTE D'OPERANDES RASSEMBLES EN ARGUMENT -------------------- */ + + +#define G_TYPE_DALVIK_ARGS_OPERAND g_dalvik_args_operand_get_type() +#define G_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_args_operand_get_type(), GDalvikArgsOperand)) +#define G_IS_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_args_operand_get_type())) +#define G_DALVIK_ARGS_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_args_operand_get_type(), GDalvikArgsOperandIface)) + + +/* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */ +typedef struct _GDalvikArgsOperand GDalvikArgsOperand; + +/* Définition d'un opérande visant une liste d'opérandes Dalvik (classe) */ +typedef struct _GDalvikArgsOperandClass GDalvikArgsOperandClass; + + +/* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */ +GType g_dalvik_args_operand_get_type(void); + +/* Crée un réceptacle pour opérandes Dalvik servant d'arguments. */ +GArchOperand *g_dalvik_args_operand_new(void); + +/* Ajoute un élément à la liste d'arguments Dalvik. */ +void g_dalvik_args_operand_add(GDalvikArgsOperand *, GArchOperand *); + + + +/* ----------------- OPERANDES POINTANT VERS LA TABLE DE CONSTANTES ----------------- */ + + + +#define G_TYPE_DALVIK_POOL_OPERAND g_dalvik_pool_operand_get_type() +#define G_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_pool_operand_get_type(), GDalvikPoolOperand)) +#define G_IS_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_pool_operand_get_type())) +#define G_DALVIK_POOL_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_pool_operand_get_type(), GDalvikPoolOperandIface)) + + +/* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */ +typedef struct _GDalvikPoolOperand GDalvikPoolOperand; + +/* Définition d'un opérande visant un élément de table de constantes Dalvik (classe) */ +typedef struct _GDalvikPoolOperandClass GDalvikPoolOperandClass; + + +/* Type de table de constantes */ +typedef enum _DalvikPoolType +{ + DPT_NONE = 0x0, + DPT_STRING = 0x1, + DPT_TYPE = 0x2, + DPT_PROTO = 0x3, + DPT_FIELD = 0x4, + DPT_METHOD = 0x5 + +} DalvikPoolType; + + +/* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */ +GType g_dalvik_pool_operand_get_type(void); + +/* Crée un opérande visant un élément constant Dalvik. */ +GArchOperand *g_dalvik_pool_operand_new(DalvikPoolType, const bin_t *, off_t *, off_t, MemoryDataSize, SourceEndian); + + + + + + + +/* ------------------------- AIDE A LA CREATION D'OPERANDES ------------------------- */ + + +/** + * Cf. les documentations suivantes : + * - http://www.netmite.com/android/mydroid/dalvik/docs/instruction-formats.html + * - http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html + * - http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html + */ + + +/* Construction d'identifiants typés */ + +#define DALVIK_OP_LEN_OFF 28 +#define DALVIK_OP_LEN_MASK 0xf0000000 + +#define DALVIK_OP_REG_OFF 24 +#define DALVIK_OP_REG_MASK 0x0f000000 + +#define DALVIK_OP_POOL_OFF 20 +#define DALVIK_OP_POOL_MASK 0x00f00000 + +#define DALVIK_OP_LEN(l) ((l) << DALVIK_OP_LEN_OFF) +#define DALVIK_OP_GET_LEN(v) (((v) & DALVIK_OP_LEN_MASK) >> DALVIK_OP_LEN_OFF) + +#define DALVIK_OP_REG(r) ((r) << DALVIK_OP_REG_OFF) +#define DALVIK_OP_COUNT_REG(v) (((v) & DALVIK_OP_REG_MASK) >> DALVIK_OP_REG_OFF) + +#define DALVIK_OP_POOL(p) ((p) << DALVIK_OP_POOL_OFF) +#define DALVIK_OP_GET_POOL(v) (((v) & DALVIK_OP_POOL_MASK) >> DALVIK_OP_POOL_OFF) + + +/* Types d'opérandes supportés */ +typedef enum _DalvikOperandType +{ + DALVIK_OPT_10X = DALVIK_OP_LEN(1) | DALVIK_OP_REG(0) | 'X', + + DALVIK_OPT_11N = DALVIK_OP_LEN(1) | DALVIK_OP_REG(1) | 'N', + DALVIK_OPT_11X = DALVIK_OP_LEN(1) | DALVIK_OP_REG(1) | 'X', + + DALVIK_OPT_12X = DALVIK_OP_LEN(1) | DALVIK_OP_REG(2) | 'X', + + DALVIK_OPT_21C = DALVIK_OP_LEN(2) | DALVIK_OP_REG(1) | 'C', + + DALVIK_OPT_21H = DALVIK_OP_LEN(2) | DALVIK_OP_REG(1) | 'H', + + DALVIK_OPT_21S = DALVIK_OP_LEN(2) | DALVIK_OP_REG(1) | 'S', + + + DALVIK_OPT_35C = DALVIK_OP_LEN(3) | DALVIK_OP_REG(5) | 'C' + + +} DalvikOperandType; + + +/* Procède à la lecture d'opérandes pour une instruction. */ +bool dalvik_read_operands(GArchInstruction *, const bin_t *, off_t *, off_t, SourceEndian, DalvikOperandType); + + + +#endif /* _ARCH_DALVIK_OPERAND_H */ diff --git a/src/arch/dalvik/processor.c b/src/arch/dalvik/processor.c new file mode 100644 index 0000000..7bf469e --- /dev/null +++ b/src/arch/dalvik/processor.c @@ -0,0 +1,198 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * processor.c - manipulation du processeur de la VM Dalvik + * + * Copyright (C) 2010 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 "processor.h" + + +#include "instruction.h" +#include "opcodes.h" +#include "../processor-int.h" + + + +/* Définition du processeur de la VM Dalvik (instance) */ +struct _GDalvikProcessor +{ + GArchProcessor parent; /* Instance parente */ + +}; + + +/* Définition du processeur de la VM Dalvik (classe) */ +struct _GDalvikProcessorClass +{ + GArchProcessorClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des processeurs de VM Dalvik. */ +static void g_dalvik_processor_class_init(GDalvikProcessorClass *); + +/* Initialise une instance de processeur de VM Dalvik. */ +static void g_dalvik_processor_init(GDalvikProcessor *); + +/* Décode une instruction dans un flux de données. */ +static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *, const bin_t *, off_t *, off_t, vmpa_t); + + +/* Indique le type défini par la GLib pour le processeur DALVIK. */ +G_DEFINE_TYPE(GDalvikProcessor, g_dalvik_processor, G_TYPE_ARCH_PROCESSOR); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des processeurs de VM Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_processor_class_init(GDalvikProcessorClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : proc = instance à initialiser. * +* * +* Description : Initialise une instance de processeur de VM Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_processor_init(GDalvikProcessor *proc) +{ + GArchProcessor *parent; /* Instance parente */ + + parent = G_ARCH_PROCESSOR(proc); + + parent->endianness = SRE_LITTLE; + parent->memsize = MDS_32_BITS; + + parent->decode = (decode_instruction_fc)g_dalvik_processor_decode_instruction; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée le support de l'architecture Dalvik. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchProcessor *g_dalvik_processor_new(void) +{ + GArchProcessor *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_PROCESSOR, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la procédure. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* * +* Description : Décode une instruction dans un flux de données. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction *g_dalvik_processor_decode_instruction(const GDalvikProcessor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) +{ + GArchInstruction *result; /* Instruction à renvoyer */ + DalvikOpcodes id; /* Identifiant d'instruction */ + + static const dalvik_read_instr decodings[DOP_COUNT] = { + + [DOP_NOP] = dalvik_read_instr_nop, + + + [DOP_CONST_4] = dalvik_read_instr_const_4, + [DOP_CONST_16] = dalvik_read_instr_const_16, + + + [DOP_CONST_HIGH16] = dalvik_read_instr_const_high16, + + + [DOP_CONST_STRING] = dalvik_read_instr_const_string, + + + + [DOP_RETURN_VOID] = dalvik_read_instr_return_void, + [DOP_RETURN] = dalvik_read_instr_return, + + + [DOP_SGET] = dalvik_read_instr_sget, + [DOP_SGET_WIDE] = dalvik_read_instr_sget_wide, + [DOP_SGET_OBJECT] = dalvik_read_instr_sget_object, + + + [DOP_INVOKE_VIRTUAL] = dalvik_read_instr_invoke_virtual, + [DOP_INVOKE_SUPER] = dalvik_read_instr_invoke_super, + [DOP_INVOKE_DIRECT] = dalvik_read_instr_invoke_direct, + [DOP_INVOKE_STATIC] = dalvik_read_instr_invoke_static, + [DOP_INVOKE_INTERFACE] = dalvik_read_instr_invoke_interface, + + + [DOP_MUL_INT_2ADDR] = dalvik_read_instr_mul_int_2addr + + + }; + + id = dalvik_guess_next_instruction(data, *pos, len); + + if (id != DOP_COUNT) (*pos)++; + + if (id == DOP_COUNT) result = NULL; + else result = decodings[id](data, pos, len, addr, proc); + + return result; + +} diff --git a/src/arch/dalvik/processor.h b/src/arch/dalvik/processor.h new file mode 100644 index 0000000..d972d73 --- /dev/null +++ b/src/arch/dalvik/processor.h @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * processor.h - prototypes pour la manipulation du processeur de la VM Dalvik + * + * Copyright (C) 2010 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 _ARCH_DALVIK_PROCESSOR_H +#define _ARCH_DALVIK_PROCESSOR_H + + +#include "../processor.h" + + + +#define G_TYPE_DALVIK_PROCESSOR g_dalvik_processor_get_type() +#define G_DALVIK_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_processor_get_type(), GDalvikProcessor)) +#define G_IS_DALVIK_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_processor_get_type())) +#define G_DALVIK_PROCESSOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_processor_get_type(), GDalvikProcessorIface)) + + +/* Définition du processeur de la VM Dalvik (instance) */ +typedef struct _GDalvikProcessor GDalvikProcessor; + +/* Définition du processeur de la VM Dalvik (classe) */ +typedef struct _GDalvikProcessorClass GDalvikProcessorClass; + + +/* Indique le type défini par la GLib pour le processeur Dalvik. */ +GType g_dalvik_processor_get_type(void); + +/* Crée le support de l'architecture Dalvik. */ +GArchProcessor *g_dalvik_processor_new(void); + + + +#endif /* _ARCH_DALVIK_PROCESSOR_H */ diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c new file mode 100644 index 0000000..78b5166 --- /dev/null +++ b/src/arch/dalvik/register.c @@ -0,0 +1,264 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.c - aides auxiliaires relatives aux registres Dalvik + * + * Copyright (C) 2010 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 "register.h" + + +#include <stdio.h> + + +#include "../operand-int.h" + + + +//* Représentation d'un registre Dalvik (instance) */ +struct _GDalvikRegister +{ + GArchOperand parent; /* Instance parente */ + + uint16_t index; /* Indice du registre */ + +}; + + +/* Représentation d'un registre Dalvik (classe) */ +struct _GDalvikRegisterClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +#define MAX_REGNAME_LEN 8 + + +/* Construit la chaîne de caractères correspondant à l'opérande. */ +static void g_dalvik_register_to_string(const GDalvikRegister *, AsmSyntax, char [MAX_REGNAME_LEN], size_t *); + +/* Ajoute du texte simple à un fichier ouvert en écriture. */ +static void g_dalvik_register_add_text(const GDalvikRegister *, GRenderingOptions *, MainRendering, FILE *); + +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +static void g_dalvik_register_to_buffer(const GDalvikRegister *, GBufferLine *, GRenderingOptions *); + + + +/* Indique le type défini pour une représentation d'un registre Dalvik. */ +G_DEFINE_TYPE(GDalvikRegister, g_dalvik_register, G_TYPE_CONTENT_EXPORTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des lignes de représentation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_class_init(GDalvikRegisterClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de ligne de représentation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_init(GDalvikRegister *reg) +{ + GContentExporter *parent; /* Instance parente */ + + parent = G_CONTENT_EXPORTER(reg); + + parent->add_text = (add_text_fc)g_dalvik_register_add_text; + parent->export_buffer = (export_buffer_fc)g_dalvik_register_to_buffer; + +} + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre Dalvik. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDalvikRegister *g_dalvik_register_new(uint16_t index) +{ + GDalvikRegister *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_REGISTER, NULL); + + result->index = index; + + return result; + +} + + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à transcrire. * +* syntax = type de représentation demandée. * +* key = description humaine du registre. [OUT] * +* klen = nombre de caractères utilisés. [OUT] * +* * +* Description : Construit la chaîne de caractères correspondant à l'opérande.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_to_string(const GDalvikRegister *reg, AsmSyntax syntax, char key[MAX_REGNAME_LEN], size_t *klen) +{ + switch (syntax) + { + case ASX_INTEL: + *klen = snprintf(key, MAX_REGNAME_LEN, "v%hd", reg->index); + break; + + case ASX_ATT: + *klen = snprintf(key, MAX_REGNAME_LEN, "%%v%hd", reg->index); + break; + + default: + *klen = 0; + break; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre X86 à transcrire. * +* options = options de rendu. * +* rendering = support effectif final des lignes de code. * +* stream = flux ouvert en écriture. * +* * +* Description : Ajoute du texte simple à un fichier ouvert en écriture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_add_text(const GDalvikRegister *reg, GRenderingOptions *options, MainRendering rendering, FILE *stream) +{ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + g_dalvik_register_to_string(reg, g_rendering_options_get_syntax(options), key, &klen); + + g_content_exporter_insert_text(G_CONTENT_EXPORTER(reg), stream, + key, klen, RTT_REGISTER); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre X86 à transcrire. * +* buffer = espace où placer ledit contenu. * +* options = options de rendu. * +* * +* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_to_buffer(const GDalvikRegister *reg, GBufferLine *buffer, GRenderingOptions *options) +{ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + g_dalvik_register_to_string(reg, g_rendering_options_get_syntax(options), key, &klen); + + g_content_exporter_insert_into_buffer(G_CONTENT_EXPORTER(reg), buffer, BLC_ASSEMBLY, + key, klen, RTT_REGISTER); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Indique si le registre correspond à ebp ou similaire. * +* * +* Retour : true si la correspondance est avérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_dalvik_register_is_base_pointer(const GDalvikRegister *reg) +{ + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Indique si le registre correspond à esp ou similaire. * +* * +* Retour : true si la correspondance est avérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_dalvik_register_is_stack_pointer(const GDalvikRegister *reg) +{ + return false; + +} diff --git a/src/arch/dalvik/register.h b/src/arch/dalvik/register.h new file mode 100644 index 0000000..5ac5617 --- /dev/null +++ b/src/arch/dalvik/register.h @@ -0,0 +1,65 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.h - prototypes pour les aides auxiliaires relatives aux registres Dalvik + * + * Copyright (C) 2010 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 _ARCH_DALVIK_REGISTERS_H +#define _ARCH_DALVIK_REGISTERS_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "../archbase.h" + + + +#define G_TYPE_DALVIK_REGISTER g_dalvik_register_get_type() +#define G_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_register_get_type(), GDalvikRegister)) +#define G_IS_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_register_get_type())) +#define G_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) +#define G_IS_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER)) +#define G_DALVIK_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) + + +/* Représentation d'un registre Dalvik (instance) */ +typedef struct _GDalvikRegister GDalvikRegister; + +/* Représentation d'un registre Dalvik (classe) */ +typedef struct _GDalvikRegisterClass GDalvikRegisterClass; + + +/* Indique le type défini pour une représentation d'un registre Dalvik. */ +GType g_dalvik_register_get_type(void); + +/* Crée une réprésentation de registre Dalvik. */ +GDalvikRegister *g_dalvik_register_new(uint16_t); + +/* Indique si le registre correspond à ebp ou similaire. */ +bool g_dalvik_register_is_base_pointer(const GDalvikRegister *); + +/* Indique si le registre correspond à esp ou similaire. */ +bool g_dalvik_register_is_stack_pointer(const GDalvikRegister *); + + + +#endif /* _ARCH_DALVIK_REGISTERS_H */ diff --git a/src/arch/immediate.c b/src/arch/immediate.c index 07f848f..1a32748 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -41,7 +41,7 @@ struct _GImmOperand { GArchOperand parent; /* Instance parente */ - AsmOperandSize size; /* Taille de l'opérande */ + MemoryDataSize size; /* Taille de l'opérande */ /** * Note : dans le cas d'une valeur signée, @@ -148,6 +148,7 @@ static void g_imm_operand_init(GImmOperand *operand) * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * * endian = ordre des bits dans la source. * * * * Description : Crée un opérande réprésentant une valeur numérique. * @@ -158,7 +159,7 @@ static void g_imm_operand_init(GImmOperand *operand) * * ******************************************************************************/ -GArchOperand *g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data, off_t *pos, off_t len, SourceEndian endian) +GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian) { GImmOperand *result; /* Opérande à retourner */ @@ -168,42 +169,52 @@ GArchOperand *g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data switch (size) { - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + if (!read_u4(&result->unsigned_imm.val8, data, pos, len, low, endian)) + goto gionfd_error; + break; + + case MDS_8_BITS_UNSIGNED: if (!read_u8(&result->unsigned_imm.val8, data, pos, len, endian)) goto gionfd_error; break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: if (!read_u16(&result->unsigned_imm.val16, data, pos, len, endian)) goto gionfd_error; break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: if (!read_u32(&result->unsigned_imm.val32, data, pos, len, endian)) goto gionfd_error; break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: if (!read_u64(&result->unsigned_imm.val64, data, pos, len, endian)) goto gionfd_error; break; - case AOS_8_BITS_SIGNED: + case MDS_4_BITS_SIGNED: + if (!read_s4(&result->signed_imm.val8, data, pos, len, low, endian)) + goto gionfd_error; + break; + + case MDS_8_BITS_SIGNED: if (!read_s8(&result->signed_imm.val8, data, pos, len, endian)) goto gionfd_error; break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: if (!read_s16(&result->signed_imm.val16, data, pos, len, endian)) goto gionfd_error; break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: if (!read_s32(&result->signed_imm.val32, data, pos, len, endian)) goto gionfd_error; break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: if (!read_s64(&result->signed_imm.val64, data, pos, len, endian)) goto gionfd_error; break; @@ -218,7 +229,7 @@ GArchOperand *g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data gionfd_error: - /* TODO : free */ + g_object_unref(G_OBJECT(result)); return NULL; @@ -238,7 +249,7 @@ GArchOperand *g_imm_operand_new_from_data(MemoryDataSize size, const bin_t *data * * ******************************************************************************/ -GArchOperand *g_imm_operand_new_from_value(AsmOperandSize size, ...) +GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, ...) { GImmOperand *result; /* Opérande à retourner */ va_list ap; /* Liste des compléments */ @@ -251,7 +262,7 @@ GArchOperand *g_imm_operand_new_from_value(AsmOperandSize size, ...) int32_t sval32; /* Valeur sur 32 bits */ int64_t sval64; /* Valeur sur 64 bits */ - if (size == AOS_UNDEFINED) return NULL; + if (size == MDS_UNDEFINED) return NULL; result = g_object_new(G_TYPE_IMM_OPERAND, NULL); @@ -262,37 +273,37 @@ GArchOperand *g_imm_operand_new_from_value(AsmOperandSize size, ...) switch (size) { /* Pour GCC... */ - case AOS_UNDEFINED: + case MDS_UNDEFINED: break; - case AOS_8_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: uval8 = (uint8_t)va_arg(ap, unsigned int); result->unsigned_imm.val8 = uval8; break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: uval16 = (uint16_t)va_arg(ap, unsigned int); result->unsigned_imm.val16 = uval16; break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: uval32 = (uint32_t)va_arg(ap, unsigned int); result->unsigned_imm.val32 = uval32; break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: uval64 = (uint64_t)va_arg(ap, unsigned int); result->unsigned_imm.val64 = uval64; break; - case AOS_8_BITS_SIGNED: + case MDS_8_BITS_SIGNED: sval8 = (int8_t)va_arg(ap, int); result->signed_imm.val8 = sval8; break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: sval16 = (int16_t)va_arg(ap, int); result->signed_imm.val16 = sval16; break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: sval32 = (int32_t)va_arg(ap, int); result->signed_imm.val32 = sval32; break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: sval64 = (int64_t)va_arg(ap, int); result->signed_imm.val64 = sval64; break; @@ -323,16 +334,19 @@ bool g_imm_operand_is_negative(const GImmOperand *operand) switch (operand->size) { - case AOS_8_BITS_SIGNED: + case MDS_4_BITS_SIGNED: + result = (operand->signed_imm.val8 & 0x08); + break; + case MDS_8_BITS_SIGNED: result = (operand->signed_imm.val8 & 0x80); break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: result = (operand->signed_imm.val16 & 0x8000); break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: result = (operand->signed_imm.val32 & 0x80000000); break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: result = (operand->signed_imm.val64 & 0x8000000000000000ll); break; default: @@ -371,37 +385,38 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt case MDS_UNDEFINED: result = snprintf(value, VMPA_MAX_SIZE, "0x???"); break; - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "0x%hhx", operand->unsigned_imm.val8); break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "0x%hx", operand->unsigned_imm.val16); break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "0x%x", operand->unsigned_imm.val32); break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "0x%llx", operand->unsigned_imm.val64); break; - case AOS_8_BITS_SIGNED: + case MDS_8_BITS_SIGNED: if (g_imm_operand_is_negative(operand)) result = snprintf(value, VMPA_MAX_SIZE, "0x%hhx", ~operand->signed_imm.val8 + 1); else result = snprintf(value, VMPA_MAX_SIZE, "0x%hhx", operand->signed_imm.val8); break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: if (g_imm_operand_is_negative(operand)) result = snprintf(value, VMPA_MAX_SIZE, "0x%hx", ~operand->signed_imm.val16 + 1); else result = snprintf(value, VMPA_MAX_SIZE, "0x%hx", operand->signed_imm.val16); break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: if (g_imm_operand_is_negative(operand)) result = snprintf(value, VMPA_MAX_SIZE, "0x%x", ~operand->signed_imm.val32 + 1); else result = snprintf(value, VMPA_MAX_SIZE, "0x%x", operand->signed_imm.val32); break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: if (g_imm_operand_is_negative(operand)) result = snprintf(value, VMPA_MAX_SIZE, "0x%llx", ~operand->signed_imm.val64 + 1); else @@ -416,28 +431,29 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt case MDS_UNDEFINED: result = snprintf(value, VMPA_MAX_SIZE, "$0x???"); break; - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%hhx", operand->unsigned_imm.val8); break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%hx", operand->unsigned_imm.val16); break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%x", operand->unsigned_imm.val32); break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%llx", operand->unsigned_imm.val64); break; - case AOS_8_BITS_SIGNED: + case MDS_8_BITS_SIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%hhx", ~operand->signed_imm.val8 + 1); break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%hx", ~operand->signed_imm.val16 + 1); break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%x", ~operand->signed_imm.val32 + 1); break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: result = snprintf(value, VMPA_MAX_SIZE, "$0x%llx", ~operand->signed_imm.val64 + 1); break; } @@ -528,16 +544,17 @@ bool g_imm_operand_to_vmpa_t(const GImmOperand *operand, vmpa_t *addr) switch (operand->size) { - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: *addr = operand->unsigned_imm.val8; break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: *addr = operand->unsigned_imm.val16; break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: *addr = operand->unsigned_imm.val32; break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: *addr = operand->unsigned_imm.val64; break; default: @@ -572,35 +589,36 @@ bool g_imm_operand_to_size_t(const GImmOperand *operand, size_t *value, bool *ne switch (operand->size) { - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: result = (sizeof(size_t) >= 1); if (result) *value = operand->unsigned_imm.val8; break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: result = (sizeof(size_t) >= 2); if (result) *value = operand->unsigned_imm.val16; break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: result = (sizeof(size_t) >= 4); if (result) *value = operand->unsigned_imm.val32; break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: result = (sizeof(size_t) >= 8); if (result) *value = operand->unsigned_imm.val64; break; - case AOS_8_BITS_SIGNED: + case MDS_8_BITS_SIGNED: result = (sizeof(size_t) >= 1); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val8; break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: result = (sizeof(size_t) >= 2); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val16; break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: result = (sizeof(size_t) >= 4); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val32; break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: result = (sizeof(size_t) >= 8); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val64; break; @@ -636,35 +654,36 @@ bool g_imm_operand_to_off_t(const GImmOperand *operand, off_t *value, bool *nega switch (operand->size) { - case AOS_8_BITS_UNSIGNED: + case MDS_4_BITS_UNSIGNED: + case MDS_8_BITS_UNSIGNED: result = (sizeof(off_t) >= 1); if (result) *value = operand->unsigned_imm.val8; break; - case AOS_16_BITS_UNSIGNED: + case MDS_16_BITS_UNSIGNED: result = (sizeof(off_t) >= 2); if (result) *value = operand->unsigned_imm.val16; break; - case AOS_32_BITS_UNSIGNED: + case MDS_32_BITS_UNSIGNED: result = (sizeof(off_t) >= 4); if (result) *value = operand->unsigned_imm.val32; break; - case AOS_64_BITS_UNSIGNED: + case MDS_64_BITS_UNSIGNED: result = (sizeof(off_t) >= 8); if (result) *value = operand->unsigned_imm.val64; break; - case AOS_8_BITS_SIGNED: + case MDS_8_BITS_SIGNED: result = (sizeof(off_t) >= 1); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val8; break; - case AOS_16_BITS_SIGNED: + case MDS_16_BITS_SIGNED: result = (sizeof(off_t) >= 2); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val16; break; - case AOS_32_BITS_SIGNED: + case MDS_32_BITS_SIGNED: result = (sizeof(off_t) >= 4); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val32; break; - case AOS_64_BITS_SIGNED: + case MDS_64_BITS_SIGNED: result = (sizeof(off_t) >= 8); if (result) *value = (*negative ? -1 : 1 ) * operand->signed_imm.val64; break; diff --git a/src/arch/immediate.h b/src/arch/immediate.h index 63ce970..1e66d54 100644 --- a/src/arch/immediate.h +++ b/src/arch/immediate.h @@ -52,10 +52,12 @@ typedef struct _GImmOperandClass GImmOperandClass; GType g_imm_operand_get_type(void); /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *g_imm_operand_new_from_data(MemoryDataSize, const bin_t *, off_t *, off_t, SourceEndian); +GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize, const bin_t *, off_t *, off_t, bool *, SourceEndian); + +#define g_imm_operand_new_from_data(size, data, pos, len, endian) _g_imm_operand_new_from_data(size, data, pos, len, NULL, endian) /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *g_imm_operand_new_from_value(AsmOperandSize, ...); +GArchOperand *g_imm_operand_new_from_value(MemoryDataSize, ...); /* Indique le signe d'une valeur immédiate. */ bool g_imm_operand_is_negative(const GImmOperand *); diff --git a/src/arch/jvm/processor.c b/src/arch/jvm/processor.c index 034b864..e9dffe2 100644 --- a/src/arch/jvm/processor.c +++ b/src/arch/jvm/processor.c @@ -46,10 +46,10 @@ struct _GJvmProcessorClass }; -/* Initialise la classe des lignes de descriptions initiales. */ +/* Initialise la classe des processeurs de JVM. */ static void g_jvm_processor_class_init(GJvmProcessorClass *); -/* Initialise la classe des lignes de descriptions initiales. */ +/* Initialise une instance de processeur de JVM. */ static void g_jvm_processor_init(GJvmProcessor *); /* Décode une instruction dans un flux de données. */ @@ -65,7 +65,7 @@ G_DEFINE_TYPE(GJvmProcessor, g_jvm_processor, G_TYPE_ARCH_PROCESSOR); * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des lignes de descriptions initiales. * +* Description : Initialise la classe des processeurs de JVM. * * * * Retour : - * * * @@ -83,7 +83,7 @@ static void g_jvm_processor_class_init(GJvmProcessorClass *klass) * * * Paramètres : proc = instance à initialiser. * * * -* Description : Initialise la classe des lignes de descriptions initiales. * +* Description : Initialise une instance de processeur de JVM. * * * * Retour : - * * * diff --git a/src/arch/processor.c b/src/arch/processor.c index 103296a..9bea205 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -42,6 +42,7 @@ #include "artificial.h" +#include "dalvik/processor.h" #include "jvm/processor.h" #include "mips/processor.h" #include "x86/processor.h" @@ -209,6 +210,7 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc bool init_all_processors(void) { + _processors_list[APT_DALVIK] = g_dalvik_processor_new(); _processors_list[APT_JVM] = g_jvm_processor_new(); _processors_list[APT_MIPS] = g_mips_processor_new(); _processors_list[APT_386] = g_x86_processor_new(); @@ -255,6 +257,10 @@ GArchProcessor *get_arch_processor_from_format(const GExeFormat *format) switch (g_exe_format_get_target_machine(format)) { + case FTM_DALVIK: + result = get_arch_processor_for_type(APT_DALVIK); + break; + case FTM_JVM: result = get_arch_processor_for_type(APT_JVM); break; diff --git a/src/arch/processor.h b/src/arch/processor.h index ea954cc..063a3ba 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -66,6 +66,7 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *, co /* Type de processeurs disponibles */ typedef enum _ArchProcessorType { + APT_DALVIK, /* Dalvik Virtual Machine */ APT_JVM, /* Java Virtual Machine */ APT_MIPS, /* Mips 32 ou 64 bits */ APT_386, /* Intel 80386 */ diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h index 5a6d69f..92b6124 100644 --- a/src/arch/x86/opcodes.h +++ b/src/arch/x86/opcodes.h @@ -25,8 +25,8 @@ #define _ARCH_X86_OPCODES_H -#include "processor.h" #include "instruction.h" +#include "processor.h" diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c index 849e54d..b3f0997 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -29,7 +29,6 @@ #include <stdio.h> -#include "../operand.h" #include "../operand-int.h" #include "../../common/extstr.h" @@ -92,7 +91,7 @@ static void g_x86_register_operand_init(GX86RegisterOperand *); /* Ajoute du texte simple à un fichier ouvert en écriture. */ static void g_x86_register_operand_add_text(const GX86RegisterOperand *, GRenderingOptions *, MainRendering, FILE *); -/*Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ +/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ static void g_x86_register_operand_to_buffer(const GX86RegisterOperand *, GBufferLine *, GRenderingOptions *); diff --git a/src/arch/x86/processor.h b/src/arch/x86/processor.h index 1014d11..a04d880 100644 --- a/src/arch/x86/processor.h +++ b/src/arch/x86/processor.h @@ -26,7 +26,7 @@ #include "../processor.h" -#include "instruction.h" +#include "instruction.h" /* FIXME : remme */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 7aa255e..f8e4f20 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -6,6 +6,7 @@ libcommon_la_SOURCES = \ endianness.h endianness.c \ environment.h environment.c \ extstr.h extstr.c \ + leb128.h leb128.c \ macros.h \ xml.h xml.c diff --git a/src/common/endianness.c b/src/common/endianness.c index 32bb65a..5c9b183 100755 --- a/src/common/endianness.c +++ b/src/common/endianness.c @@ -25,8 +25,42 @@ +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = ordre des bits dans la source. * +* * +* Description : Lit un nombre non signé sur 4 bits. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_u4(uint8_t *target, const bin_t *data, off_t *pos, off_t len, bool *low, SourceEndian endian) +{ + if ((len - *pos) < 1) return false; + + if (*low) + { + *target = data[*pos] & 0x0f; + *low = false; + } + else + { + *target = (data[*pos] & 0xf0) >> 4; + *low = true; + *pos += 1; + } + return true; +} /****************************************************************************** diff --git a/src/common/endianness.h b/src/common/endianness.h index f9d421e..f729ac5 100755 --- a/src/common/endianness.h +++ b/src/common/endianness.h @@ -26,7 +26,6 @@ #include <stdbool.h> -#include <sys/types.h> #include "../arch/archbase.h" @@ -43,6 +42,9 @@ typedef enum _SourceEndian } SourceEndian; +/* Lit un nombre non signé sur 4 bits. */ +bool read_u4(uint8_t *, const bin_t *, off_t *, off_t, bool *, SourceEndian); + /* Lit un nombre non signé sur un octet. */ bool read_u8(uint8_t *, const bin_t *, off_t *, off_t, SourceEndian); @@ -56,6 +58,7 @@ bool read_u32(uint32_t *, const bin_t *, off_t *, off_t, SourceEndian); bool read_u64(uint64_t *, const bin_t *, off_t *, off_t, SourceEndian); +#define read_s4(target, data, pos, len, low, endian) read_u4((uint8_t *)target, data, pos, len, low, endian) #define read_s8(target, data, pos, len, endian) read_u8((uint8_t *)target, data, pos, len, endian) #define read_s16(target, data, pos, len, endian) read_u16((uint16_t *)target, data, pos, len, endian) #define read_s32(target, data, pos, len, endian) read_u32((uint32_t *)target, data, pos, len, endian) diff --git a/src/common/leb128.c b/src/common/leb128.c new file mode 100644 index 0000000..4a03797 --- /dev/null +++ b/src/common/leb128.c @@ -0,0 +1,111 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * leb128.c - support des valeurs encodées au format LEB128. + * + * Copyright (C) 2010 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 "leb128.h" + + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* * +* Description : Lit un nombre non signé encodé au format LEB128. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_uleb128(uleb128_t *target, const bin_t *data, off_t *pos, off_t len) +{ + int shift; /* Décallage à appliquer */ + off_t i; /* Boucle de parcours */ + + shift = 0; + *target = 0; + + for (i = 0; i < 8; i++) + { + /* On évite les débordements... */ + if (*pos >= len) return false; + + *target |= (data[*pos] & 0x7f) << shift; + + shift += 7; + (*pos)++; + + if ((data[*pos - 1] & 0x80) == 0x00) break; + + } + + return (i < 8); + +} + + +/****************************************************************************** +* * +* Paramètres : target = lieu d'enregistrement de la lecture. [OUT] * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* * +* Description : Lit un nombre signé encodé au format LEB128. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_leb128(leb128_t *target, const bin_t *data, off_t *pos, off_t len) +{ + int shift; /* Décallage à appliquer */ + off_t i; /* Boucle de parcours */ + + shift = 0; + *target = 0; + + for (i = 0; i < 8; i++) + { + /* On évite les débordements... */ + if (*pos >= len) return false; + + *target |= (data[*pos] & 0x7f) << shift; + + shift += 7; + + if ((data[(*pos)++] & 0x80) == 0x00) break; + + } + + if (shift < (8 * sizeof(int64_t)) && (data[*pos - 1] & 0x40) == 0x40) + *target |= - (1 << shift); + + return (i < 8); + +} diff --git a/src/common/leb128.h b/src/common/leb128.h new file mode 100644 index 0000000..0364cf7 --- /dev/null +++ b/src/common/leb128.h @@ -0,0 +1,49 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * leb128.h - prototypes pour le support des valeurs encodées au format LEB128. + * + * Copyright (C) 2010 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 _COMMON_LEB128_H +#define _COMMON_LEB128_H + + +#include <stdbool.h> + + +#include "../arch/archbase.h" + + + +/* Nouveaux types */ +typedef uint64_t uleb128_t; +typedef int64_t leb128_t; + + + +/* Lit un nombre non signé encodé au format LEB128. */ +bool read_uleb128(uleb128_t *, const bin_t *, off_t *, off_t); + +/* Lit un nombre signé encodé au format LEB128. */ +bool read_leb128(leb128_t *, const bin_t *, off_t *, off_t); + + + +#endif /* _COMMON_LEB128_H */ diff --git a/src/format/Makefile.am b/src/format/Makefile.am index b080536..61fc0c6 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -21,6 +21,7 @@ libformat_la_SOURCES = \ # part.h part.c libformat_la_LIBADD = \ + dex/libformatdex.la \ dwarf/libformatdwarf.la \ elf/libformatelf.la \ java/libformatjava.la \ @@ -36,4 +37,5 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = dwarf elf java mangling pe +SUBDIRS = dex elf java mangling pe +#SUBDIRS = dex dwarf elf java mangling pe diff --git a/src/format/dex/Makefile.am b/src/format/dex/Makefile.am new file mode 100755 index 0000000..76cd63e --- /dev/null +++ b/src/format/dex/Makefile.am @@ -0,0 +1,19 @@ + +noinst_LTLIBRARIES = libformatdex.la + +libformatdex_la_SOURCES = \ + class.h class.c \ + dex-int.h dex-int.c \ + dex.h dex.c \ + dex_def.h \ + method.h method.c \ + pool.h pool.c + +libformatdex_la_LDFLAGS = + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/format/dex/class.c b/src/format/dex/class.c new file mode 100644 index 0000000..03431f0 --- /dev/null +++ b/src/format/dex/class.c @@ -0,0 +1,298 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * class.c - manipulation des classes du format DEX + * + * Copyright (C) 2010 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 "class.h" + + +#include <malloc.h> + + +#include "dex-int.h" +#include "method.h" + + + + + + + + +/* Classe issue du code source (instance) */ +struct _GDexClass +{ + GObject parent; /* A laisser en premier */ + + GDexMethod **direct_methods; /* Méthodes propres */ + size_t dmethods_count; /* Quantité de ces méthodes */ + GDexMethod **virtual_methods; /* Méthodes virtuelles */ + size_t vmethods_count; /* Quantité de ces méthodes */ + +}; + +/* Classe issue du code source (classe) */ +struct _GDexClassClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une classe issue du code source. */ +static void g_dex_class_class_init(GDexClassClass *); + +/* Procède à l'initialisation d'une classe issue du code source. */ +static void g_dex_class_init(GDexClass *); + +/* Crée une nouvelle représentation de classe issue de code. */ +static GDexClass *g_dex_class_new(const GDexFormat *, off_t); + + + + + + + + + + +/* Détermine le type d'une classe issue du code source. */ +G_DEFINE_TYPE(GDexClass, g_dex_class, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe issue du code source.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_class_init(GDexClassClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : class = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe issue du code source.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_init(GDexClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* offset = tête de lecture des données initiale. * +* * +* Description : Crée une nouvelle représentation de classe issue de code. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDexClass *g_dex_class_new(const GDexFormat *format, off_t offset) +{ + GDexClass *result; /* Composant à retourner */ + class_def_item def; /* Définition de la classe */ + class_data_item data; /* Contenu de la classe */ + uleb128_t i; /* Boucle de parcours */ + GDexMethod *method; /* Méthode chargée */ + + if (!read_dex_class_def_item(format, &offset, &def)) + return NULL; + + offset = def.class_data_off; + + if (!read_dex_class_data_item(format, &offset, &data)) + return NULL; + + + + printf(" Classe :: d meth count == 0x%lld\n", data.direct_methods_size); + printf(" Classe :: v meth count == 0x%lld\n", data.virtual_methods_size); + + + + result = g_object_new(G_TYPE_DEX_CLASS, NULL); + + for (i = 0; i < data.direct_methods_size; i++) + { + method = g_dex_method_new(format, &data.direct_methods[i]); + + if (method != NULL) + { + result->dmethods_count++; + result->direct_methods = (GDexMethod **)realloc(result->direct_methods, + result->dmethods_count * sizeof(GDexMethod *)); + + result->direct_methods[result->dmethods_count - 1] = method; + + } + + } + + + + for (i = 0; i < data.virtual_methods_size; i++) + { + method = g_dex_method_new(format, &data.virtual_methods[i]); + + if (method != NULL) + { + result->vmethods_count++; + result->virtual_methods = (GDexMethod **)realloc(result->virtual_methods, + result->vmethods_count * sizeof(GDexMethod *)); + + result->virtual_methods[result->vmethods_count - 1] = method; + + } + + } + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* parts = liste à venir compléter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones binaires à analyser. * +* * +* Retour : Zones binaires à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPart **g_dex_class_get_parts(const GDexClass *class, GBinPart **parts, size_t *count) +{ + size_t i; /* Boucle de parcours */ + GBinPart *part; /* Partie à intégrer à la liste*/ + + for (i = 0; i < class->dmethods_count; i++) + { + part = g_dex_method_as_part(class->direct_methods[i]); + + parts = (GBinPart **)realloc(parts, ++(*count) * sizeof(GBinPart *)); + parts[*count - 1] = part; + + } + + for (i = 0; i < class->vmethods_count; i++) + { + part = g_dex_method_as_part(class->virtual_methods[i]); + + parts = (GBinPart **)realloc(parts, ++(*count) * sizeof(GBinPart *)); + parts[*count - 1] = part; + + } + + return parts; + +} + + + + + + + + + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge toutes les classes listées dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_classes(GDexFormat *format) +{ + const dex_header *header; /* Raccourci d'usage */ + uint32_t i; /* Boucle de parcours */ + GDexClass *class; /* Représentation chargée */ + + header = &format->header; + + for (i = 0; i < header->class_defs_size; i++) + { + class = g_dex_class_new(format, header->class_defs_off + i * sizeof(class_def_item)); + + if (class != NULL) + { + format->classes_count++; + format->classes = (GDexClass **)realloc(format->classes, + format->classes_count * sizeof(GDexClass *)); + + format->classes[format->classes_count - 1] = class; + + } + + } + + return true; + +} diff --git a/src/format/dex/class.h b/src/format/dex/class.h new file mode 100644 index 0000000..d78e6e9 --- /dev/null +++ b/src/format/dex/class.h @@ -0,0 +1,71 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * class.h - prototypes pour la manipulation des classes du format DEX + * + * Copyright (C) 2010 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 _FORMAT_DEX_CLASS_H +#define _FORMAT_DEX_CLASS_H + + +#include <glib-object.h> + + +#include "dex.h" + + + +#define G_TYPE_DEX_CLASS (g_dex_class_get_type()) +#define G_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_CLASS, GDexClass)) +#define G_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_CLASS, GDexClassClass)) +#define G_IS_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_CLASS)) +#define G_IS_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_CLASS)) +#define G_DEX_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_CLASS, GDexClassClass)) + + + +/* Classe issue du code source (instance) */ +typedef struct _GDexClass GDexClass; + +/* Classe issue du code source (classe) */ +typedef struct _GDexClassClass GDexClassClass; + + + +/* Détermine le type d'une classe issue du code source. */ +GType g_dex_class_get_type(void); + +/* Fournit les références aux zones binaires à analyser. */ +GBinPart **g_dex_class_get_parts(const GDexClass *, GBinPart **, size_t *); + + + + + + + +/* Charge toutes les classes listées dans le contenu binaire. */ +bool load_all_dex_classes(GDexFormat *); + + + + + +#endif /* _FORMAT_DEX_CLASS_H */ diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c new file mode 100644 index 0000000..be1c211 --- /dev/null +++ b/src/format/dex/dex-int.c @@ -0,0 +1,518 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dex-int.c - structures internes du format DEX + * + * Copyright (C) 2010 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 "dex-int.h" + + +#include <malloc.h> + + +#include "../../common/endianness.h" + + + +/* ---------------------------------------------------------------------------------- */ +/* ELEMENTS DE TABLE DES CONSTANTES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* str_id = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un identifiant de chaîne DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_string_id_item(const GDexFormat *format, off_t *pos, string_id_item *str_id) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u32(&str_id->string_data_off, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* str_data = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture de proriétés de chaîne DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_string_data_item(const GDexFormat *format, off_t *pos, string_data_item *str_data) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_uleb128(&str_data->utf16_size, content, pos, length); + + str_data->data = &content[*pos]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* item = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un identifiant de type DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_type_id_item(const GDexFormat *format, off_t *pos, type_id_item *item) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u32(&item->descriptor_idx, content, pos, length, SRE_LITTLE); + + return result; + +} + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* meth_id = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une description de méthode. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_method_id_item(const GDexFormat *format, off_t *pos, method_id_item *meth_id) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u16(&meth_id->class_idx, content, pos, length, SRE_LITTLE); + result &= read_u16(&meth_id->proto_idx, content, pos, length, SRE_LITTLE); + result &= read_u32(&meth_id->name_idx, content, pos, length, SRE_LITTLE); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* class_def = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture des propriétés d'une classe DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_class_def_item(const GDexFormat *format, off_t *pos, class_def_item *class_def) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u32(&class_def->class_idx, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->access_flags, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->superclass_idx, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->interfaces_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->source_file_idx, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->annotations_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->class_data_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&class_def->static_values_off, content, pos, length, SRE_LITTLE); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DESCRIPTION DE CLASSES DEX */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* field = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un champ quelconque DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_encoded_field(const GDexFormat *format, off_t *pos, encoded_field *field) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_uleb128(&field->field_idx_diff, content, pos, length); + result &= read_uleb128(&field->access_flags, content, pos, length); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* method = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une méthode quelconque DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_encoded_method(const GDexFormat *format, off_t *pos, encoded_method *method) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_uleb128(&method->method_idx_diff, content, pos, length); + result &= read_uleb128(&method->access_flags, content, pos, length); + result &= read_uleb128(&method->code_off, content, pos, length); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* item = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'un contenu de classe DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_class_data_item(const GDexFormat *format, off_t *pos, class_data_item *item) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + uleb128_t i; /* Boucle de parcours */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + item->static_fields = NULL; + item->instance_fields = NULL; + item->direct_methods = NULL; + item->virtual_methods = NULL; + + result &= read_uleb128(&item->static_fields_size, content, pos, length); + result &= read_uleb128(&item->instance_fields_size, content, pos, length); + result &= read_uleb128(&item->direct_methods_size, content, pos, length); + result &= read_uleb128(&item->virtual_methods_size, content, pos, length); + + if (result && item->static_fields_size > 0) + { + item->static_fields = (encoded_field *)calloc(item->static_fields_size, sizeof(encoded_field)); + + for (i = 0; i < item->static_fields_size && result; i++) + result = read_dex_encoded_field(format, pos, &item->static_fields[i]); + + } + + if (result && item->instance_fields_size > 0) + { + item->instance_fields = (encoded_field *)calloc(item->instance_fields_size, sizeof(encoded_field)); + + for (i = 0; i < item->instance_fields_size && result; i++) + result = read_dex_encoded_field(format, pos, &item->instance_fields[i]); + + } + + if (result && item->direct_methods_size > 0) + { + item->direct_methods = (encoded_method *)calloc(item->direct_methods_size, sizeof(encoded_method)); + + for (i = 0; i < item->direct_methods_size && result; i++) + result = read_dex_encoded_method(format, pos, &item->direct_methods[i]); + + } + + if (result && item->virtual_methods_size > 0) + { + item->virtual_methods = (encoded_method *)calloc(item->virtual_methods_size, sizeof(encoded_method)); + + for (i = 0; i < item->virtual_methods_size && result; i++) + result = read_dex_encoded_method(format, pos, &item->virtual_methods[i]); + + } + + if (!result) + reset_dex_class_data_item(item); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : item = structure à nettoyer. * +* * +* Description : Supprime tous les éléments chargés en mémoire à la lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_dex_class_data_item(class_data_item *item) +{ + if (item->static_fields != NULL) + free(item->static_fields); + + if (item->instance_fields != NULL) + free(item->instance_fields); + + if (item->direct_methods != NULL) + free(item->direct_methods); + + if (item->virtual_methods != NULL) + free(item->virtual_methods); + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* pos = position de début de lecture. [OUT] * +* item = structure lue à retourner. [OUT] * +* * +* Description : Procède à la lecture d'une portion de code DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dex_code_item(const GDexFormat *format, off_t *pos, code_item *item) +{ + bool result; /* Bilan à retourner */ + const bin_t *content; /* Contenu binaire à lire */ + off_t length; /* Taille totale du contenu */ + + result = true; + + content = G_BIN_FORMAT(format)->content; + length = G_BIN_FORMAT(format)->length; + + result &= read_u16(&item->registers_size, content, pos, length, SRE_LITTLE); + result &= read_u16(&item->ins_size, content, pos, length, SRE_LITTLE); + result &= read_u16(&item->outs_size, content, pos, length, SRE_LITTLE); + result &= read_u16(&item->tries_size, content, pos, length, SRE_LITTLE); + result &= read_u32(&item->debug_info_off, content, pos, length, SRE_LITTLE); + result &= read_u32(&item->insns_size, content, pos, length, SRE_LITTLE); + + item->insns = (uint16_t *)pos; + + return result; + +} + + + + + + + +/****************************************************************************** +* * +* 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; + +} + + + + + diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h new file mode 100755 index 0000000..e34dbd3 --- /dev/null +++ b/src/format/dex/dex-int.h @@ -0,0 +1,117 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dex-int.h - prototypes pour les structures internes du format DEX + * + * Copyright (C) 2008 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 _FORMAT_DEX_DEX_INT_H +#define _FORMAT_DEX_DEX_INT_H + + +#include "class.h" +#include "dex.h" +#include "dex_def.h" +#include "../executable-int.h" + + + + + +/* Format d'exécutable DEX (instance) */ +struct _GDexFormat +{ + GExeFormat parent; /* A laisser en premier */ + + dex_header header; /* En-tête du programme */ + + + + GDexClass **classes; /* Classes retrouvées */ + size_t classes_count; /* Nombre de ces classes */ + + + +}; + +/* Format d'exécutable DEX (classe) */ +struct _GDexFormatClass +{ + GExeFormatClass parent; /* A laisser en premier */ + +}; + + + +/* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */ + + +/* Procède à la lecture d'un identifiant de chaîne DEX. */ +bool read_dex_string_id_item(const GDexFormat *, off_t *, string_id_item *); + +/* Procède à la lecture de proriétés de chaîne DEX. */ +bool read_dex_string_data_item(const GDexFormat *, off_t *, string_data_item *); + +/* Procède à la lecture d'un identifiant de type DEX. */ +bool read_dex_type_id_item(const GDexFormat *, off_t *, type_id_item *); + + + +/* Procède à la lecture d'une description de méthode. */ +bool read_dex_method_id_item(const GDexFormat *, off_t *, method_id_item *); + +/* Procède à la lecture des propriétés d'une classe DEX. */ +bool read_dex_class_def_item(const GDexFormat *, off_t *, class_def_item *); + + + +/* --------------------------- DESCRIPTION DE CLASSES DEX --------------------------- */ + + +/* Procède à la lecture d'un champ quelconque DEX. */ +bool read_dex_encoded_field(const GDexFormat *, off_t *, encoded_field *); + +/* Procède à la lecture d'une méthode quelconque DEX. */ +bool read_dex_encoded_method(const GDexFormat *, off_t *, encoded_method *); + +/* Procède à la lecture d'un contenu de classe DEX. */ +bool read_dex_class_data_item(const GDexFormat *, off_t *, class_data_item *); + +/* Supprime tous les éléments chargés en mémoire à la lecture. */ +void reset_dex_class_data_item(class_data_item *); + + + +/* Procède à la lecture d'une portion de code DEX. */ +bool read_dex_code_item(const GDexFormat *, off_t *, code_item *); + + + + +/* Procède à la lecture d'une en-tête de programme DEX. */ +bool read_dex_header(const GDexFormat *, off_t *, dex_header *); + + + + + + + + +#endif /* _FORMAT_DEX_DEX_INT_H */ diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c new file mode 100755 index 0000000..5b68d5f --- /dev/null +++ b/src/format/dex/dex.c @@ -0,0 +1,307 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dex.c - support du format DEX + * + * Copyright (C) 2010 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 "dex.h" + + +#include <string.h> + + +#include "dex-int.h" + + + + + + + + + + + +/* Initialise la classe des formats d'exécutables DEX. */ +static void g_dex_format_class_init(GDexFormatClass *); + +/* Initialise une instance de format d'exécutable DEX. */ +static void g_dex_format_init(GDexFormat *); + +/* Indique le type d'architecture visée par le format. */ +static FormatTargetMachine g_dex_format_get_target_machine(const GDexFormat *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +static vmpa_t g_dex_format_get_entry_point(const GDexFormat *); + +/* Fournit les références aux zones binaires à analyser. */ +static GBinPart **g_dex_format_get_parts(const GDexFormat *, size_t *); + +/* Fournit la position correspondant à une adresse virtuelle. */ +static bool g_dex_format_translate_address_into_offset(const GDexFormat *, vmpa_t, off_t *); + +/* Fournit l'adresse virtuelle correspondant à une position. */ +static bool g_dex_format_translate_offset_into_address(const GDexFormat *, off_t, vmpa_t *); + + + +/****************************************************************************** +* * +* Paramètres : type = type de format recherché. * +* content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : true si la réponse est positive, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dex_is_matching(FormatType type, const uint8_t *content, off_t length) +{ + bool result; /* Bilan à faire connaître */ + + result = false; + + if (length >= DEX_FILE_MAGIC_LEN) + result = (memcmp(content, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0); + + return result; + +} + + +/* Indique le type défini pour un format d'exécutable DEX. */ +G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_class_init(GDexFormatClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_init(GDexFormat *format) +{ + GExeFormat *exe_format; /* Format parent à constituer */ + + exe_format = G_EXE_FORMAT(format); + + exe_format->get_machine = (get_target_machine_fc)g_dex_format_get_target_machine; + exe_format->get_entry_point = (get_entry_point_fc)g_dex_format_get_entry_point; + exe_format->get_parts = (get_parts_fc)g_dex_format_get_parts; + + exe_format->translate_addr = (translate_addr_fc)g_dex_format_translate_address_into_offset; + exe_format->translate_off = (translate_off_fc)g_dex_format_translate_offset_into_address; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* length = taille du contenu en question. * +* * +* Description : Prend en charge un nouveau format DEX. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_dex_format_new(const bin_t *content, off_t length) +{ + GDexFormat *result; /* Structure à retourner */ + off_t offset; /* Tête de lecture */ + + result = g_object_new(G_TYPE_DEX_FORMAT, NULL); + + g_binary_format_set_content(G_BIN_FORMAT(result), content, length); + + + offset = 0; + + if (!read_dex_header(result, &offset, &result->header)) + { + /* TODO */ + return NULL; + } + + /* TODO : vérifier l'en-tête ! */ + + + + if (!load_all_dex_classes(result)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + + + + + + return G_BIN_FORMAT(result); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static FormatTargetMachine g_dex_format_get_target_machine(const GDexFormat *format) +{ + return FTM_DALVIK; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Fournit l'adresse mémoire du point d'entrée du programme. * +* * +* Retour : Adresse de mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static vmpa_t g_dex_format_get_entry_point(const GDexFormat *format) +{ + return 0;//(format->is_32b ? format->header.e_entry.addr32 : format->header.e_entry.addr64); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* count = quantité de zones listées. [OUT] * +* * +* Description : Fournit les références aux zones binaires à analyser. * +* * +* Retour : Zones binaires à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinPart **g_dex_format_get_parts(const GDexFormat *format, size_t *count) +{ + GBinPart **result; /* Tableau à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + *count = 0; + + for (i = 0; i < format->classes_count; i++) + result = g_dex_class_get_parts(format->classes[i], result, count); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit la position correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dex_format_translate_address_into_offset(const GDexFormat *format, vmpa_t addr, off_t *pos) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* pos = position dans le flux binaire à retrouver. * +* addr = adresse virtuelle correspondante. [OUT] * +* * +* Description : Fournit l'adresse virtuelle correspondant à une position. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dex_format_translate_offset_into_address(const GDexFormat *format, off_t pos, vmpa_t *addr) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h new file mode 100755 index 0000000..cfa72c1 --- /dev/null +++ b/src/format/dex/dex.h @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dex.h - prototypes pour le support du format DEX + * + * Copyright (C) 2010 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 _FORMAT_DEX_DEX_H +#define _FORMAT_DEX_DEX_H + + +#include <glib-object.h> +#include <stdbool.h> +#include <sys/types.h> + + +#include "../format.h" + + + +#define G_TYPE_DEX_FORMAT g_dex_format_get_type() +#define G_DEX_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dex_format_get_type(), GDexFormat)) +#define G_IS_DEX_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dex_format_get_type())) +#define G_DEX_FORMAT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dex_format_get_type(), GDexFormatIface)) +#define G_DEX_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_FORMAT, GDexFormatClass)) + + +/* Format d'exécutable DEX (instance) */ +typedef struct _GDexFormat GDexFormat; + +/* Format d'exécutable DEX (classe) */ +typedef struct _GDexFormatClass GDexFormatClass; + + +/* Indique si le format peut être pris en charge ici. */ +bool dex_is_matching(FormatType, const bin_t *, off_t); + +/* Indique le type défini pour un format d'exécutable DEX. */ +GType g_dex_format_get_type(void); + +/* Prend en charge un nouveau format DEX. */ +GBinFormat *g_dex_format_new(const bin_t *, off_t); + + + +#endif /* _FORMAT_DEX_DEX_H */ diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h new file mode 100755 index 0000000..9387a90 --- /dev/null +++ b/src/format/dex/dex_def.h @@ -0,0 +1,189 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * dex_def.h - liste des structures et constantes utilisées par le format DEX + * + * Copyright (C) 2010 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 _FORMAT_DEX_DEX_DEF_H +#define _FORMAT_DEX_DEX_DEF_H + + +#include "../../common/leb128.h" + + + +/* ------------------------ ELEMENTS DE TABLE DES CONSTANTES ------------------------ */ + + +/* Chaîne de caractères */ + +typedef struct _string_id_item +{ + uint32_t string_data_off; /* Propriétés de la chaîne */ + +} string_id_item; + +typedef struct _string_data_item +{ + uleb128_t utf16_size; /* Taille du décodage */ + const uint8_t *data; /* Caractères terminés par '\0'*/ + +} string_data_item; + +/* Description d'un type */ +typedef struct _type_id_item +{ + uint32_t descriptor_idx; /* Description du type */ + +} type_id_item; + + + + +/* Description d'une méthode */ +typedef struct _method_id_item +{ + uint16_t class_idx; /* Classe d'appartenance */ + uint16_t proto_idx; /* Prototype de la méthode */ + uint32_t name_idx; /* Nom de la méthode */ + +} method_id_item; + +/* Description d'une classe */ +typedef struct _class_def_item +{ + uint32_t class_idx; /* Type de la classe */ + uint32_t access_flags; /* Drapeaux d'accès déclarés */ + uint32_t superclass_idx; /* Type de la classe parente */ + uint32_t interfaces_off; /* Liste des interfaces */ + uint32_t source_file_idx; /* Fichier source d'origine */ + uint32_t annotations_off; /* Eventuelles annotations */ + uint32_t class_data_off; /* Données de la classe */ + uint32_t static_values_off; /* Initialisations statiques */ + +} class_def_item; + + + +/* --------------------------- DESCRIPTION DE CLASSES DEX --------------------------- */ + + +/* Propriétés d'une champ */ +typedef struct _encoded_field +{ + uleb128_t field_idx_diff; /* Description du champ */ + uleb128_t access_flags; /* Conditions d'accès */ + +} encoded_field; + +/* Propriétés d'une méthode */ +typedef struct _encoded_method +{ + uleb128_t method_idx_diff; /* Description de la méthode */ + uleb128_t access_flags; /* Conditions d'accès */ + uleb128_t code_off; /* Position du code associé */ + +} encoded_method; + +/* Données de fonctionnement pour classe */ +typedef struct _class_data_item +{ + uleb128_t static_fields_size; /* Quantité de champs statiques*/ + uleb128_t instance_fields_size; /* Qté de champs instanciables */ + uleb128_t direct_methods_size; /* Qté de méthodes propres */ + uleb128_t virtual_methods_size; /* Qté de méthodes virtuelles */ + + encoded_field *static_fields; /* Champs statiques */ + encoded_field *instance_fields; /* Champs instanciables */ + encoded_method *direct_methods; /* Méthodes propres */ + encoded_method *virtual_methods; /* Méthodes virtuelles */ + +} class_data_item; + + + +/* --------------------------- PORTION DE CODE EXECUTABLE --------------------------- */ + + +/* Description de la zone */ +typedef struct _code_item +{ + uint16_t registers_size; /* Qté de registres utilisés */ + uint16_t ins_size; /* Nbre d'arguments en entrée */ + uint16_t outs_size; /* Nbre d'arguments en sortie */ + uint16_t tries_size; /* Qté de try/catch */ + uint32_t debug_info_off; /* Information de débogage */ + uint32_t insns_size; /* Nbre de blocs de 2 octets */ + + uint16_t *insns; /* Code exécutable */ + + +} code_item; + + + + +/* -------------------------- 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 + + +/* 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; + + + +#endif /* _FORMAT_DEX_DEX_DEF_H */ diff --git a/src/format/dex/method.c b/src/format/dex/method.c new file mode 100644 index 0000000..3a604d0 --- /dev/null +++ b/src/format/dex/method.c @@ -0,0 +1,193 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * method.c - manipulation des methodes du format DEX + * + * Copyright (C) 2010 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 "method.h" + + +#include "dex-int.h" +#include "pool.h" + + + + + +/* Methode issue du code source (instance) */ +struct _GDexMethod +{ + GObject parent; /* A laisser en premier */ + + GBinRoutine *routine; /* Représentation interne */ + + code_item body; /* Corps de la méthode */ + off_t offset; /* Position du code */ + +}; + +/* Methode issue du code source (classe) */ +struct _GDexMethodClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une methode issue du code. */ +static void g_dex_method_class_init(GDexMethodClass *); + +/* Procède à l'initialisation d'une methode issue du code. */ +static void g_dex_method_init(GDexMethod *); + + + + + + + + + + +/* Détermine le type d'une methode issue du code source. */ +G_DEFINE_TYPE(GDexMethod, g_dex_method, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une methode issue du code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_method_class_init(GDexMethodClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : method = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une methode issue du code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_method_init(GDexMethod *method) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* seed = graine des informations à extraire. * +* * +* Description : Crée une nouvelle représentation de methode issue de code. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexMethod *g_dex_method_new(const GDexFormat *format, const encoded_method *seed) +{ + GDexMethod *result; /* Composant à retourner */ + off_t offset; /* Tête de lecture */ + code_item item; /* Corps de la méthode */ + + + GBinRoutine *routine; + + offset = seed->code_off; + + if (!read_dex_code_item(format, &offset, &item)) + return NULL; + + result = g_object_new(G_TYPE_DEX_METHOD, NULL); + + result->body = item; + + //printf(" method idx :: %d\n", seed->method_idx_diff); + //printf(" code size :: %d\n", item.insns_size); + + + routine = get_routine_from_dex_pool(format, seed->method_idx_diff); + + + + result->offset = seed->code_off + 4 * sizeof(uint16_t) + 2 *sizeof(uint32_t);/* TODO : faire plus propre ! */ + + + + g_binary_routine_set_address(routine, result->offset); + + + g_binary_format_add_routine(G_BIN_FORMAT(format), routine); + + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : method = représentation interne du format DEX à consulter. * +* * +* Description : Fournit la zone binaire correspondant à la méthode. * +* * +* Retour : Zone binaire à analyser. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPart *g_dex_method_as_part(const GDexMethod *method) +{ + GBinPart *result; /* Instance à retourner */ + + result = g_binary_part_new(); + + g_binary_part_set_name(result, "name"); + + g_binary_part_set_values(result, + method->offset, method->body.insns_size * sizeof(uint16_t), method->offset); + + return result; + +} + + + diff --git a/src/format/dex/method.h b/src/format/dex/method.h new file mode 100644 index 0000000..dd6f4b1 --- /dev/null +++ b/src/format/dex/method.h @@ -0,0 +1,68 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * method.h - prototypes pour la manipulation des methodes du format DEX + * + * Copyright (C) 2010 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 _FORMAT_DEX_METHOD_H +#define _FORMAT_DEX_METHOD_H + + +#include <glib-object.h> + + +#include "dex.h" +#include "dex_def.h" + + + +#define G_TYPE_DEX_METHOD (g_dex_method_get_type()) +#define G_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_METHOD, GDexMethod)) +#define G_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_METHOD, GDexMethodClass)) +#define G_IS_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_METHOD)) +#define G_IS_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_METHOD)) +#define G_DEX_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_METHOD, GDexMethodClass)) + + + +/* Methode issue du code source (instance) */ +typedef struct _GDexMethod GDexMethod; + +/* Methode issue du code source (classe) */ +typedef struct _GDexMethodClass GDexMethodClass; + + + +/* Détermine le type d'une methode issue du code source. */ +GType g_dex_method_get_type(void); + +/* Crée une nouvelle représentation de methode issue de code. */ +GDexMethod *g_dex_method_new(const GDexFormat *, const encoded_method *); + +/* Fournit la zone binaire correspondant à la méthode. */ +GBinPart *g_dex_method_as_part(const GDexMethod *); + + + + + + + +#endif /* _FORMAT_DEX_METHOD_H */ diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c new file mode 100644 index 0000000..0a8bed3 --- /dev/null +++ b/src/format/dex/pool.c @@ -0,0 +1,197 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pool.c - extraction des informations issues des tables globales + * + * Copyright (C) 2010 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 "pool.h" + + +#include "dex-int.h" +#include "../mangling/demangler.h" + + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index du type recherchée. * +* * +* Description : Extrait une représentation de type d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GOpenidaType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index) +{ + off_t pos; /* Tête de lecture */ + type_id_item type_id; /* Définition de la classe */ + string_id_item str_id; /* Identifiant de chaîne */ + string_data_item str_data; /* Description de chaîne */ + + + //printf("Index :: 0x%04hx\n", index); + + + pos = format->header.type_ids_off + index * sizeof(type_id_item); + + if (!read_dex_type_id_item(format, &pos, &type_id)) + return NULL; + + + + + pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item); + + if (!read_dex_string_id_item(format, &pos, &str_id)) + return NULL; + + pos = str_id.string_data_off; + + if (!read_dex_string_data_item(format, &pos, &str_data)) + return NULL; + + + //printf(">> String :: '%s'\n", str_data.data); + + + return demangle_type(DGT_JAVA, (char *)str_data.data); + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la classe recherchée. * +* * +* Description : Extrait une représentation de classe d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GOpenidaType *get_class_from_dex_pool(const GDexFormat *format, uint16_t index) +{ + GOpenidaType *result; /* Instance à retourner */ + off_t pos; /* Tête de lecture */ + class_def_item class_def; /* Définition de la classe */ + + pos = format->header.class_defs_off + index * sizeof(class_def_item); + + if (!read_dex_class_def_item(format, &pos, &class_def)) + return NULL; + + + + result = NULL; + + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la routine recherchée. * +* * +* Description : Extrait une représentation de routine d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uleb128_t index) +{ + GBinRoutine *result; /* Instance à retourner */ + off_t pos; /* Tête de lecture */ + method_id_item meth_id; /* Description de la méthode */ + + + GOpenidaType *type; + + string_id_item str_id; /* Identifiant de chaîne */ + string_data_item str_data; /* Description de chaîne */ + + pos = format->header.method_ids_off + index * sizeof(method_id_item); + + if (!read_dex_method_id_item(format, &pos, &meth_id)) + return NULL; + + + + + + + type = get_type_from_dex_pool(format, meth_id.class_idx); + + /* + if (type == NULL) + printf("class is nil\n"); + + else + printf("class = '%s'\n", g_openida_type_to_string(type)); + */ + + /* Nom de la méthode */ + + pos = format->header.string_ids_off + meth_id.name_idx * sizeof(string_id_item); + + if (!read_dex_string_id_item(format, &pos, &str_id)) + return NULL; + + pos = str_id.string_data_off; + + if (!read_dex_string_data_item(format, &pos, &str_data)) + return NULL; + + + //printf("String :: '%s'\n", str_data.data); + + + result = g_binary_routine_new(); + + g_binary_routine_set_name(result, (char *)str_data.data); + + if (type != NULL) + g_binary_routine_set_namespace(result, type); + + + //printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result)); + + return result; + +} diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h new file mode 100644 index 0000000..a41a1da --- /dev/null +++ b/src/format/dex/pool.h @@ -0,0 +1,48 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pool.h - prototypes pour l'extraction des informations issues des tables globales + * + * Copyright (C) 2010 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 _FORMAT_DEX_POOL_H +#define _FORMAT_DEX_POOL_H + + +#include "dex.h" +#include "../../analysis/routine.h" +#include "../../common/leb128.h" + + + +/* Extrait une représentation de type d'une table DEX. */ +GOpenidaType *get_type_from_dex_pool(const GDexFormat *, uint16_t); + + +/* Extrait une représentation de classe d'une table DEX. */ +GOpenidaType *get_class_from_dex_pool(const GDexFormat *, uint16_t); + + + +/* Extrait une représentation de routine d'une table DEX. */ +GBinRoutine *get_routine_from_dex_pool(const GDexFormat *, uleb128_t); + + + +#endif /* _FORMAT_DEX_POOL_H */ diff --git a/src/format/executable.h b/src/format/executable.h index 2042df4..c90ccfe 100644 --- a/src/format/executable.h +++ b/src/format/executable.h @@ -37,6 +37,7 @@ typedef enum _FormatTargetMachine { FTM_NONE, /* Aucune archi. (reconnue) */ + FTM_DALVIK, /* Dalvik Virtual Machine */ FTM_JVM, /* Java Virtual Machine */ FTM_MIPS, /* Mips 32 ou 64 bits */ FTM_386, /* Intel 80386 */ diff --git a/src/format/format-int.h b/src/format/format-int.h index 13eb50a..319f5cd 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -57,7 +57,7 @@ struct _GBinFormatClass /* Définit le contenu binaire à analyser. */ -void g_binary_format_set_content(GBinFormat *, bin_t *, off_t); +void g_binary_format_set_content(GBinFormat *, const bin_t *, off_t); diff --git a/src/format/format.c b/src/format/format.c index df375fb..c53e7aa 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -28,6 +28,7 @@ #include "format-int.h" +#include "dex/dex.h" #include "dwarf/dwarf.h" #include "elf/elf.h" #include "java/java.h" @@ -145,7 +146,7 @@ static void g_binary_format_init(GBinFormat *format) * * ******************************************************************************/ -void g_binary_format_set_content(GBinFormat *format, bin_t *content, off_t length) +void g_binary_format_set_content(GBinFormat *format, const bin_t *content, off_t length) { format->content = content; format->length = length; @@ -334,8 +335,9 @@ bool g_binary_format_resolve_symbol(const GBinFormat *format, const char **label bool init_all_formats(void) { + register_format(FID_DEX, _("Dalvik Executable"), FMT_EXEC, dex_is_matching, g_dex_format_new); + //register_format(FID_DWARF, _("Dwarf"), FMT_DEBUG, dwarf_is_matching, g_dwarf_format_new); register_format(FID_ELF, _("ELF"), FMT_EXEC, elf_is_matching, g_elf_format_new); - register_format(FID_DWARF, _("Dwarf"), FMT_DEBUG, dwarf_is_matching, g_dwarf_format_new); register_format(FID_JAVA, _("Java"), FMT_EXEC, java_is_matching, g_java_format_new); register_format(FID_PE, _("PE"), FMT_EXEC, pe_is_matching, g_pe_format_new); diff --git a/src/format/format.h b/src/format/format.h index 05a2af9..0223525 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -81,8 +81,9 @@ bool g_binary_format_resolve_symbol(const GBinFormat *, const char **, SymbolTyp /* Identifiants pour les différents formats */ typedef enum _FormatIdentifier { + FID_DEX, /* Format DEX */ + //FID_DWARF, /* Format Dwarf */ FID_ELF, /* Format ELF */ - FID_DWARF, /* Format Dwarf */ FID_JAVA, /* Format Java */ FID_PE, /* Format PE */ diff --git a/src/format/java/java-int.h b/src/format/java/java-int.h index 20ddf3c..40ed675 100755 --- a/src/format/java/java-int.h +++ b/src/format/java/java-int.h @@ -63,4 +63,4 @@ bool read_java_header(const GJavaFormat *, off_t *, java_header *); -#endif /* _FORMAT_JAVA_E_JAVA_INT_H */ +#endif /* _FORMAT_JAVA_JAVA_INT_H */ diff --git a/src/format/mangling/Makefile.am b/src/format/mangling/Makefile.am index 994919d..6298743 100644 --- a/src/format/mangling/Makefile.am +++ b/src/format/mangling/Makefile.am @@ -1,11 +1,13 @@ -BUILT_SOURCES = itanium_gram.h +BUILT_SOURCES = itanium_gram.h libjavamangling_la-java_gram.h AM_YFLAGS = -d -noinst_LTLIBRARIES = libformatmangling.la +noinst_LTLIBRARIES = libjavamangling.la libformatmangling.la libformatmangling_la_SOURCES = \ + context-int.h \ + context.h context.c \ demangler.h demangler.c \ itanium.h \ itanium_gram.y \ @@ -13,6 +15,23 @@ libformatmangling_la_SOURCES = \ libformatmangling_la_LDFLAGS = +libformatmangling_la_LIBADD = \ + libjavamangling.la + + +# Partie Java + +libjavamangling_la_SOURCES = \ + java.h \ + java_gram.y \ + java_tok.l + +libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c + +libjavamangling_la_LFLAGS = -P java_ -o lex.yy.c + + + INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) @@ -22,4 +41,5 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) # Automake fait les choses à moitié -CLEANFILES = itanium_gram.h itanium_gram.c itanium_tok.c +CLEANFILES = itanium_gram.h itanium_gram.c itanium_tok.c \ + java_gram.h java_gram.c libjavamangling_la-java_tok.c diff --git a/src/format/mangling/context-int.h b/src/format/mangling/context-int.h new file mode 100644 index 0000000..e8e6ec0 --- /dev/null +++ b/src/format/mangling/context-int.h @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.h - prototypes internes liés aux contextes de décodage + * + * Copyright (C) 2010 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 _FORMAT_MANGLING_CONTEXT_INT_H +#define _FORMAT_MANGLING_CONTEXT_INT_H + + +#include "context.h" + + + +/* Contexte de décodage (instance) */ +struct _GDemanglingContext +{ + GObject parent; /* A laisser en premier */ + + union + { + GOpenidaType *type; /* Type décodé */ + }; + +}; + +/* Contexte de décodage (classe) */ +struct _GDemanglingContextClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _FORMAT_MANGLING_CONTEXT_INT_H */ diff --git a/src/format/mangling/context.c b/src/format/mangling/context.c new file mode 100644 index 0000000..0d57937 --- /dev/null +++ b/src/format/mangling/context.c @@ -0,0 +1,95 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.c - fourniture de contexte aux phases de décodage + * + * Copyright (C) 2010 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 "context.h" + + +#include "context-int.h" + + + +/* Initialise la classe des contextes de décodage. */ +static void g_demangling_context_class_init(GDemanglingContextClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_demangling_context_init(GDemanglingContext *); + + + +/* Indique le type défini pour un contexte de décodage. */ +G_DEFINE_TYPE(GDemanglingContext, g_demangling_context, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_class_init(GDemanglingContextClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_init(GDemanglingContext *context) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à consulter. * +* * +* Description : Fournit le type créé à l'issue du codage. * +* * +* Retour : Instance en place ou NULL en cas d'erreur fatale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GOpenidaType *g_demangling_context_get_decoded_type(const GDemanglingContext *context) +{ + return context->type; + +} diff --git a/src/format/mangling/context.h b/src/format/mangling/context.h new file mode 100644 index 0000000..3ede4da --- /dev/null +++ b/src/format/mangling/context.h @@ -0,0 +1,57 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * context.h - prototypes pour la fourniture de contexte aux phases de décodage + * + * Copyright (C) 2010 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 _FORMAT_MANGLING_CONTEXT_H +#define _FORMAT_MANGLING_CONTEXT_H + + +#include <glib-object.h> + + +#include "../../analysis/routine.h" + + + +#define G_TYPE_DEMANGLING_CONTEXT g_demangling_context_get_type() +#define G_DEMANGLING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_demangling_context_get_type(), GDemanglingContext)) +#define G_IS_DEMANGLING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_demangling_context_get_type())) +#define G_DEMANGLING_CONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_demangling_context_get_type(), GDemanglingContextIface)) +#define G_DEMANGLING_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEMANGLING_CONTEXT, GDemanglingContextClass)) + + +/* Contexte de décodage (instance) */ +typedef struct _GDemanglingContext GDemanglingContext; + +/* Contexte de décodage (classe) */ +typedef struct _GDemanglingContextClass GDemanglingContextClass; + + +/* Indique le type défini pour un contexte de décodage. */ +GType g_demangling_context_get_type(void); + +/* Fournit le type créé à l'issue du codage. */ +GOpenidaType *g_demangling_context_get_decoded_type(const GDemanglingContext *); + + + +#endif /* _FORMAT_MANGLING_CONTEXT_H */ diff --git a/src/format/mangling/demangler.c b/src/format/mangling/demangler.c index e8b6b0f..47ffd36 100644 --- a/src/format/mangling/demangler.c +++ b/src/format/mangling/demangler.c @@ -29,79 +29,90 @@ #include "demangler-int.h" #include "itanium.h" +#include "java.h" -static name_demangler **demanglers = NULL; -static size_t demanglers_count = 0; +/* Prépare de quoi effectuer un décodage. */ +typedef GDemanglingContext * (* create_context_fc) (void); +/* Procède au décodage d'une chaîne de caractères. */ +typedef bool (* demangle_type_fc) (GDemanglingContext *, const char *); -/* Enregistre un nouveau décodeur de noms. */ -void register_new_demangler(name_demangler *); +/* Appels liés à un décodeur */ +typedef struct _demangling_properties +{ + create_context_fc create_context; /* Création de contextes */ + demangle_type_fc demangle_type; /* Décodage d'un type */ +} demangling_properties; -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Procède au chargement des différents décodeurs de noms. * -* * -* Retour : true pour indiquer un chargement réussi, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ -bool init_all_demanglers(void) -{ - register_new_demangler(create_itanium_demangler()); +/* Liste des décodeurs */ +static demangling_properties demanglers[DGT_COUNT] = { - return true; + [DGT_ITANIUM] = { + .create_context = (create_context_fc)NULL, + .demangle_type = (demangle_type_fc)NULL + }, + + [DGT_JAVA] = { + .create_context = (create_context_fc)g_java_dcontext_new, + .demangle_type = (demangle_type_fc)demangle_java_type + } + +}; -} /****************************************************************************** * * -* Paramètres : demangler = décodeur opérationnel. * +* Paramètres : type = identifiant du décodeur visé. * * * -* Description : Enregistre un nouveau décodeur de noms. * +* Description : Fournit la référence correspondant à un décodeur donné. * * * -* Retour : - * +* Retour : Adresse du décodeur trouvé ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -void register_new_demangler(name_demangler *demangler) +name_demangler *get_demangler_by_type(DemanglerType type) { - demanglers = (name_demangler **)realloc(demanglers, ++demanglers_count * sizeof(name_demangler *)); - demanglers[demanglers_count - 1] = demangler; + name_demangler *result; /* Adresse à retourner */ + + result = NULL;//demanglers[0]; + + return result; } /****************************************************************************** * * -* Paramètres : type = identifiant du décodeur visé. * +* Paramètres : demangler = décodeur à utiliser. * +* name = chaîne de caractères à décoder. * * * -* Description : Fournit la référence correspondant à un décodeur donné. * +* Description : Tente de décoder une chaîne de caractères donnée. * * * -* Retour : Adresse du décodeur trouvé ou NULL. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -name_demangler *get_demangler_by_type(DemanglerType type) +GBinRoutine *try_to_demangle_routine(name_demangler *demangler, const char *name) { - name_demangler *result; /* Adresse à retourner */ - - result = demanglers[0]; + GBinRoutine *result; /* Construction à remonter */ + result = NULL; + /* + if (demangler->can_be_demangled(demangler, name)) + result = demangler->demangle_routine(demangler, name); + */ return result; } @@ -109,8 +120,8 @@ name_demangler *get_demangler_by_type(DemanglerType type) /****************************************************************************** * * -* Paramètres : demangler = décodeur à utiliser. * -* name = chaîne de caractères à décoder. * +* Paramètres : type = type de décodeur à utiliser. * +* desc = chaîne de caractères à décoder. * * * * Description : Tente de décoder une chaîne de caractères donnée. * * * @@ -120,14 +131,26 @@ name_demangler *get_demangler_by_type(DemanglerType type) * * ******************************************************************************/ -GBinRoutine *try_to_demangle_routine(name_demangler *demangler, const char *name) +GOpenidaType *demangle_type(DemanglerType type, const char *desc) { - GBinRoutine *result; /* Construction à remonter */ + GOpenidaType *result; /* Construction à remonter */ + GDemanglingContext *context; /* Contexte pour le décodage */ result = NULL; - + /* if (demangler->can_be_demangled(demangler, name)) result = demangler->demangle_routine(demangler, name); + */ + + context = demanglers[type].create_context(); + + if (demanglers[type].demangle_type(context, desc)) + { + result = g_demangling_context_get_decoded_type(context); + g_object_ref(result); + } + + g_object_unref(context); return result; diff --git a/src/format/mangling/demangler.h b/src/format/mangling/demangler.h index fb23f16..0cdadb5 100644 --- a/src/format/mangling/demangler.h +++ b/src/format/mangling/demangler.h @@ -35,7 +35,10 @@ /* Identifiant des décodeurs existants */ typedef enum _DemanglerType { - DGT_ITANIUM /* Gnu V3 */ + DGT_ITANIUM, /* Gnu V3 */ + DGT_JAVA, /* Java / DEX */ + + DGT_COUNT } DemanglerType; @@ -45,9 +48,6 @@ typedef struct _name_demangler name_demangler; -/* Procède au chargement des différents décodeurs de noms. */ -bool init_all_demanglers(void); - /* Fournit la référence correspondant à un décodeur donné. */ name_demangler *get_demangler_by_type(DemanglerType); @@ -55,5 +55,9 @@ name_demangler *get_demangler_by_type(DemanglerType); GBinRoutine *try_to_demangle_routine(name_demangler *, const char *); +/* Tente de décoder une chaîne de caractères donnée. */ +GOpenidaType *demangle_type(DemanglerType, const char *); + + #endif /* _FORMAT_MANGLING_DEMANGLER_H */ diff --git a/src/format/mangling/java.h b/src/format/mangling/java.h new file mode 100644 index 0000000..08dafe3 --- /dev/null +++ b/src/format/mangling/java.h @@ -0,0 +1,59 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * java.h - prototypes pour le décodage des noms d'éléments selon Java + * + * Copyright (C) 2010 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 _FORMAT_MANGLING_JAVA_H +#define _FORMAT_MANGLING_JAVA_H + + +#include <stdbool.h> + + +#include "context.h" +#include "demangler.h" + + + +/* ------------------------- CONTEXTE POUR LE DECODAGE JAVA ------------------------- */ + + +/* Contexte de décodage Java (instance) */ +typedef struct _GJavaDContext GJavaDContext; + +/* Contexte de décodage Java (classe) */ +typedef struct _GJavaDContextClass GJavaDContextClass; + + +/* Prépare de quoi effectuer un décodage Java. */ +GDemanglingContext *g_java_dcontext_new(void); + + + + + + +/* Procède au décodage d'une chaîne de caractères. */ +bool demangle_java_type(GJavaDContext *, const char *); + + + +#endif /* _FORMAT_MANGLING_JAVA_H */ diff --git a/src/format/mangling/java_gram.y b/src/format/mangling/java_gram.y new file mode 100644 index 0000000..3522b01 --- /dev/null +++ b/src/format/mangling/java_gram.y @@ -0,0 +1,271 @@ + +%{ + + + +#include "context-int.h" +#include "demangler-int.h" +#include "java.h" + + + +/* ------------------------- CONTEXTE POUR LE DECODAGE JAVA ------------------------- */ + + +#define G_TYPE_JAVA_DCONTEXT g_java_dcontext_get_type() +#define G_JAVA_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_java_dcontext_get_type(), GJavaDContext)) +#define G_IS_JAVA_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_java_dcontext_get_type())) +#define G_JAVA_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_java_dcontext_get_type(), GJavaDContextIface)) +#define G_JAVA_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JAVA_DCONTEXT, GJavaDContextClass)) + + +/* Contexte de décodage Java (instance) */ +struct _GJavaDContext +{ + GDemanglingContext parent; /* A laisser en premier */ + +}; + +/* Contexte de décodage Java (classe) */ +struct _GJavaDContextClass +{ + GDemanglingContextClass parent; /* A laisser en premier */ + +}; + + +/* Indique le type défini pour un contexte de décodage. */ +static GType g_java_dcontext_get_type(void); + +/* Initialise la classe des contextes de décodage. */ +static void g_java_dcontext_class_init(GJavaDContextClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_java_dcontext_init(GJavaDContext *); + + + + + + + +%} + + +%union { + + void /*GOpenidaType*/ *type; + + char *text; /* Chaîne de caractères */ + +} + +%parse-param { GJavaDContext *context } + +%token V Z B S C I J F D +%token L SEMICOLON +%token SLASH DOLLAR +%token TEXT + +%type <type> type_descriptor field_type_descriptor non_array_field_type_descriptor full_class_name + +%type <text> TEXT + + +%{ + +/* De lexi.c... */ +/*int yylex(YYSTYPE *, YYLTYPE *);*/ +void java_restart(FILE *); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE java__scan_string(const char *); +extern void java__delete_buffer(YY_BUFFER_STATE); + + extern int java_lex (void); + + +/* Affiche un message d'erreur concernant l'analyse. */ +/*int yyerror(const YYLTYPE *, bool, char **, unsigned char *, char *);*/ + +%} + + +%% + + +input: + type_descriptor { G_DEMANGLING_CONTEXT(context)->type = $1; } + ; + +type_descriptor: + 'V' { $$ = g_basic_type_new(BTP_VOID); } + | field_type_descriptor { $$ = $1; } + ; + +field_type_descriptor: + non_array_field_type_descriptor { $$ = $1; } + ; + +non_array_field_type_descriptor: + Z { $$ = g_basic_type_new(BTP_BOOL); } + | B { $$ = g_basic_type_new(BTP_UCHAR); } + | S { $$ = g_basic_type_new(BTP_SHORT); } + | C { $$ = g_basic_type_new(BTP_CHAR); } + | I { $$ = g_basic_type_new(BTP_INT); } + | J { $$ = g_basic_type_new(BTP_LONG); } + | F { $$ = g_basic_type_new(BTP_FLOAT); } + | D { $$ = g_basic_type_new(BTP_DOUBLE); } + | L full_class_name SEMICOLON { $$ = $2; } + ; + +full_class_name: + TEXT { $$ = g_class_enum_type_new(CET_CLASS, $1); } + | full_class_name SLASH TEXT { + $$ = g_class_enum_type_new(CET_CLASS, $3); + g_openida_type_set_namespace($$, $1); + g_object_unref($1); + } + | full_class_name DOLLAR TEXT { + $$ = g_class_enum_type_new(CET_CLASS, $3); + g_openida_type_set_namespace($$, $1); + g_object_unref($1); + } + ; + + +%% + + + +/* ---------------------------------------------------------------------------------- */ +/* CONTEXTE POUR LE DECODAGE JAVA */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un contexte de décodage. */ +G_DEFINE_TYPE(GJavaDContext, g_java_dcontext, G_TYPE_DEMANGLING_CONTEXT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_dcontext_class_init(GJavaDContextClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_dcontext_init(GJavaDContext *context) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prépare de quoi effectuer un décodage Java. * +* * +* Retour : Instance du contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDemanglingContext *g_java_dcontext_new(void) +{ + GDemanglingContext *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_JAVA_DCONTEXT, NULL); + + return result; + +} + + + + + + + + + + + + + + + +/** + * Affiche un message d'erreur concernant l'analyse. + * @param yyloc informations concernant les coordonnées du soucis. + * @param hunt indique le type de passe réalisée. + * @param ucode code résultant compilé. + * @param index indice de commande à mettre à jour. + * @param msg indications humaines sur l'événement. + * @return 0. + */ +int java_error(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */char *msg) +{ + + + + fprintf(stderr, "ERREUR !\n"); + fprintf(stderr, "%s\n", msg); + + return -1; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* desc = chaîne de caractères à décoder. * +* * +* Description : Procède au décodage d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool demangle_java_type(GJavaDContext *context, const char *desc) +{ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + buffer = java__scan_string(desc); + ret = yyparse(context); + java__delete_buffer(buffer); + + return (ret == 0); + +} diff --git a/src/format/mangling/java_tok.l b/src/format/mangling/java_tok.l new file mode 100644 index 0000000..06777f9 --- /dev/null +++ b/src/format/mangling/java_tok.l @@ -0,0 +1,33 @@ + +%{ + +#include "libjavamangling_la-java_gram.h" + +%} + + +%option noyywrap +%option yylineno + +%x string + + +%% + +V { return V; } +Z { return Z; } +B { return B; } +S { return S; } +C { return C; } +I { return I; } +J { return J; } +F { return F; } +D { return D; } +L { printf("Got 'L'\n"); BEGIN(string); return L; } +<string>[/] { printf("Got '/'\n"); return SLASH; } +<string>[$] { printf("Got '$'\n"); return DOLLAR; } +<string>[;] { BEGIN(INITIAL); return SEMICOLON; } + +<string>[A-Za-z0-9]* { java_lval.text = yytext; printf("Got text:'%s'\n", yytext); return TEXT; } + +%% @@ -33,7 +33,6 @@ #include "project.h" #include "arch/processor.h" #include "format/format.h" -#include "format/mangling/demangler.h" #include "glibext/delayed.h" #include "gtkext/support.h" #include "plugins/pglist.h" @@ -103,7 +102,6 @@ int main(int argc, char **argv) /* Initialisation du programme */ init_all_processors(); - init_all_demanglers(); init_all_formats(); /* Création de l'interface */ |