diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-10-01 15:55:39 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-10-01 15:55:39 (GMT) |
commit | d51fef170f00602744e55a8fdb21a3c7d196696a (patch) | |
tree | 5f51c1cdb09669da974c1b99d280a4e7078aab7f | |
parent | 9aa5b354e83825e2d9843aea742aa62221a2130b (diff) |
Rewritten the whole support of DEX file format.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@581 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r-- | ChangeLog | 68 | ||||
-rw-r--r-- | plugins/mobicore/mclf.c | 58 | ||||
-rw-r--r-- | src/analysis/variable.c | 2 | ||||
-rw-r--r-- | src/arch/dalvik/decomp/invoke.c | 2 | ||||
-rw-r--r-- | src/arch/dalvik/operands/pool.c | 2 | ||||
-rw-r--r-- | src/core/formats.c | 5 | ||||
-rw-r--r-- | src/format/Makefile.am | 2 | ||||
-rw-r--r-- | src/format/dex/class.c | 291 | ||||
-rw-r--r-- | src/format/dex/class.h | 14 | ||||
-rw-r--r-- | src/format/dex/dex-int.c | 370 | ||||
-rwxr-xr-x | src/format/dex/dex-int.h | 51 | ||||
-rwxr-xr-x | src/format/dex/dex.c | 364 | ||||
-rwxr-xr-x | src/format/dex/dex.h | 6 | ||||
-rwxr-xr-x | src/format/dex/dex_def.h | 2 | ||||
-rw-r--r-- | src/format/dex/method.c | 156 | ||||
-rw-r--r-- | src/format/dex/method.h | 9 | ||||
-rw-r--r-- | src/format/dex/pool.c | 472 | ||||
-rw-r--r-- | src/format/dex/pool.h | 31 | ||||
-rw-r--r-- | src/format/elf/elf.c | 19 | ||||
-rw-r--r-- | src/format/executable-int.c | 69 | ||||
-rw-r--r-- | src/format/executable-int.h | 26 | ||||
-rw-r--r-- | src/format/executable.c | 5 | ||||
-rwxr-xr-x | src/format/java/java.c | 124 | ||||
-rw-r--r-- | src/format/pe/pe.c | 63 | ||||
-rw-r--r-- | src/gui/menus/project.c | 16 |
25 files changed, 1288 insertions, 939 deletions
@@ -1,3 +1,71 @@ +15-10-01 Cyrille Bagard <nocbos@gmail.com> + + * plugins/mobicore/mclf.c: + * src/analysis/variable.c: + * src/arch/dalvik/decomp/invoke.c: + * src/arch/dalvik/operands/pool.c: + Update code. + + * src/core/formats.c: + Add support for the DEX format. + + * 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/method.c: + * src/format/dex/method.h: + * src/format/dex/pool.c: + * src/format/dex/pool.h: + Rewrite the whole support of DEX file format. + + * src/format/elf/elf.c: + * src/format/executable.c: + Update code. + + * src/format/executable-int.c: + New entry: provide generic translations for machines without virtual + addresses. + + * src/format/executable-int.h: + * src/format/java/java.c: + Update code. + + * src/format/Makefile.am: + Add the 'executable-int.c' file to libformat_la_SOURCES. + + * src/format/pe/pe.c: + * src/gui/menus/project.c: + Update code. + +15-10-01 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + Add the new Makefile from the 'src/format/mangling/dex' directory. + + * src/format/mangling/Makefile.am: + Include 'dex/libformatmanglingdex.la' into libformatmangling_la_LIBADD + and add 'dex' to SUBDIRS. + + * src/format/mangling/context-int.h: + * src/format/mangling/context.c: + * src/format/mangling/context.h: + * src/format/mangling/demangler.c: + * src/format/mangling/demangler.h: + Update code into a more GLib-friendly direction. + + * src/format/mangling/dex/Makefile.am: + * src/format/mangling/dex/context.c: + * src/format/mangling/dex/context.h: + * src/format/mangling/dex/shorty_gram.y: + * src/format/mangling/dex/shorty_tok.l: + * src/format/mangling/dex/type_gram.y: + * src/format/mangling/dex/type_tok.l: + New entries: decode mangled names in a way suitable for the DEX format. + 15-09-28 Cyrille Bagard <nocbos@gmail.com> * src/analysis/content.c: diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c index 4ff44bb..7b1249c 100644 --- a/plugins/mobicore/mclf.c +++ b/plugins/mobicore/mclf.c @@ -44,6 +44,12 @@ static void g_mclf_format_class_init(GMCLFFormatClass *); /* Initialise une instance de format d'exécutable MCLF. */ static void g_mclf_format_init(GMCLFFormat *); +/* Supprime toutes les références externes. */ +static void g_mclf_format_dispose(GMCLFFormat *); + +/* Procède à la libération totale de la mémoire. */ +static void g_mclf_format_finalize(GMCLFFormat *); + /* Indique le type d'architecture visée par le format. */ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *); @@ -111,6 +117,18 @@ G_DEFINE_TYPE(GMCLFFormat, g_mclf_format, G_TYPE_EXE_FORMAT); static void g_mclf_format_class_init(GMCLFFormatClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + GExeFormatClass *exe; /* Version en exécutable */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_mclf_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_mclf_format_finalize; + + exe = G_EXE_FORMAT_CLASS(klass); + + exe->get_machine = (get_target_machine_fc)g_mclf_format_get_target_machine; + exe->refine_portions = (refine_portions_fc)g_mclf_format_refine_portions; } @@ -129,12 +147,44 @@ static void g_mclf_format_class_init(GMCLFFormatClass *klass) static void g_mclf_format_init(GMCLFFormat *format) { - GExeFormat *exe_format; /* Format parent à constituer */ - exe_format = G_EXE_FORMAT(format); +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mclf_format_dispose(GMCLFFormat *format) +{ + G_OBJECT_CLASS(g_mclf_format_parent_class)->dispose(G_OBJECT(format)); + +} - exe_format->get_machine = (get_target_machine_fc)g_mclf_format_get_target_machine; - exe_format->refine_portions = (refine_portions_fc)g_mclf_format_refine_portions; + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mclf_format_finalize(GMCLFFormat *format) +{ + G_OBJECT_CLASS(g_mclf_format_parent_class)->finalize(G_OBJECT(format)); } diff --git a/src/analysis/variable.c b/src/analysis/variable.c index 682f5f5..a8f1ba5 100644 --- a/src/analysis/variable.c +++ b/src/analysis/variable.c @@ -128,7 +128,7 @@ GBinVariable *g_binary_variable_new(GDataType *type) result = g_object_new(G_TYPE_BIN_VARIABLE, NULL); result->type = type; - g_object_ref(G_OBJECT(type)); + ///// A retirer /// g_object_ref(G_OBJECT(type)); return result; diff --git a/src/arch/dalvik/decomp/invoke.c b/src/arch/dalvik/decomp/invoke.c index d82e741..c20d439 100644 --- a/src/arch/dalvik/decomp/invoke.c +++ b/src/arch/dalvik/decomp/invoke.c @@ -35,6 +35,8 @@ #include "../../../format/dex/pool.h" +#define get_routine_from_dex_pool(p, i) NULL + /****************************************************************************** diff --git a/src/arch/dalvik/operands/pool.c b/src/arch/dalvik/operands/pool.c index 3537cd6..2f5c4a0 100644 --- a/src/arch/dalvik/operands/pool.c +++ b/src/arch/dalvik/operands/pool.c @@ -328,7 +328,7 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *operand, GBuff break; case DPT_METHOD: - routine = get_routine_from_dex_pool(operand->format, operand->index); + routine = NULL;//get_routine_from_dex_pool(operand->format, operand->index); if (routine != NULL) { diff --git a/src/core/formats.c b/src/core/formats.c index 1326fc4..5543331 100644 --- a/src/core/formats.c +++ b/src/core/formats.c @@ -29,6 +29,7 @@ #include <string.h> +#include "../format/dex/dex.h" #include "../format/dwarf/dwarf.h" #include "../format/dwarf/v2/dwarf.h" #include "../format/dwarf/v3/dwarf.h" @@ -195,12 +196,16 @@ bool load_hard_coded_formats_definitions(void) /* Détections */ + result &= register_format_matcher(dex_is_matching, NULL); + result &= register_format_matcher(dwarf_is_matching, NULL); result &= register_format_matcher(elf_is_matching, NULL); /* Chargements */ + result &= register_format_loader("dex", "Dalvik Executable format", g_dex_format_new); + result &= register_format_loader("dwarf_v2", "Debugging With Arbitrary Record Formats (v2)", g_dwarfv2_format_new); diff --git a/src/format/Makefile.am b/src/format/Makefile.am index a3402ee..3f18b88 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libformat.la libformat_la_SOURCES = \ debuggable-int.h \ debuggable.h debuggable.c \ - executable-int.h \ + executable-int.h executable-int.c \ executable.h executable.c \ format-int.h \ format.h format.c \ diff --git a/src/format/dex/class.c b/src/format/dex/class.c index b866cd7..657461f 100644 --- a/src/format/dex/class.c +++ b/src/format/dex/class.c @@ -33,11 +33,6 @@ - - - - - /* Classe issue du code source (instance) */ struct _GDexClass { @@ -66,17 +61,14 @@ 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); - -/* Inscrit les méthodes d'une classe en tant que routines. */ -static void g_dex_class_register_method(const GDexClass *, GBinFormat *); - - - - +/* Supprime toutes les références externes. */ +static void g_dex_class_dispose(GDexClass *); +/* Procède à la libération totale de la mémoire. */ +static void g_dex_class_finalize(GDexClass *); +/* Inscrit les méthodes d'une classe en tant que routines. */ +//static void g_dex_class_register_method(const GDexClass *, GBinFormat *); @@ -84,7 +76,6 @@ static void g_dex_class_register_method(const GDexClass *, GBinFormat *); G_DEFINE_TYPE(GDexClass, g_dex_class, G_TYPE_OBJECT); - /****************************************************************************** * * * Paramètres : class = classe de composant GLib à initialiser. * @@ -99,6 +90,12 @@ G_DEFINE_TYPE(GDexClass, g_dex_class, G_TYPE_OBJECT); static void g_dex_class_class_init(GDexClassClass *class) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_class_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_class_finalize; } @@ -123,8 +120,64 @@ static void g_dex_class_init(GDexClass *class) /****************************************************************************** * * +* Paramètres : class = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_dispose(GDexClass *class) +{ + size_t i; /* Boucle de parcours */ + + if (class->direct_methods != NULL) + for (i = 0; i < class->dmethods_count; i++) + if (class->direct_methods[i] != NULL) + g_object_unref(G_OBJECT(class->direct_methods[i])); + + if (class->virtual_methods != NULL) + for (i = 0; i < class->vmethods_count; i++) + if (class->virtual_methods[i] != NULL) + g_object_unref(G_OBJECT(class->virtual_methods[i])); + + G_OBJECT_CLASS(g_dex_class_parent_class)->dispose(G_OBJECT(class)); + +} + + +/****************************************************************************** +* * +* Paramètres : class = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_finalize(GDexClass *class) +{ + if (class->direct_methods != NULL) + free(class->direct_methods); + + if (class->virtual_methods != NULL) + free(class->virtual_methods); + + G_OBJECT_CLASS(g_dex_class_parent_class)->finalize(G_OBJECT(class)); + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * -* offset = tête de lecture des données initiale. * +* def = définitions générales associées à la classe. * * * * Description : Crée une nouvelle représentation de classe issue de code. * * * @@ -134,120 +187,66 @@ static void g_dex_class_init(GDexClass *class) * * ******************************************************************************/ -static GDexClass *g_dex_class_new(const GDexFormat *format, off_t offset) +GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) { GDexClass *result; /* Composant à retourner */ - class_def_item def; /* Définition de la classe */ + vmpa2t addr; /* Tête de lecture générique */ class_data_item data; /* Contenu de la classe */ uleb128_t index; /* Conservation du dernier id */ uleb128_t i; /* Boucle de parcours */ GDexMethod *method; /* Méthode chargée */ - if (!read_dex_class_def_item(format, &offset, &def)) - return NULL; + init_vmpa(&addr, def->class_data_off, VMPA_NO_VIRTUAL); - offset = def.class_data_off; - - if (!read_dex_class_data_item(format, &offset, &data)) + if (!read_dex_class_data_item(format, &addr, &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); - result->definition = def; + result->definition = *def; + + /** + * On évite ici les méthodes (virtuelles) non définies. + */ + if (def->access_flags & ACC_ANNOTATION) goto gdcn_done; index = 0; + result->dmethods_count = data.direct_methods_size; + result->direct_methods = (GDexMethod **)calloc(result->dmethods_count, sizeof(GDexMethod *)); + for (i = 0; i < data.direct_methods_size; i++) { method = g_dex_method_new(format, &data.direct_methods[i], &index); + if (method == NULL) goto gdcn_bad_method; - 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; - - } + result->direct_methods[i] = method; } index = 0; + result->vmethods_count = data.virtual_methods_size; + result->virtual_methods = (GDexMethod **)calloc(result->vmethods_count, sizeof(GDexMethod *)); + for (i = 0; i < data.virtual_methods_size; i++) { method = g_dex_method_new(format, &data.virtual_methods[i], &index); + if (method == NULL) goto gdcn_bad_method; - 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; - - } + result->virtual_methods[i] = method; } - + gdcn_done: return result; -} + gdcn_bad_method: + g_object_unref(G_OBJECT(result)); -/****************************************************************************** -* * -* Paramètres : class = informations chargées à consulter. * -* format = format binaire à compléter. * -* * -* Description : Inscrit les méthodes d'une classe en tant que routines. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_dex_class_register_method(const GDexClass *class, GBinFormat *format) -{ - size_t i; /* Boucle de parcours */ - GBinRoutine *routine; /* Routine à inscrire */ - - for (i = 0; i < class->dmethods_count; i++) - { - routine = g_dex_method_get_routine(class->direct_methods[i]); - g_binary_format_add_routine(format, routine); - - /* - printf("routine @ 0x%08llx :: '%s'\n", - g_binary_routine_get_address(routine), - g_binary_routine_get_name(routine)); - */ - - } - - for (i = 0; i < class->vmethods_count; i++) - { - routine = g_dex_method_get_routine(class->virtual_methods[i]); - g_binary_format_add_routine(format, routine); - - /* - printf("routine @ 0x%08llx :: '%s'\n", - g_binary_routine_get_address(routine), - g_binary_routine_get_name(routine)); - */ - - } + return NULL; } @@ -310,47 +309,27 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t /****************************************************************************** * * * Paramètres : class = informations chargées à consulter. * -* parts = liste à venir compléter. * -* count = quantité de zones listées. [OUT] * +* raw = portion de binaire brut à raffiner. * * * -* Description : Fournit les références aux zones binaires à analyser. * +* Description : Intègre la méthode en tant que portion de code. * * * -* Retour : Zones binaires à analyser. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -#if 0 -GBinPart **g_dex_class_get_parts(const GDexClass *class, GBinPart **parts, size_t *count) + +void g_dex_class_include_as_portion(const GDexClass *class, GBinPortion *raw) { 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; - - } + g_dex_method_include_as_portion(class->direct_methods[i], raw); 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; + g_dex_method_include_as_portion(class->virtual_methods[i], raw); } -#endif - - - /****************************************************************************** @@ -428,7 +407,7 @@ const char *g_dex_class_get_source_file(const GDexClass *class, const GDexFormat void g_dex_class_decompile(const GDexClass *class, GLangOutput *lang, GCodeBuffer *buffer, const GDexFormat *format) { - +#if 0 GDataType *type; @@ -482,7 +461,7 @@ GBufferLine *line, GLangOutput *output) - +#endif } @@ -500,69 +479,3 @@ GBufferLine *line, GLangOutput *output) - - -/****************************************************************************** -* * -* 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; - -} - - -/****************************************************************************** -* * -* Paramètres : format = représentation interne du format DEX à compléter. * -* * -* Description : Enregistre toutes les méthodes des classes listées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_all_dex_class_methods(GDexFormat *format) -{ - size_t i; /* Boucle de parcours */ - GBinFormat *bformat; /* Autre version du format */ - - bformat = G_BIN_FORMAT(format); - - for (i = 0; i < format->classes_count; i++) - g_dex_class_register_method(format->classes[i], bformat); - -} diff --git a/src/format/dex/class.h b/src/format/dex/class.h index 8125b91..77fa6ba 100644 --- a/src/format/dex/class.h +++ b/src/format/dex/class.h @@ -54,14 +54,17 @@ typedef struct _GDexClassClass GDexClassClass; /* Détermine le type d'une classe issue du code source. */ GType g_dex_class_get_type(void); +/* Crée une nouvelle représentation de classe issue de code. */ +GDexClass *g_dex_class_new(GDexFormat *, const class_def_item *); + /* Dénombre les méthodes chargées d'un type donné. */ size_t g_dex_class_count_methods(const GDexClass *, bool); /* Fournit une méthode chargée correspondant à un type donné. */ GDexMethod *g_dex_class_get_method(const GDexClass *, bool, size_t); -/* Fournit les références aux zones binaires à analyser. */ -//GBinPart **g_dex_class_get_parts(const GDexClass *, GBinPart **, size_t *); +/* Intègre la méthode en tant que portion de code. */ +void g_dex_class_include_as_portion(const GDexClass *, GBinPortion *); /* Retrouve si possible la méthode associée à une adresse. */ GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t); @@ -76,13 +79,6 @@ void g_dex_class_decompile(const GDexClass *, GLangOutput *, GCodeBuffer *, cons -/* Charge toutes les classes listées dans le contenu binaire. */ -bool load_all_dex_classes(GDexFormat *); - -/* Enregistre toutes les méthodes des classes listées. */ -void register_all_dex_class_methods(GDexFormat *); - - #endif /* _FORMAT_DEX_CLASS_H */ diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c index 5ce0675..79cdc57 100644 --- a/src/format/dex/dex-int.c +++ b/src/format/dex/dex-int.c @@ -51,48 +51,46 @@ * * ******************************************************************************/ -bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) +bool read_dex_header(const GDexFormat *format, vmpa2t *pos, dex_header *header) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ size_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; for (i = 0; i < DEX_FILE_MAGIC_LEN && result; i++) - result = read_u8(&header->magic[i], content, pos, length); + result = g_binary_content_read_u8(content, pos, &header->magic[i]); - result &= read_u32(&header->checksum, content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->checksum); for (i = 0; i < 20 && result; i++) - result = read_u8(&header->signature[i], content, pos, length); - - 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); + result = g_binary_content_read_u8(content, pos, &header->signature[i]); + + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->file_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->header_size); + + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->endian_tag); + + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->link_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->map_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->string_ids_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->type_ids_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->proto_ids_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->field_ids_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->method_ids_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->class_defs_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &header->data_off); return result; @@ -119,18 +117,14 @@ bool read_dex_header(const GDexFormat *format, off_t *pos, dex_header *header) * * ******************************************************************************/ -bool read_dex_string_id_item(const GDexFormat *format, off_t *pos, string_id_item *str_id) +bool read_dex_string_id_item(const GDexFormat *format, vmpa2t *pos, string_id_item *str_id) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ - result = true; - - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u32(&str_id->string_data_off, content, pos, length, SRE_LITTLE); + result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &str_id->string_data_off); return result; @@ -151,20 +145,17 @@ bool read_dex_string_id_item(const GDexFormat *format, off_t *pos, string_id_ite * * ******************************************************************************/ -bool read_dex_string_data_item(const GDexFormat *format, off_t *pos, string_data_item *str_data) +bool read_dex_string_data_item(const GDexFormat *format, vmpa2t *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; + GBinContent *content; /* Contenu binaire à lire */ - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_uleb128(&str_data->utf16_size, content, pos, length); + result = g_binary_content_read_uleb128(content, pos, &str_data->utf16_size); - str_data->data = &content[*pos]; + if (result) + str_data->data = g_binary_content_get_raw_access(content, pos, str_data->utf16_size); return result; @@ -185,18 +176,14 @@ bool read_dex_string_data_item(const GDexFormat *format, off_t *pos, string_data * * ******************************************************************************/ -bool read_dex_type_id_item(const GDexFormat *format, off_t *pos, type_id_item *item) +bool read_dex_type_id_item(const GDexFormat *format, vmpa2t *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; + GBinContent *content; /* Contenu binaire à lire */ - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u32(&item->descriptor_idx, content, pos, length, SRE_LITTLE); + result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->descriptor_idx); return result; @@ -217,20 +204,16 @@ bool read_dex_type_id_item(const GDexFormat *format, off_t *pos, type_id_item *i * * ******************************************************************************/ -bool read_dex_proto_id_item(const GDexFormat *format, off_t *pos, proto_id_item *proto_id) +bool read_dex_proto_id_item(const GDexFormat *format, vmpa2t *pos, proto_id_item *proto_id) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ - - result = true; + GBinContent *content; /* Contenu binaire à lire */ - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u32(&proto_id->shorty_idx, content, pos, length, SRE_LITTLE); - result &= read_u32(&proto_id->return_type_idx, content, pos, length, SRE_LITTLE); - result &= read_u32(&proto_id->parameters_off, content, pos, length, SRE_LITTLE); + result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->shorty_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->return_type_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &proto_id->parameters_off); return result; @@ -251,20 +234,16 @@ bool read_dex_proto_id_item(const GDexFormat *format, off_t *pos, proto_id_item * * ******************************************************************************/ -bool read_dex_field_id_item(const GDexFormat *format, off_t *pos, field_id_item *field_id) +bool read_dex_field_id_item(const GDexFormat *format, vmpa2t *pos, field_id_item *field_id) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ - result = true; - - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u16(&field_id->class_idx, content, pos, length, SRE_LITTLE); - result &= read_u16(&field_id->type_idx, content, pos, length, SRE_LITTLE); - result &= read_u32(&field_id->name_idx, content, pos, length, SRE_LITTLE); + result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->class_idx); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &field_id->type_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &field_id->name_idx); return result; @@ -285,20 +264,16 @@ bool read_dex_field_id_item(const GDexFormat *format, off_t *pos, field_id_item * * ******************************************************************************/ -bool read_dex_method_id_item(const GDexFormat *format, off_t *pos, method_id_item *meth_id) +bool read_dex_method_id_item(const GDexFormat *format, vmpa2t *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; + GBinContent *content; /* Contenu binaire à lire */ - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - 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); + result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->class_idx); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &meth_id->proto_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &meth_id->name_idx); return result; @@ -319,25 +294,21 @@ bool read_dex_method_id_item(const GDexFormat *format, off_t *pos, method_id_ite * * ******************************************************************************/ -bool read_dex_class_def_item(const GDexFormat *format, off_t *pos, class_def_item *class_def) +bool read_dex_class_def_item(const GDexFormat *format, vmpa2t *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; + GBinContent *content; /* Contenu binaire à lire */ - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - 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); + result = g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->access_flags); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->superclass_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->interfaces_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->source_file_idx); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->annotations_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->class_data_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &class_def->static_values_off); return result; @@ -364,19 +335,17 @@ bool read_dex_class_def_item(const GDexFormat *format, off_t *pos, class_def_ite * * ******************************************************************************/ -bool read_dex_encoded_field(const GDexFormat *format, off_t *pos, encoded_field *field) +bool read_dex_encoded_field(const GDexFormat *format, vmpa2t *pos, encoded_field *field) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_uleb128(&field->field_idx_diff, content, pos, length); - result &= read_uleb128(&field->access_flags, content, pos, length); + result &= g_binary_content_read_uleb128(content, pos, &field->field_idx_diff); + result &= g_binary_content_read_uleb128(content, pos, &field->access_flags); return result; @@ -397,20 +366,18 @@ bool read_dex_encoded_field(const GDexFormat *format, off_t *pos, encoded_field * * ******************************************************************************/ -bool read_dex_encoded_method(const GDexFormat *format, off_t *pos, encoded_method *method) +bool read_dex_encoded_method(const GDexFormat *format, vmpa2t *pos, encoded_method *method) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - 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); + result &= g_binary_content_read_uleb128(content, pos, &method->method_idx_diff); + result &= g_binary_content_read_uleb128(content, pos, &method->access_flags); + result &= g_binary_content_read_uleb128(content, pos, &method->code_off); return result; @@ -431,18 +398,14 @@ bool read_dex_encoded_method(const GDexFormat *format, off_t *pos, encoded_metho * * ******************************************************************************/ -bool read_dex_type_item(const GDexFormat *format, off_t *pos, type_item *item) +bool read_dex_type_item(const GDexFormat *format, vmpa2t *pos, type_item *item) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ - result = true; - - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u16(&item->type_idx, content, pos, length, SRE_LITTLE); + result = g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->type_idx); return result; @@ -463,21 +426,19 @@ bool read_dex_type_item(const GDexFormat *format, off_t *pos, type_item *item) * * ******************************************************************************/ -bool read_dex_type_list(const GDexFormat *format, off_t *pos, type_list *list) +bool read_dex_type_list(const GDexFormat *format, vmpa2t *pos, type_list *list) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u32(&list->size, content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &list->size); - list->list = (type_item *)&content[*pos]; - result &= ((*pos + list->size * sizeof(type_item)) <= length); + list->list = (type_item *)g_binary_content_get_raw_access(content, pos, list->size * sizeof(type_item)); + result &= (list->list != NULL); return result; @@ -498,27 +459,25 @@ bool read_dex_type_list(const GDexFormat *format, off_t *pos, type_list *list) * * ******************************************************************************/ -bool read_dex_class_data_item(const GDexFormat *format, off_t *pos, class_data_item *item) +bool read_dex_class_data_item(const GDexFormat *format, vmpa2t *pos, class_data_item *item) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ uleb128_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //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); + content = G_BIN_FORMAT(format)->content; + + result &= g_binary_content_read_uleb128(content, pos, &item->static_fields_size); + result &= g_binary_content_read_uleb128(content, pos, &item->instance_fields_size); + result &= g_binary_content_read_uleb128(content, pos, &item->direct_methods_size); + result &= g_binary_content_read_uleb128(content, pos, &item->virtual_methods_size); if (result && item->static_fields_size > 0) { @@ -617,19 +576,17 @@ void reset_dex_class_data_item(class_data_item *item) * * ******************************************************************************/ -bool read_dex_encoded_type_addr_pair(const GDexFormat *format, off_t *pos, encoded_type_addr_pair *pair) +bool read_dex_encoded_type_addr_pair(const GDexFormat *format, vmpa2t *pos, encoded_type_addr_pair *pair) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_uleb128(&pair->type_idx, content, pos, length); - result &= read_uleb128(&pair->addr, content, pos, length); + result &= g_binary_content_read_uleb128(content, pos, &pair->type_idx); + result &= g_binary_content_read_uleb128(content, pos, &pair->addr); return result; @@ -650,22 +607,20 @@ bool read_dex_encoded_type_addr_pair(const GDexFormat *format, off_t *pos, encod * * ******************************************************************************/ -bool read_dex_encoded_catch_handler(const GDexFormat *format, off_t *pos, encoded_catch_handler *handler) +bool read_dex_encoded_catch_handler(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler *handler) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ leb128_t count; /* Nombre de gestionnaires */ leb128_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - handler->offset = *pos; + handler->offset = get_phy_addr(pos); - result &= read_leb128(&handler->size, content, pos, length); + result &= g_binary_content_read_leb128(content, pos, &handler->size); count = leb128_abs(handler->size); @@ -680,7 +635,8 @@ bool read_dex_encoded_catch_handler(const GDexFormat *format, off_t *pos, encode else handler->handlers = NULL; if (handler->size < 0) - result &= read_uleb128(&handler->catch_all_addr, content, pos, length); + result &= g_binary_content_read_uleb128(content, pos, &handler->catch_all_addr); + else handler->catch_all_addr = ULEB128_MAX; @@ -723,22 +679,20 @@ void reset_dex_encoded_catch_handler(encoded_catch_handler *handler) * * ******************************************************************************/ -bool read_dex_encoded_catch_handler_list(const GDexFormat *format, off_t *pos, encoded_catch_handler_list *list) +bool read_dex_encoded_catch_handler_list(const GDexFormat *format, vmpa2t *pos, encoded_catch_handler_list *list) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ off_t saved_off; /* Sauvegarde de position */ + GBinContent *content; /* Contenu binaire à lire */ uleb128_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + saved_off = get_phy_addr(pos); - saved_off = *pos; + content = G_BIN_FORMAT(format)->content; - result &= read_uleb128(&list->size, content, pos, length); + result &= g_binary_content_read_uleb128(content, pos, &list->size); if (list->size > 0 && result) { @@ -800,20 +754,18 @@ void reset_dex_encoded_catch_handler_list(encoded_catch_handler_list *list) * * ******************************************************************************/ -bool read_dex_try_item(const GDexFormat *format, off_t *pos, try_item *item) +bool read_dex_try_item(const GDexFormat *format, vmpa2t *pos, try_item *item) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; - result &= read_u32(&item->start_addr, content, pos, length, SRE_LITTLE); - result &= read_u16(&item->insn_count, content, pos, length, SRE_LITTLE); - result &= read_u16(&item->handler_off, content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->start_addr); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->insn_count); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->handler_off); return result; @@ -834,33 +786,29 @@ bool read_dex_try_item(const GDexFormat *format, off_t *pos, try_item *item) * * ******************************************************************************/ -bool read_dex_code_item(const GDexFormat *format, off_t *pos, code_item *item) +bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ uint16_t padding; /* Eventuel alignement */ uint16_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //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); + content = G_BIN_FORMAT(format)->content; - item->insns = (uint16_t *)pos; + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->registers_size); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->ins_size); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->outs_size); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &item->tries_size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->debug_info_off); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->insns_size); - *pos += item->insns_size * sizeof(uint16_t); + item->insns = (uint16_t *)g_binary_content_get_raw_access(content, pos, item->insns_size * sizeof(uint16_t)); /* Padding ? */ if (item->tries_size > 0 && item->insns_size % 2 == 1) - result &= read_u16(&padding, content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &padding); if (item->tries_size > 0 && result) { @@ -928,30 +876,28 @@ void reset_dex_code_item(code_item *item) * * ******************************************************************************/ -bool read_dex_packed_switch(const GDexFormat *format, off_t *pos, packed_switch *packed) +bool read_dex_packed_switch(const GDexFormat *format, vmpa2t *pos, packed_switch *packed) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ uint16_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; - packed->targets = NULL; - result &= read_u16(&packed->ident, content, pos, length, SRE_LITTLE); - result &= read_u16(&packed->size, content, pos, length, SRE_LITTLE); - result &= read_u32(&packed->first_key, content, pos, length, SRE_LITTLE); + content = G_BIN_FORMAT(format)->content; + + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->ident); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &packed->size); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->first_key); if (result && packed->size > 0) { packed->targets = (uint32_t *)calloc(packed->size, sizeof(uint32_t)); for (i = 0; i < packed->size && result; i++) - result &= read_u32(&packed->targets[i], content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &packed->targets[i]); } @@ -997,23 +943,21 @@ void reset_dex_packed_switch(packed_switch *packed) * * ******************************************************************************/ -bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch *sparse) +bool read_dex_sparse_switch(const GDexFormat *format, vmpa2t *pos, sparse_switch *sparse) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ uint16_t i; /* Boucle de parcours */ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; sparse->keys = NULL; sparse->targets = NULL; - result &= read_u16(&sparse->ident, content, pos, length, SRE_LITTLE); - result &= read_u16(&sparse->size, content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->ident); + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &sparse->size); if (result && sparse->size > 0) { @@ -1021,10 +965,10 @@ bool read_dex_sparse_switch(const GDexFormat *format, off_t *pos, sparse_switch sparse->targets = (uint32_t *)calloc(sparse->size, sizeof(uint32_t)); for (i = 0; i < sparse->size && result; i++) - result &= read_u32(&sparse->keys[i], content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->keys[i]); for (i = 0; i < sparse->size && result; i++) - result &= read_u32(&sparse->targets[i], content, pos, length, SRE_LITTLE); + result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &sparse->targets[i]); } @@ -1073,19 +1017,21 @@ void reset_dex_sparse_switch(sparse_switch *sparse) * * ******************************************************************************/ -bool read_dex_switch(const GDexFormat *format, off_t *pos, dex_switch *dswitch) +bool read_dex_switch(const GDexFormat *format, vmpa2t *pos, dex_switch *dswitch) { bool result; /* Bilan à retourner */ - const bin_t *content; /* Contenu binaire à lire */ - off_t length; /* Taille totale du contenu */ + GBinContent *content; /* Contenu binaire à lire */ uint16_t ident; /* Pseudo-code d'identification*/ result = true; - content = NULL; //G_BIN_FORMAT(format)->content; - length = 0; //G_BIN_FORMAT(format)->length; + content = G_BIN_FORMAT(format)->content; + + result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &ident); - result &= read_u16(&ident, content, (off_t []) { *pos }, length, SRE_LITTLE); + /** + * La tête de lecture n'est pas mise à jour volontairement ! + */ if (result) { diff --git a/src/format/dex/dex-int.h b/src/format/dex/dex-int.h index 1803e05..28aadd5 100755 --- a/src/format/dex/dex-int.h +++ b/src/format/dex/dex-int.h @@ -41,12 +41,11 @@ struct _GDexFormat dex_header header; /* En-tête du programme */ - - + GDataType **types; /* Types partagés pour Dalvik */ + GBinVariable **fields; /* Champs de données partagés */ + GBinRoutine **prototypes; /* Routines vierges à décorer */ + GDexMethod **methods; /* Méthodes retrouvées */ GDexClass **classes; /* Classes retrouvées */ - size_t classes_count; /* Nombre de ces classes */ - - }; @@ -72,7 +71,7 @@ GDexClass *g_dex_format_get_class(const GDexFormat *, size_t); /* Procède à la lecture d'une en-tête de programme DEX. */ -bool read_dex_header(const GDexFormat *, off_t *, dex_header *); +bool read_dex_header(const GDexFormat *, vmpa2t *, dex_header *); @@ -80,25 +79,25 @@ bool read_dex_header(const GDexFormat *, off_t *, dex_header *); /* Procède à la lecture d'un identifiant de chaîne DEX. */ -bool read_dex_string_id_item(const GDexFormat *, off_t *, string_id_item *); +bool read_dex_string_id_item(const GDexFormat *, vmpa2t *, 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 *); +bool read_dex_string_data_item(const GDexFormat *, vmpa2t *, 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 *); +bool read_dex_type_id_item(const GDexFormat *, vmpa2t *, type_id_item *); /* Procède à la lecture d'une description de prototype. */ -bool read_dex_proto_id_item(const GDexFormat *, off_t *, proto_id_item *); +bool read_dex_proto_id_item(const GDexFormat *, vmpa2t *, proto_id_item *); /* Procède à la lecture d'une description de champ. */ -bool read_dex_field_id_item(const GDexFormat *, off_t *, field_id_item *); +bool read_dex_field_id_item(const GDexFormat *, vmpa2t *, field_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 *); +bool read_dex_method_id_item(const GDexFormat *, vmpa2t *, 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 *); +bool read_dex_class_def_item(const GDexFormat *, vmpa2t *, class_def_item *); @@ -106,19 +105,19 @@ bool read_dex_class_def_item(const GDexFormat *, off_t *, class_def_item *); /* Procède à la lecture d'un champ quelconque DEX. */ -bool read_dex_encoded_field(const GDexFormat *, off_t *, encoded_field *); +bool read_dex_encoded_field(const GDexFormat *, vmpa2t *, encoded_field *); /* Procède à la lecture d'une méthode quelconque DEX. */ -bool read_dex_encoded_method(const GDexFormat *, off_t *, encoded_method *); +bool read_dex_encoded_method(const GDexFormat *, vmpa2t *, encoded_method *); /* Procède à la lecture d'un type DEX. */ -bool read_dex_type_item(const GDexFormat *, off_t *, type_item *); +bool read_dex_type_item(const GDexFormat *, vmpa2t *, type_item *); /* Procède à la lecture d'une liste de types DEX. */ -bool read_dex_type_list(const GDexFormat *, off_t *, type_list *); +bool read_dex_type_list(const GDexFormat *, vmpa2t *, type_list *); /* Procède à la lecture d'un contenu de classe DEX. */ -bool read_dex_class_data_item(const GDexFormat *, off_t *, class_data_item *); +bool read_dex_class_data_item(const GDexFormat *, vmpa2t *, class_data_item *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_class_data_item(class_data_item *); @@ -129,25 +128,25 @@ void reset_dex_class_data_item(class_data_item *); /* Procède à la lecture d'une association exception <-> code. */ -bool read_dex_encoded_type_addr_pair(const GDexFormat *, off_t *, encoded_type_addr_pair *); +bool read_dex_encoded_type_addr_pair(const GDexFormat *, vmpa2t *, encoded_type_addr_pair *); /* Procède à la lecture d'une association exception <-> code. */ -bool read_dex_encoded_catch_handler(const GDexFormat *, off_t *, encoded_catch_handler *); +bool read_dex_encoded_catch_handler(const GDexFormat *, vmpa2t *, encoded_catch_handler *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_encoded_catch_handler(encoded_catch_handler *); /* Procède à la lecture d'une association exception <-> code. */ -bool read_dex_encoded_catch_handler_list(const GDexFormat *, off_t *, encoded_catch_handler_list *); +bool read_dex_encoded_catch_handler_list(const GDexFormat *, vmpa2t *, encoded_catch_handler_list *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_encoded_catch_handler_list(encoded_catch_handler_list *); /* Procède à la lecture d'une association exception <-> code. */ -bool read_dex_try_item(const GDexFormat *, off_t *, try_item *); +bool read_dex_try_item(const GDexFormat *, vmpa2t *, try_item *); /* Procède à la lecture d'une portion de code DEX. */ -bool read_dex_code_item(const GDexFormat *, off_t *, code_item *); +bool read_dex_code_item(const GDexFormat *, vmpa2t *, code_item *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_code_item(code_item *); @@ -158,19 +157,19 @@ void reset_dex_code_item(code_item *); /* Procède à la lecture d'un contenu d'aiguillage compact. */ -bool read_dex_packed_switch(const GDexFormat *, off_t *, packed_switch *); +bool read_dex_packed_switch(const GDexFormat *, vmpa2t *, packed_switch *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_packed_switch(packed_switch *); /* Procède à la lecture d'un contenu d'aiguillage dispersé. */ -bool read_dex_sparse_switch(const GDexFormat *, off_t *, sparse_switch *); +bool read_dex_sparse_switch(const GDexFormat *, vmpa2t *, sparse_switch *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_sparse_switch(sparse_switch *); /* Procède à la lecture d'un contenu d'aiguillage Dex interne. */ -bool read_dex_switch(const GDexFormat *, off_t *, dex_switch *); +bool read_dex_switch(const GDexFormat *, vmpa2t *, dex_switch *); /* Supprime tous les éléments chargés en mémoire à la lecture. */ void reset_dex_switch(dex_switch *); diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index 0015357..35ffe47 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -45,49 +45,81 @@ static void g_dex_format_class_init(GDexFormatClass *); /* Initialise une instance de format d'exécutable DEX. */ static void g_dex_format_init(GDexFormat *); -/* Détermine tous les fichiers source indiqués. */ -static void g_dex_format_find_all_sources(GDexFormat *); +/* Supprime toutes les références externes. */ +static void g_dex_format_dispose(GDexFormat *); -/* Procède à la décompilation complète du format. */ -static void g_dex_format_decompile(const GDexFormat *, GCodeBuffer *, const char *); +/* Procède à la libération totale de la mémoire. */ +static void g_dex_format_finalize(GDexFormat *); /* Indique le type d'architecture visée par le format. */ static const char *g_dex_format_get_target_machine(const GDexFormat *); -/* Fournit les références aux zones binaires à analyser. */ -//static GBinPart **g_dex_format_get_parts(const GDexFormat *, size_t *); +/* Etend la définition des portions au sein d'un binaire. */ +static void g_dex_format_refine_portions(const GDexFormat *, GBinPortion *); + +/* Fournit l'emplacement d'une section donnée. */ +static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_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 *); +/* Détermine tous les fichiers source indiqués. */ +//static void g_dex_format_find_all_sources(GDexFormat *); + +/* Procède à la décompilation complète du format. */ +static void g_dex_format_decompile(const GDexFormat *, GCodeBuffer *, const char *); /****************************************************************************** * * * Paramètres : content = contenu binaire à parcourir. * +* parent = éventuel format exécutable déjà chargé. * +* unused = adresse non utilisée ici. * +* key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Indique si le format peut être pris en charge ici. * * * -* Retour : true si la réponse est positive, false sinon. * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ -bool dex_is_matching(GBinContent *content) +FormatMatchStatus dex_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) { - bool result; /* Bilan à faire connaître */ + FormatMatchStatus result; /* Bilan à renvoyer */ vmpa2t addr; /* Tête de lecture initiale */ + bool status; /* Bilan des accès mémoire */ char magic[DEX_FILE_MAGIC_LEN]; /* Idenfiant standard */ + + /* REMME */ + if (parent != NULL) return FMS_UNKNOWN; + + init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); - result = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic); + status = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic); - result &= (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0); + status &= (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0); + + if (status) + { + result = FMS_MATCHED; + *key = strdup(parent == NULL ? "dex" : "dexdbg"); + } + else + result = FMS_UNKNOWN; return result; @@ -112,6 +144,23 @@ G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT); static void g_dex_format_class_init(GDexFormatClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + GExeFormatClass *exe; /* Version en exécutable */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_format_finalize; + + exe = G_EXE_FORMAT_CLASS(klass); + + exe->get_machine = (get_target_machine_fc)g_dex_format_get_target_machine; + exe->refine_portions = (refine_portions_fc)g_dex_format_refine_portions; + + exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa; + exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa; + + exe->get_range_by_name = (get_range_by_name_fc)g_dex_format_get_section_range_by_name; } @@ -130,19 +179,49 @@ static void g_dex_format_class_init(GDexFormatClass *klass) static void g_dex_format_init(GDexFormat *format) { - GExeFormat *exe_format; /* Format parent à compléter #1*/ - GBinFormat *bin_format; /* Format parent à compléter #2*/ + GBinFormat *bin_format; /* Format parent à compléter #1*/ bin_format = G_BIN_FORMAT(format); bin_format->decompile = (format_decompile_fc)g_dex_format_decompile; - exe_format = G_EXE_FORMAT(format); +} - exe_format->get_machine = (get_target_machine_fc)g_dex_format_get_target_machine; - 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 : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_dispose(GDexFormat *format) +{ + G_OBJECT_CLASS(g_dex_format_parent_class)->dispose(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_finalize(GDexFormat *format) +{ + G_OBJECT_CLASS(g_dex_format_parent_class)->finalize(G_OBJECT(format)); } @@ -150,9 +229,9 @@ static void g_dex_format_init(GDexFormat *format) /****************************************************************************** * * * Paramètres : content = contenu binaire à parcourir. * -* length = taille du contenu en question. * +* parent = éventuel format exécutable déjà chargé. * * * -* Description : Prend en charge un nouveau format DEX. * +* Description : Prend en charge un nouveau format Dex. * * * * Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* * * @@ -160,54 +239,127 @@ static void g_dex_format_init(GDexFormat *format) * * ******************************************************************************/ -GBinFormat *g_dex_format_new(const bin_t *content, off_t length) +GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) { GDexFormat *result; /* Structure à retourner */ - off_t offset; /* Tête de lecture */ + vmpa2t pos; /* Position de tête de lecture */ result = g_object_new(G_TYPE_DEX_FORMAT, NULL); - //g_binary_format_set_content(G_BIN_FORMAT(result), content, length); + g_binary_format_set_content(G_BIN_FORMAT(result), content); + init_vmpa(&pos, 0, VMPA_NO_VIRTUAL); - offset = 0; + if (!read_dex_header(result, &pos, &result->header)) + goto gdfn_error; - if (!read_dex_header(result, &offset, &result->header)) - { - /* TODO */ - return NULL; - } + if (!load_all_dex_types(result)) + goto gdfn_error; - /* TODO : vérifier l'en-tête ! */ + if (!load_all_dex_fields(result)) + goto gdfn_error; + if (!load_all_dex_prototypes(result)) + goto gdfn_error; + if (!load_all_dex_methods(result)) + goto gdfn_error; if (!load_all_dex_classes(result)) - { - g_object_unref(G_OBJECT(result)); - return NULL; - } + goto gdfn_error; - register_all_dex_class_methods(result); + return G_BIN_FORMAT(result); - g_dex_format_find_all_sources(result); + gdfn_error: + g_object_unref(G_OBJECT(result)); + exit(0); - if (!find_all_dex_strings(result)) - { - g_object_unref(G_OBJECT(result)); - return NULL; - } + 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 const char *g_dex_format_get_target_machine(const GDexFormat *format) +{ + return "dalvik"; + +} + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* raw = portion de binaire brut à raffiner. * +* * +* Description : Etend la définition des portions au sein d'un binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_refine_portions(const GDexFormat *format, GBinPortion *raw) +{ + size_t max; /* Nombre d'itérations prévues */ + size_t i; /* Boucle de parcours */ + + max = g_dex_format_count_classes(format); + + for (i = 0; i < max; i++) + g_dex_class_include_as_portion(format->classes[i], raw); } /****************************************************************************** * * +* Paramètres : format = description de l'exécutable à consulter. * +* name = nom de la section recherchée. * +* range = emplacement en mémoire à renseigner. [OUT] * +* * +* Description : Fournit l'emplacement d'une section donnée. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dex_format_get_section_range_by_name(const GDexFormat *format, const char *name, mrange_t *range) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + + + + + + + + + +/****************************************************************************** +* * * Paramètres : format = informations chargées à consulter. * * addr = adresse de la routine à retrouver. * * * @@ -221,6 +373,11 @@ GBinFormat *g_dex_format_new(const bin_t *content, off_t length) GDexMethod *g_dex_format_find_method_by_address(const GDexFormat *format, vmpa_t addr) { + + return NULL; + + +#if 0 GDexMethod *result; /* Trouvaille à retourner */ size_t i; /* Boucle de parcours */ @@ -230,6 +387,7 @@ GDexMethod *g_dex_format_find_method_by_address(const GDexFormat *format, vmpa_t result = g_dex_class_find_method_by_address(format->classes[i], addr); return result; +#endif } @@ -245,9 +403,12 @@ GDexMethod *g_dex_format_find_method_by_address(const GDexFormat *format, vmpa_t * Remarques : - * * * ******************************************************************************/ - +#if 0 static void g_dex_format_find_all_sources(GDexFormat *format) { + +#if 0 + GBinFormat *bf; /* Instance parente */ size_t i; /* Boucle de parcours #1 */ const char *source; /* Fichier source trouvé */ @@ -275,8 +436,10 @@ static void g_dex_format_find_all_sources(GDexFormat *format) } -} +#endif +} +#endif /****************************************************************************** * * @@ -294,6 +457,9 @@ static void g_dex_format_find_all_sources(GDexFormat *format) static void g_dex_format_decompile(const GDexFormat *format, GCodeBuffer *buffer, const char *filename) { + +#if 0 + GLangOutput *lang; /* Langage de sortie */ size_t i; /* Boucle de parcours */ const char *source; /* Fichier source trouvé */ @@ -328,106 +494,11 @@ char *_g_data_type_to_string(const GDataType *type, bool simple) } -} - - -/****************************************************************************** -* * -* 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 const char *g_dex_format_get_target_machine(const GDexFormat *format) -{ - return "dalvik"; - -} - - -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ -#if 0 -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; - -} #endif -/****************************************************************************** -* * -* 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; - -} - /****************************************************************************** * * @@ -443,7 +514,11 @@ static bool g_dex_format_translate_offset_into_address(const GDexFormat *format, size_t g_dex_format_count_classes(const GDexFormat *format) { + return 0; + +#if 0 return format->classes_count; +#endif } @@ -466,3 +541,8 @@ GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index) return format->classes[index]; } + + + + + diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h index 7f427a3..1ff3809 100755 --- a/src/format/dex/dex.h +++ b/src/format/dex/dex.h @@ -30,7 +30,7 @@ #include <sys/types.h> -#include "../format.h" +#include "../../core/formats.h" @@ -49,13 +49,13 @@ typedef struct _GDexFormatClass GDexFormatClass; /* Indique si le format peut être pris en charge ici. */ -bool dex_is_matching(GBinContent *); +FormatMatchStatus dex_is_matching(GBinContent *, GExeFormat *, void *, char **); /* 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); +GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *); /* Redéfinition : classe issue du code source (instance) */ typedef struct _GDexClass GDexClass; diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h index 09496b6..ea2cd60 100755 --- a/src/format/dex/dex_def.h +++ b/src/format/dex/dex_def.h @@ -250,7 +250,7 @@ typedef struct _encoded_catch_handler * structure efface la représentation physique, on conserve en mémoire * le décalage rencontré à la lecture dans un champ artificiel. */ - off_t offset; /* Position dans le binaire */ + phys_t offset; /* Position dans le binaire */ } encoded_catch_handler; diff --git a/src/format/dex/method.c b/src/format/dex/method.c index c721cea..c68e9e1 100644 --- a/src/format/dex/method.c +++ b/src/format/dex/method.c @@ -24,13 +24,15 @@ #include "method.h" +#include <i18n.h> + + #include "dex-int.h" #include "pool.h" - /* Methode issue du code source (instance) */ struct _GDexMethod { @@ -58,12 +60,11 @@ 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 *); +/* Supprime toutes les références externes. */ +static void g_dex_method_dispose(GDexMethod *); - - - - - +/* Procède à la libération totale de la mémoire. */ +static void g_dex_method_finalize(GDexMethod *); @@ -86,6 +87,12 @@ G_DEFINE_TYPE(GDexMethod, g_dex_method, G_TYPE_OBJECT); static void g_dex_method_class_init(GDexMethodClass *class) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_method_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_method_finalize; } @@ -110,6 +117,47 @@ static void g_dex_method_init(GDexMethod *method) /****************************************************************************** * * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_method_dispose(GDexMethod *method) +{ + if (method->routine != NULL) + g_object_unref(G_OBJECT(method->routine)); + + G_OBJECT_CLASS(g_dex_method_parent_class)->dispose(G_OBJECT(method)); + +} + + +/****************************************************************************** +* * +* Paramètres : method = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_method_finalize(GDexMethod *method) +{ + G_OBJECT_CLASS(g_dex_method_parent_class)->finalize(G_OBJECT(method)); + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * * seed = graine des informations à extraire. * * last = dernier indice utilisé (à mettre à jour). [OUT] * @@ -122,63 +170,63 @@ static void g_dex_method_init(GDexMethod *method) * * ******************************************************************************/ -GDexMethod *g_dex_method_new(const GDexFormat *format, const encoded_method *seed, uleb128_t *last) +GDexMethod *g_dex_method_new(GDexFormat *format, const encoded_method *seed, uleb128_t *last) { GDexMethod *result; /* Composant à retourner */ - off_t offset; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ code_item item; /* Corps de la méthode */ + GBinRoutine *routine; /* Routine représentée */ + mrange_t range; /* Emplacement du code associé */ + init_vmpa(&addr, seed->code_off, VMPA_NO_VIRTUAL); - GBinRoutine *routine; - - vmpa2t addr; - mrange_t range; - - - offset = seed->code_off; - - if (!read_dex_code_item(format, &offset, &item)) + if (!read_dex_code_item(format, &addr, &item)) return NULL; *last += seed->method_idx_diff; - routine = get_routine_from_dex_pool(format, *last); + routine = get_prototype_from_dex_pool(format, *last); if (routine == NULL) return NULL; - result = g_object_new(G_TYPE_DEX_METHOD, NULL); result->info = *seed; result->body = item; - //printf(" ==== (%p) %s ====\n", routine, g_binary_routine_to_string(routine)); - - //printf(" try ? %d\n", item.tries_size); + result->offset = seed->code_off + 4 * sizeof(uint16_t) + 2 *sizeof(uint32_t);/* TODO : faire plus propre ! */ - //printf(" method idx :: %d\n", seed->method_idx_diff); - //printf(" code size :: %d\n", item.insns_size); + init_vmpa(&addr, result->offset, VMPA_NO_VIRTUAL); + init_mrange(&range, &addr, item.insns_size * sizeof(uint16_t)); - /* - printf(" code regs :: %d\n", item.registers_size); - printf(" code ins :: %d\n", item.ins_size); - printf(" code outs :: %d\n", item.outs_size); - */ + g_binary_routine_set_range(routine, &range); - //printf(" method idx :: %lld\n", *last); + result->routine = routine; + return result; - result->offset = seed->code_off + 4 * sizeof(uint16_t) + 2 *sizeof(uint32_t);/* TODO : faire plus propre ! */ +} - //printf(" method off :: 0x%08x\n", result->offset); +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter.* +* method_id = informations de base quant à la méthode. * +* * +* Description : Crée une nouvelle représentation de methode vide. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ - init_vmpa(&addr, result->offset, VMPA_NO_VIRTUAL); - init_mrange(&range, &addr, item.insns_size * sizeof(uint16_t)); +GDexMethod *g_dex_method_new_empty(const GDexFormat *format, const method_id_item *method_id) +{ + GDexMethod *result; /* Composant à retourner */ - g_binary_routine_set_range(routine, &range); - result->routine = routine; + result = g_object_new(G_TYPE_DEX_METHOD, NULL); return result; @@ -246,33 +294,43 @@ GBinRoutine *g_dex_method_get_routine(const GDexMethod *method) /****************************************************************************** * * * Paramètres : method = représentation interne du format DEX à consulter. * +* raw = portion de binaire brut à raffiner. * * * -* Description : Fournit la zone binaire correspondant à la méthode. * +* Description : Intègre la méthode en tant que portion de code. * * * -* Retour : Zone binaire à analyser. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -#if 0 -GBinPart *g_dex_method_as_part(const GDexMethod *method) + +void g_dex_method_include_as_portion(const GDexMethod *method, GBinPortion *raw) { - GBinPart *result; /* Instance à retourner */ - off_t size; /* Taille du code associé */ + GBinPortion *new; /* Nouvelle portion définie */ + char *desc; /* Description d'une portion */ + vmpa2t addr; /* Emplacement dans le binaire */ - result = g_binary_part_new(); + /* Si la taille est nulle, on ne fait rien */ + if (method->info.access_flags & ACC_NATIVE) + return; - g_binary_part_set_name(result, "name"); + new = g_binary_portion_new(BPC_CODE); - if (method->info.access_flags & ACC_NATIVE) size = 0; - else size = method->body.insns_size * sizeof(uint16_t); + asprintf(&desc, _("Dalvik code")); - g_binary_part_set_values(result, method->offset, size, method->offset); + g_binary_portion_set_desc(new, desc); - return result; + free(desc); + + init_vmpa(&addr, method->offset, VMPA_NO_VIRTUAL); + g_binary_portion_set_values(new, &addr, method->body.insns_size * sizeof(uint16_t)); + + g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC); + + g_binary_portion_include(raw, new); } -#endif + /****************************************************************************** * * diff --git a/src/format/dex/method.h b/src/format/dex/method.h index 79e3077..dee33cb 100644 --- a/src/format/dex/method.h +++ b/src/format/dex/method.h @@ -67,7 +67,10 @@ typedef enum _DexVariableIndex 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 *, uleb128_t *); +GDexMethod *g_dex_method_new(GDexFormat *, const encoded_method *, uleb128_t *); + +/* Crée une nouvelle représentation de methode vide. */ +GDexMethod *g_dex_method_new_empty(const GDexFormat *, const method_id_item *); /* Fournit les indications Dex concernant la méthode. */ const encoded_method *g_dex_method_get_dex_info(const GDexMethod *); @@ -78,8 +81,8 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *); /* Fournit la routine OpenIDA correspondant à la méthode. */ GBinRoutine *g_dex_method_get_routine(const GDexMethod *); -/* Fournit la zone binaire correspondant à la méthode. */ -//GBinPart *g_dex_method_as_part(const GDexMethod *); +/* Intègre la méthode en tant que portion de code. */ +void g_dex_method_include_as_portion(const GDexMethod *, GBinPortion *); /* Indique la position de la méthode au sein du binaire. */ off_t g_dex_method_get_offset(const GDexMethod *); diff --git a/src/format/dex/pool.c b/src/format/dex/pool.c index a869873..904ab76 100644 --- a/src/format/dex/pool.c +++ b/src/format/dex/pool.c @@ -24,11 +24,13 @@ #include "pool.h" +#include <malloc.h> #include <string.h> #include "dex-int.h" #include "../mangling/demangler.h" +#include "../mangling/dex/context.h" @@ -83,6 +85,7 @@ bool find_all_dex_strings(GDexFormat *format) const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) { off_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ string_id_item str_id; /* Identifiant de chaîne */ string_data_item str_data; /* Description de chaîne */ @@ -90,13 +93,15 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) return NULL; pos = format->header.string_ids_off + index * sizeof(string_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) + if (!read_dex_string_id_item(format, &addr, &str_id)) return NULL; pos = str_id.string_data_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_data_item(format, &pos, &str_data)) + if (!read_dex_string_data_item(format, &addr, &str_data)) return NULL; return (const char *)str_data.data; @@ -109,6 +114,49 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) + + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge en mémoire l'ensemble des types du format DEX. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_types(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GDataType *type; /* Type récupéré */ + + result = true; + + format->types = (GDataType **)calloc(format->header.type_ids_size, sizeof(GDataType *)); + + for (i = 0; i < format->header.type_ids_size && result; i++) + { + type = get_type_from_dex_pool(format, i); + + if (type != NULL) + g_object_unref(G_OBJECT(type)); + else + result = false; + + } + + return result; + +} + + /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * @@ -122,89 +170,94 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index) +GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) { - off_t pos; /* Tête de lecture */ + GDataType *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ 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("Tp Index :: %hd / %d\n", index, format->header.type_ids_size); - + result = NULL; if (index >= format->header.type_ids_size) - return NULL; - - pos = format->header.type_ids_off + index * sizeof(type_id_item); + goto gtfdp_error; - if (!read_dex_type_id_item(format, &pos, &type_id)) - return NULL; + if (format->types[index] == NULL) + { + pos = format->header.type_ids_off + index * sizeof(type_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + if (!read_dex_type_id_item(format, &addr, &type_id)) + goto gtfdp_error; + pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + if (!read_dex_string_id_item(format, &addr, &str_id)) + goto gtfdp_error; - pos = format->header.string_ids_off + type_id.descriptor_idx * sizeof(string_id_item); + pos = str_id.string_data_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) - return NULL; + if (!read_dex_string_data_item(format, &addr, &str_data)) + goto gtfdp_error; - pos = str_id.string_data_off; + format->types[index] = demangle_type(G_TYPE_DEX_DEMANGLER, (char *)str_data.data); - if (!read_dex_string_data_item(format, &pos, &str_data)) - return NULL; + } + result = format->types[index]; - //printf(">> String :: '%s'\n", str_data.data); + if (result != NULL) + g_object_ref(G_OBJECT(result)); + gtfdp_error: - return demangle_type(DGT_JAVA, (char *)str_data.data); + return result; } - - - /****************************************************************************** * * -* Paramètres : format = représentation interne du format DEX à consulter. * -* index = index de la classe recherchée. * +* Paramètres : format = description de l'exécutable à compléter. * * * -* Description : Extrait une représentation de classe d'une table DEX. * +* Description : Charge en mémoire l'ensemble des champs du format DEX. * * * -* Retour : Composant GLib créé. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index) +bool load_all_dex_fields(GDexFormat *format) { - GDataType *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ - class_def_item class_def; /* Définition de la classe */ - - if (index >= format->header.class_defs_size) - return NULL; + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GBinVariable *field; /* Champ récupéré */ - pos = format->header.class_defs_off + index * sizeof(class_def_item); - - if (!read_dex_class_def_item(format, &pos, &class_def)) - return NULL; + result = true; + format->fields = (GBinVariable **)calloc(format->header.field_ids_size, sizeof(GBinVariable *)); + for (i = 0; i < format->header.field_ids_size && result; i++) + { + field = get_field_from_dex_pool(format, i); - result = NULL; + if (field != NULL) + g_object_unref(G_OBJECT(field)); + else + result = false; + } return result; } - - /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * @@ -218,48 +271,67 @@ GDataType *get_class_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) +GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) { GBinVariable *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ field_id_item field_id; /* Description du champ */ GDataType *type; /* Type du champ */ const char *name; /* Désignation humaine */ + GBinVariable *field; /* Instance nouvelle à définir */ GDataType *owner; /* Propriétaire du champ */ + result = NULL; + if (index >= format->header.field_ids_size) - return NULL; + goto gffdp_error; - pos = format->header.field_ids_off + index * sizeof(field_id_item); + if (format->fields[index] == NULL) + { + pos = format->header.field_ids_off + index * sizeof(field_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_field_id_item(format, &pos, &field_id)) - return NULL; + if (!read_dex_field_id_item(format, &addr, &field_id)) + goto gffdp_error; - type = get_type_from_dex_pool(format, field_id.type_idx); + type = get_type_from_dex_pool(format, field_id.type_idx); + if (type == NULL) goto gffdp_error; - name = get_string_from_dex_pool(format, field_id.name_idx); - if (name == NULL) goto bad_name; + name = get_string_from_dex_pool(format, field_id.name_idx); + if (name == NULL) goto gffdp_bad_name; - result = g_binary_variable_new(type); - g_binary_variable_set_name(result, name); + field = g_binary_variable_new(type); + g_binary_variable_set_name(field, name); - if (field_id.class_idx != NO_INDEX) - { - owner = get_type_from_dex_pool(format, field_id.class_idx); - if (owner == NULL) goto bad_owner; + if (field_id.class_idx != NO_INDEX) + { + owner = get_type_from_dex_pool(format, field_id.class_idx); + if (owner == NULL) goto gffdp_bad_owner; + + g_binary_variable_set_owner(field, owner); + + } - g_binary_variable_set_owner(result, owner); + format->fields[index] = field; } + result = format->fields[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + gffdp_error: + return result; - bad_owner: + gffdp_bad_owner: g_object_ref(G_OBJECT(type)); g_object_unref(G_OBJECT(result)); - bad_name: + gffdp_bad_name: g_object_unref(G_OBJECT(type)); @@ -270,6 +342,44 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) /****************************************************************************** * * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge tous les prototypes listés dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_prototypes(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GBinRoutine *proto; /* Prototype récupéré */ + + result = true; + + format->prototypes = (GBinRoutine **)calloc(format->header.proto_ids_size, sizeof(GBinRoutine *)); + + for (i = 0; i < format->header.proto_ids_size && result; i++) + { + proto = get_prototype_from_dex_pool(format, i); + + if (proto != NULL) + g_object_unref(G_OBJECT(proto)); + else + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = représentation interne du format DEX à consulter. * * index = index de la routine recherchée. * * * @@ -281,114 +391,244 @@ GBinVariable *get_field_from_dex_pool(const GDexFormat *format, uint32_t index) * * ******************************************************************************/ -GBinRoutine *get_routine_from_dex_pool(const GDexFormat *format, uint32_t index) +GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) { GBinRoutine *result; /* Instance à retourner */ - off_t pos; /* Tête de lecture */ - method_id_item meth_id; /* Description de la méthode */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + proto_id_item proto_id; /* Prototype de routine */ + GDataType *type; /* Type de retour */ + const char *name; /* Description compressée */ + type_list args; /* Liste des arguments */ + uint32_t i; /* Boucle de parcours */ + GBinVariable *arg; /* Argument reconstitué */ + if (index >= format->header.method_ids_size) + goto grfdp_error; - GDataType *type; + if (format->prototypes[index] == NULL) + { + pos = format->header.proto_ids_off + index * sizeof(proto_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - string_id_item str_id; /* Identifiant de chaîne */ - string_data_item str_data; /* Description de chaîne */ + if (!read_dex_proto_id_item(format, &addr, &proto_id)) + goto grfdp_error; + /* Type de retour */ - proto_id_item proto_id; /* Information de prototypage */ - type_list args; /* Liste des arguments */ + type = get_type_from_dex_pool(format, proto_id.return_type_idx); + + /* Nom de la méthode */ + + name = get_string_from_dex_pool(format, proto_id.shorty_idx); + + /* Liste des arguments */ + + pos = proto_id.parameters_off; + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); + + if (read_dex_type_list(format, &addr, &args)) + for (i = 0; i < args.size; i++) + { + type = get_type_from_dex_pool(format, args.list[i].type_idx); + if (type == NULL) continue; + + arg = g_binary_variable_new(type); + //g_binary_routine_add_arg(result, arg); + + } + + /* Mise en place finale */ + + format->prototypes[index] = demangle_routine(G_TYPE_DEX_DEMANGLER, name); + +#if 0 + if (format->prototypes[index] != NULL) + g_binary_routine_set_return_type(format->prototypes[index], type); +#endif + + } + + result = format->prototypes[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + grfdp_error: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à compléter. * +* * +* Description : Charge toutes les méthodes listées dans le contenu binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dex_methods(GDexFormat *format) +{ + bool result; /* Bilan à retourner */ uint32_t i; /* Boucle de parcours */ - GBinVariable *arg; /* Argument reconstitué */ + GDexMethod *method; /* Méthode récupérée */ - if (index >= format->header.method_ids_size) - return NULL; + result = true; - pos = format->header.method_ids_off + index * sizeof(method_id_item); + format->methods = (GDexMethod **)calloc(format->header.method_ids_size, sizeof(GDexMethod *)); - if (!read_dex_method_id_item(format, &pos, &meth_id)) - return NULL; + for (i = 0; i < format->header.method_ids_size && result; i++) + { + method = get_method_from_dex_pool(format, i); + if (method != NULL) + g_object_unref(G_OBJECT(method)); + else + result = false; + } + return result; +} - type = get_type_from_dex_pool(format, meth_id.class_idx); +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* index = index de la classe recherchée. * +* * +* Description : Extrait une représentation de méthode d'une table DEX. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ - /* - if (type == NULL) - printf("class is nil\n"); +GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index) +{ + GDexMethod *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + method_id_item method_id; /* Définition de la méthode */ - else - printf("class = '%s'\n", g_data_type_to_string(type)); - */ + result = NULL; - /* Nom de la méthode */ + if (index >= format->header.method_ids_size) + goto gmfdp_error; - pos = format->header.string_ids_off + meth_id.name_idx * sizeof(string_id_item); + if (format->methods[index] == NULL) + { + pos = format->header.method_ids_off + index * sizeof(method_id_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - if (!read_dex_string_id_item(format, &pos, &str_id)) - return NULL; + if (!read_dex_method_id_item(format, &addr, &method_id)) + goto gmfdp_error; - pos = str_id.string_data_off; + format->methods[index] = g_dex_method_new_empty(format, &method_id); - if (!read_dex_string_data_item(format, &pos, &str_data)) - return NULL; + } + result = format->methods[index]; - //printf("String :: '%s'\n", str_data.data); + if (result != NULL) + g_object_ref(G_OBJECT(result)); + gmfdp_error: - result = g_binary_routine_new(); + return result; - g_binary_routine_set_name(result, (char *)str_data.data); +} - if (type != NULL) - g_binary_routine_set_namespace(result, type); +/****************************************************************************** +* * +* 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) +{ + bool result; /* Bilan à retourner */ + uint32_t i; /* Boucle de parcours */ + GDexClass *class; /* Classe récupérée */ - /* - printf(" ####\n"); - printf(" #### ROUTINE '%s'\n", g_binary_routine_to_string(result)); - printf(" ####\n"); - printf(" ####\n"); - */ + result = true; - //printf("==>>> routine :: '%s'\n", g_binary_routine_to_string(result)); + format->classes = (GDexClass **)calloc(format->header.class_defs_size, sizeof(GDexClass *)); + for (i = 0; i < format->header.class_defs_size && result; i++) + { + class = get_class_from_dex_pool(format, i); + if (class != NULL) + g_object_unref(G_OBJECT(class)); + else + result = false; + } + return result; +} - /* Retour de la routine */ +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ - pos = format->header.proto_ids_off + meth_id.proto_idx * sizeof(proto_id_item); +GDexClass *get_class_from_dex_pool(GDexFormat *format, uint32_t index) +{ + GDexClass *result; /* Instance à retourner */ + phys_t pos; /* Tête de lecture */ + vmpa2t addr; /* Tête de lecture générique */ + class_def_item class_def; /* Définition de la classe */ - if (!read_dex_proto_id_item(format, &pos, &proto_id)) - goto no_more_info; + result = NULL; - type = get_type_from_dex_pool(format, proto_id.return_type_idx); + if (index >= format->header.class_defs_size) + goto gcfdp_error; - g_binary_routine_set_return_type(result, type); + if (format->classes[index] == NULL) + { + pos = format->header.class_defs_off + index * sizeof(class_def_item); + init_vmpa(&addr, pos, VMPA_NO_VIRTUAL); - /* Arguments de la routine */ + if (!read_dex_class_def_item(format, &addr, &class_def)) + goto gcfdp_error; - pos = proto_id.parameters_off; + format->classes[index] = g_dex_class_new(format, &class_def); - if (read_dex_type_list(format, &pos, &args)) - for (i = 0; i < args.size; i++) - { - type = get_type_from_dex_pool(format, args.list[i].type_idx); - if (type == NULL) continue; + } - arg = g_binary_variable_new(type); - g_binary_routine_add_arg(result, arg); + result = format->classes[index]; - } + if (result != NULL) + g_object_ref(G_OBJECT(result)); - no_more_info: + gcfdp_error: return result; diff --git a/src/format/dex/pool.h b/src/format/dex/pool.h index e947465..df02ed8 100644 --- a/src/format/dex/pool.h +++ b/src/format/dex/pool.h @@ -25,7 +25,9 @@ #define _FORMAT_DEX_POOL_H +#include "class.h" #include "dex.h" +#include "method.h" #include "../../analysis/routine.h" @@ -36,22 +38,39 @@ bool find_all_dex_strings(GDexFormat *); /* Extrait une chaîne de caractères d'une table DEX. */ const char *get_string_from_dex_pool(const GDexFormat *, uint32_t); -/* Extrait une représentation de type d'une table DEX. */ -GDataType *get_type_from_dex_pool(const GDexFormat *, uint16_t); -/* Extrait une représentation de classe d'une table DEX. */ -GDataType *get_class_from_dex_pool(const GDexFormat *, uint32_t); +/* Charge en mémoire l'ensemble des types du format DEX. */ +bool load_all_dex_types(GDexFormat *); +/* Extrait une représentation de type d'une table DEX. */ +GDataType *get_type_from_dex_pool(GDexFormat *, uint32_t); +/* Charge en mémoire l'ensemble des champs du format DEX. */ +bool load_all_dex_fields(GDexFormat *); /* Extrait une représentation de champ d'une table DEX. */ -GBinVariable *get_field_from_dex_pool(const GDexFormat *, uint32_t); +GBinVariable *get_field_from_dex_pool(GDexFormat *, uint32_t); + +/* Charge tous les prototypes listés dans le contenu binaire. */ +bool load_all_dex_prototypes(GDexFormat *); /* Extrait une représentation de routine d'une table DEX. */ -GBinRoutine *get_routine_from_dex_pool(const GDexFormat *, uint32_t); +GBinRoutine *get_prototype_from_dex_pool(GDexFormat *, uint32_t); + +/* Charge toutes les méthodes listées dans le contenu binaire. */ +bool load_all_dex_methods(GDexFormat *); + +/* Extrait une représentation de méthode d'une table DEX. */ +GDexMethod *get_method_from_dex_pool(GDexFormat *, uint32_t); + +/* Charge toutes les classes listées dans le contenu binaire. */ +bool load_all_dex_classes(GDexFormat *); + +/* Extrait une représentation de classe d'une table DEX. */ +GDexClass *get_class_from_dex_pool(GDexFormat *, uint32_t); diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 50df077..ea1f1ff 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -76,7 +76,7 @@ static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, static bool g_elf_format_translate_address_into_vmpa(const GElfFormat *, virt_t, vmpa2t *); /* Fournit l'emplacement d'une section donnée. */ -bool g_elf_format_get_section_range_by_name(const GElfFormat *, const char *, mrange_t *); +static bool g_elf_format_get_section_range_by_name(const GElfFormat *, const char *, mrange_t *); @@ -149,6 +149,9 @@ static void g_elf_format_class_init(GElfFormatClass *klass) exe = G_EXE_FORMAT_CLASS(klass); + exe->get_machine = (get_target_machine_fc)g_elf_format_get_target_machine; + exe->refine_portions = (refine_portions_fc)g_elf_format_refine_portions; + exe->translate_phys = (translate_phys_fc)g_elf_format_translate_offset_into_vmpa; exe->translate_virt = (translate_virt_fc)g_elf_format_translate_address_into_vmpa; @@ -171,12 +174,6 @@ static void g_elf_format_class_init(GElfFormatClass *klass) static void g_elf_format_init(GElfFormat *format) { - GExeFormat *exe_format; /* Format parent à constituer */ - - exe_format = G_EXE_FORMAT(format); - - exe_format->get_machine = (get_target_machine_fc)g_elf_format_get_target_machine; - exe_format->refine_portions = (refine_portions_fc)g_elf_format_refine_portions; } @@ -393,9 +390,9 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion * new = g_binary_portion_new(background); - sprintf(desc, "%s \"%s\"", - _("Segment"), - get_elf_program_type_desc(ELF_PHDR(format, phdr, p_type))); + snprintf(desc, MAX_PORTION_DESC, "%s \"%s\"", + _("Segment"), + get_elf_program_type_desc(ELF_PHDR(format, phdr, p_type))); g_binary_portion_set_desc(new, desc); @@ -532,7 +529,7 @@ static bool g_elf_format_translate_address_into_vmpa(const GElfFormat *format, v * * ******************************************************************************/ -bool g_elf_format_get_section_range_by_name(const GElfFormat *format, const char *name, mrange_t *range) +static bool g_elf_format_get_section_range_by_name(const GElfFormat *format, const char *name, mrange_t *range) { bool result; /* Bilan à retourner */ phys_t offset; /* Position physique de section*/ diff --git a/src/format/executable-int.c b/src/format/executable-int.c new file mode 100644 index 0000000..c4b8e6e --- /dev/null +++ b/src/format/executable-int.c @@ -0,0 +1,69 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * executable-int.c - code utile aux formats d'exécutables + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 "executable-int.h" + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une position physique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos) +{ + init_vmpa(pos, off, VMPA_NO_VIRTUAL); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* addr = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *format, virt_t addr, vmpa2t *pos) +{ + return false; + +} diff --git a/src/format/executable-int.h b/src/format/executable-int.h index f5a25b5..4b86092 100644 --- a/src/format/executable-int.h +++ b/src/format/executable-int.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * executable-int.h - prototypes utiles aux formats d'exécutables + * executable-int.h - prototypes de code utile aux formats d'exécutables * * Copyright (C) 2009-2013 Cyrille Bagard * @@ -38,14 +38,6 @@ typedef const char * (* get_target_machine_fc) (const GExeFormat *); /* Etend la définition des portions au sein d'un binaire. */ typedef void (* refine_portions_fc) (const GExeFormat *, GBinPortion *); -/* Fournit la position correspondant à une adresse virtuelle. */ -typedef bool (* translate_addr_fc) (const GExeFormat *, vmpa_t, off_t *); - -/* Fournit l'adresse virtuelle correspondant à une position. */ -typedef bool (* translate_off_fc) (const GExeFormat *, off_t, vmpa_t *); - - - /* Fournit l'emplacement correspondant à une position physique. */ typedef bool (* translate_phys_fc) (const GExeFormat *, phys_t, vmpa2t *); @@ -65,12 +57,6 @@ struct _GExeFormat GDbgFormat **debugs; /* Informations de débogage */ size_t debugs_count; /* Nombre de ces informations */ - get_target_machine_fc get_machine; /* Architecture ciblée */ - refine_portions_fc refine_portions; /* Décrit les portions binaires*/ - - translate_addr_fc translate_addr; /* Correspondance addr -> pos */ - translate_off_fc translate_off; /* Correspondance pos -> addr */ - GBinPortion *portions; /* Morceaux binaires distincts */ }; @@ -80,6 +66,9 @@ struct _GExeFormatClass { GBinFormatClass parent; /* A laisser en premier */ + get_target_machine_fc get_machine; /* Architecture ciblée */ + refine_portions_fc refine_portions; /* Décrit les portions binaires*/ + translate_phys_fc translate_phys; /* Correspondance phys -> vmpa */ translate_virt_fc translate_virt; /* Correspondance virt -> vmpa */ @@ -88,5 +77,12 @@ struct _GExeFormatClass }; +/* Fournit l'emplacement correspondant à une position physique. */ +bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *, phys_t, vmpa2t *); + +/* Fournit l'emplacement correspondant à une adresse virtuelle. */ +bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *, virt_t, vmpa2t *); + + #endif /* _FORMAT_EXECUTABLE_INT_H */ diff --git a/src/format/executable.c b/src/format/executable.c index 5ff773c..325dc8b 100644 --- a/src/format/executable.c +++ b/src/format/executable.c @@ -182,7 +182,7 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *format, size_t index) const char *g_exe_format_get_target_machine(const GExeFormat *format) { - return format->get_machine(format); + return G_EXE_FORMAT_GET_CLASS(format)->get_machine(format); } @@ -213,8 +213,7 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format) g_binary_portion_set_values(format->portions, &addr, length); - if (format->refine_portions != NULL) - format->refine_portions(format, format->portions); + G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format, format->portions); } diff --git a/src/format/java/java.c b/src/format/java/java.c index 39403c4..4fcecd9 100755 --- a/src/format/java/java.c +++ b/src/format/java/java.c @@ -45,14 +45,14 @@ static void g_java_format_class_init(GJavaFormatClass *); /* Initialise une instance de format d'exécutable Java. */ static void g_java_format_init(GJavaFormat *); -/* Indique le type d'architecture visée par le format. */ -static const char *g_java_format_get_target_machine(const GJavaFormat *); +/* Supprime toutes les références externes. */ +static void g_java_format_dispose(GJavaFormat *); -/* Fournit la position correspondant à une adresse virtuelle. */ -static bool g_java_format_translate_address_into_offset(const GJavaFormat *, vmpa_t, off_t *); +/* Procède à la libération totale de la mémoire. */ +static void g_java_format_finalize(GJavaFormat *); -/* Fournit l'adresse virtuelle correspondant à une position. */ -static bool g_java_format_translate_offset_into_address(const GJavaFormat *, off_t, vmpa_t *); +/* Indique le type d'architecture visée par le format. */ +static const char *g_java_format_get_target_machine(const GJavaFormat *); @@ -103,6 +103,21 @@ G_DEFINE_TYPE(GJavaFormat, g_java_format, G_TYPE_EXE_FORMAT); static void g_java_format_class_init(GJavaFormatClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + GExeFormatClass *exe; /* Version en exécutable */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_java_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_java_format_finalize; + + exe = G_EXE_FORMAT_CLASS(klass); + + exe->get_machine = (get_target_machine_fc)g_java_format_get_target_machine; + //exe->refine_portions = (refine_portions_fc)g_java_format_refine_portions; + + exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa; + exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa; } @@ -121,14 +136,44 @@ static void g_java_format_class_init(GJavaFormatClass *klass) static void g_java_format_init(GJavaFormat *format) { - GExeFormat *exe_format; /* Format parent à constituer */ - exe_format = G_EXE_FORMAT(format); +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_format_dispose(GJavaFormat *format) +{ + G_OBJECT_CLASS(g_java_format_parent_class)->dispose(G_OBJECT(format)); + +} + - exe_format->get_machine = (get_target_machine_fc)g_java_format_get_target_machine; +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - exe_format->translate_addr = (translate_addr_fc)g_java_format_translate_address_into_offset; - exe_format->translate_off = (translate_off_fc)g_java_format_translate_offset_into_address; +static void g_java_format_finalize(GJavaFormat *format) +{ + G_OBJECT_CLASS(g_java_format_parent_class)->finalize(G_OBJECT(format)); } @@ -189,63 +234,6 @@ static const char *g_java_format_get_target_machine(const GJavaFormat *format) } -/****************************************************************************** -* * -* 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_java_format_translate_address_into_offset(const GJavaFormat *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_java_format_translate_offset_into_address(const GJavaFormat *format, off_t pos, vmpa_t *addr) -{ - bool result; /* Bilan à retourner */ - - result = false; - - return result; - -} - - - - - - - - - diff --git a/src/format/pe/pe.c b/src/format/pe/pe.c index 39560ce..239f52a 100644 --- a/src/format/pe/pe.c +++ b/src/format/pe/pe.c @@ -45,12 +45,6 @@ static const char *g_pe_format_get_target_machine(const GPeFormat *); /* Fournit les références aux zones binaires à analyser. */ //static GBinPart **g_pe_format_get_parts(const GPeFormat *, size_t *); -/* Fournit la position correspondant à une adresse virtuelle. */ -static bool g_pe_format_translate_address_into_offset(const GPeFormat *, vmpa_t, off_t *); - -/* Fournit l'adresse virtuelle correspondant à une position. */ -static bool g_pe_format_translate_offset_into_address(const GPeFormat *, off_t, vmpa_t *); - /****************************************************************************** @@ -130,14 +124,6 @@ static void g_pe_format_class_init(GPeFormatClass *klass) static void g_pe_format_init(GPeFormat *format) { - GExeFormat *exe_format; /* Format parent à constituer */ - - exe_format = G_EXE_FORMAT(format); - - exe_format->get_machine = (get_target_machine_fc)g_pe_format_get_target_machine; - - exe_format->translate_addr = (translate_addr_fc)g_pe_format_translate_address_into_offset; - exe_format->translate_off = (translate_off_fc)g_pe_format_translate_offset_into_address; } @@ -286,52 +272,3 @@ static GBinPart **g_pe_format_get_parts(const GPeFormat *format, size_t *count) } #endif - -/****************************************************************************** -* * -* 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_pe_format_translate_address_into_offset(const GPeFormat *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_pe_format_translate_offset_into_address(const GPeFormat *format, off_t pos, vmpa_t *addr) -{ - bool result; /* Bilan à retourner */ - - result = false; - - return result; - -} diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c index 6b7e6b4..a85e78f 100644 --- a/src/gui/menus/project.c +++ b/src/gui/menus/project.c @@ -221,14 +221,6 @@ static void mcb_project_add_shellcode(GtkMenuItem *menuitem, GMenuBar *bar) free(dir); } - if (g_study_project_get_filename(get_current_project()) != NULL) - { - dir = strdup(g_study_project_get_filename(get_current_project())); - dir = dirname(dir); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); - free(dir); - } - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); @@ -287,14 +279,6 @@ static void mcb_project_add_binary_file(GtkMenuItem *menuitem, GMenuBar *bar) free(dir); } - if (g_study_project_get_filename(get_current_project()) != NULL) - { - dir = strdup(g_study_project_get_filename(get_current_project())); - dir = dirname(dir); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); - free(dir); - } - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |