From c136e2c4c1ad02ea2e363fbe71ce54c6255793e2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 7 May 2018 16:24:16 +0200 Subject: Extended the Python bindings for the Dex format. --- plugins/androhelpers/params.c | 4 + plugins/androhelpers/switch.c | 4 + plugins/androhelpers/try_n_catch.c | 4 + plugins/dex/Makefile.am | 1 + plugins/dex/class.c | 254 ++++++++++++++++- plugins/dex/class.h | 30 +- plugins/dex/dex-int.c | 2 +- plugins/dex/dex_def.h | 2 +- plugins/dex/field.c | 230 +++++++++++++++ plugins/dex/field.h | 70 +++++ plugins/dex/format.c | 15 +- plugins/dex/method.c | 8 +- plugins/dex/method.h | 12 +- plugins/dex/pool.c | 180 ++++++++++-- plugins/dex/pool.h | 19 +- plugins/dex/python/Makefile.am | 6 +- plugins/dex/python/class.c | 449 ++++++++++++++++++++++++++++++ plugins/dex/python/constants.c | 104 +++++++ plugins/dex/python/constants.h | 39 +++ plugins/dex/python/field.c | 186 +++++++++++++ plugins/dex/python/field.h | 42 +++ plugins/dex/python/format.c | 354 +++++++++++++++++++++++ plugins/dex/python/method.c | 223 +++++++++++++++ plugins/dex/python/method.h | 42 +++ plugins/dex/python/module.c | 8 + plugins/dex/python/translate.c | 293 +++++++++++++++++++ plugins/dex/python/translate.h | 53 ++++ plugins/elf/python/constants.c | 8 +- plugins/elf/python/constants.h | 2 +- plugins/elf/python/format.c | 2 +- plugins/pychrysalide/analysis/Makefile.am | 3 +- plugins/pychrysalide/analysis/module.c | 2 + plugins/pychrysalide/analysis/type.c | 2 +- plugins/pychrysalide/analysis/variable.c | 268 ++++++++++++++++++ plugins/pychrysalide/analysis/variable.h | 42 +++ plugins/readdex/class.c | 2 +- src/analysis/routine.c | 2 +- src/analysis/variable.c | 8 +- src/analysis/variable.h | 12 +- 39 files changed, 2904 insertions(+), 83 deletions(-) create mode 100644 plugins/dex/field.c create mode 100644 plugins/dex/field.h create mode 100644 plugins/dex/python/constants.c create mode 100644 plugins/dex/python/constants.h create mode 100644 plugins/dex/python/field.c create mode 100644 plugins/dex/python/field.h create mode 100644 plugins/dex/python/method.c create mode 100644 plugins/dex/python/method.h create mode 100644 plugins/dex/python/translate.c create mode 100644 plugins/dex/python/translate.h create mode 100644 plugins/pychrysalide/analysis/variable.c create mode 100644 plugins/pychrysalide/analysis/variable.h diff --git a/plugins/androhelpers/params.c b/plugins/androhelpers/params.c index d85baca..26f4265 100644 --- a/plugins/androhelpers/params.c +++ b/plugins/androhelpers/params.c @@ -212,6 +212,7 @@ bool replace_parameters(GLoadedBinary *binary) { method = g_dex_class_get_method(class, false, j); visit_all_method_operands(method, instrs); + g_object_unref(G_OBJECT(method)); } meth_count = g_dex_class_count_methods(class, true); @@ -219,8 +220,11 @@ bool replace_parameters(GLoadedBinary *binary) { method = g_dex_class_get_method(class, true, j); visit_all_method_operands(method, instrs); + g_object_unref(G_OBJECT(method)); } + g_object_unref(G_OBJECT(class)); + } g_object_unref(G_OBJECT(proc)); diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c index 5f18b87..2ef6277 100644 --- a/plugins/androhelpers/switch.c +++ b/plugins/androhelpers/switch.c @@ -412,6 +412,7 @@ bool extract_switch_info(GLoadedBinary *binary, bool link) { method = g_dex_class_get_method(class, false, j); look_for_switch_instructions(method, instrs, binary, format, link); + g_object_unref(G_OBJECT(method)); } meth_count = g_dex_class_count_methods(class, true); @@ -419,8 +420,11 @@ bool extract_switch_info(GLoadedBinary *binary, bool link) { method = g_dex_class_get_method(class, true, j); look_for_switch_instructions(method, instrs, binary, format, link); + g_object_unref(G_OBJECT(method)); } + g_object_unref(G_OBJECT(class)); + } g_object_unref(G_OBJECT(proc)); diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c index cf33926..1fa3971 100644 --- a/plugins/androhelpers/try_n_catch.c +++ b/plugins/androhelpers/try_n_catch.c @@ -438,6 +438,7 @@ bool process_exception_handlers(GLoadedBinary *binary, bool link) { method = g_dex_class_get_method(class, false, j); look_for_exception_handlers(binary, format, method, link); + g_object_unref(G_OBJECT(method)); } meth_count = g_dex_class_count_methods(class, true); @@ -445,8 +446,11 @@ bool process_exception_handlers(GLoadedBinary *binary, bool link) { method = g_dex_class_get_method(class, true, j); look_for_exception_handlers(binary, format, method, link); + g_object_unref(G_OBJECT(method)); } + g_object_unref(G_OBJECT(class)); + } g_object_unref(G_OBJECT(format)); diff --git a/plugins/dex/Makefile.am b/plugins/dex/Makefile.am index 50c1dcc..c72d1c6 100755 --- a/plugins/dex/Makefile.am +++ b/plugins/dex/Makefile.am @@ -9,6 +9,7 @@ libdex_la_SOURCES = \ class.h class.c \ dex-int.h dex-int.c \ dex_def.h \ + field.h field.c \ format.h format.c \ loading.h loading.c \ method.h method.c \ diff --git a/plugins/dex/class.c b/plugins/dex/class.c index 5cd159b..ef3ed85 100644 --- a/plugins/dex/class.c +++ b/plugins/dex/class.c @@ -28,7 +28,6 @@ #include "dex-int.h" -#include "method.h" #include "pool.h" @@ -38,10 +37,17 @@ struct _GDexClass { GObject parent; /* A laisser en premier */ + GDexFormat *format; /* Lien vers la table globale */ + class_def_item definition; /* Définition de la classe */ bool has_data; /* Indicateur de présence */ class_data_item data; /* Contenu de la classe */ + GDexField **static_fields; /* Champs statiques */ + size_t sfields_count; /* Quantité de ces champs */ + GDexField **instance_fields; /* Champs propres à la classe */ + size_t ifields_count; /* Quantité de ces champs */ + GDexMethod **direct_methods; /* Méthodes propres */ size_t dmethods_count; /* Quantité de ces méthodes */ GDexMethod **virtual_methods; /* Méthodes virtuelles */ @@ -69,9 +75,6 @@ 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 *); - /* Détermine le type d'une classe issue du code source. */ @@ -136,6 +139,16 @@ static void g_dex_class_dispose(GDexClass *class) { size_t i; /* Boucle de parcours */ + if (class->static_fields != NULL) + for (i = 0; i < class->sfields_count; i++) + if (class->static_fields[i] != NULL) + g_object_unref(G_OBJECT(class->static_fields[i])); + + if (class->instance_fields != NULL) + for (i = 0; i < class->ifields_count; i++) + if (class->instance_fields[i] != NULL) + g_object_unref(G_OBJECT(class->instance_fields[i])); + if (class->direct_methods != NULL) for (i = 0; i < class->dmethods_count; i++) if (class->direct_methods[i] != NULL) @@ -146,6 +159,8 @@ static void g_dex_class_dispose(GDexClass *class) if (class->virtual_methods[i] != NULL) g_object_unref(G_OBJECT(class->virtual_methods[i])); + g_object_unref(G_OBJECT(class->format)); + G_OBJECT_CLASS(g_dex_class_parent_class)->dispose(G_OBJECT(class)); } @@ -165,6 +180,15 @@ static void g_dex_class_dispose(GDexClass *class) static void g_dex_class_finalize(GDexClass *class) { + if (class->has_data) + reset_dex_class_data_item(&class->data); + + if (class->static_fields != NULL) + free(class->static_fields); + + if (class->instance_fields != NULL) + free(class->instance_fields); + if (class->direct_methods != NULL) free(class->direct_methods); @@ -194,15 +218,19 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) GDexClass *result; /* Composant à retourner */ vmpa2t addr; /* Tête de lecture générique */ class_data_item data; /* Contenu de la classe */ - GDataType *ctype; /* Type créé par la classe */ - GBinFormat *base; /* Autre version du format */ uleb128_t index; /* Conservation du dernier id */ uleb128_t i; /* Boucle de parcours */ + GDexField *field; /* Champ chargé */ + GDataType *ctype; /* Type créé par la classe */ + GBinFormat *base; /* Autre version du format */ GDexMethod *method; /* Méthode chargée */ GBinRoutine *routine; /* Version interne de méthode */ result = g_object_new(G_TYPE_DEX_CLASS, NULL); + result->format = format; + g_object_ref(G_OBJECT(format)); + result->definition = *def; result->has_data = (def->class_data_off != 0); @@ -227,6 +255,42 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) result->data = data; /** + * Chargement des champs de classe. + */ + + index = 0; + + result->sfields_count = data.static_fields_size; + result->static_fields = (GDexField **)calloc(result->sfields_count, sizeof(GDexField *)); + + for (i = 0; i < result->sfields_count; i++) + { + field = g_dex_field_new(format, &data.static_fields[i], &index); + if (field == NULL) goto gdcn_bad_field; + + result->static_fields[i] = field; + + } + + index = 0; + + result->ifields_count = data.instance_fields_size; + result->instance_fields = (GDexField **)calloc(result->ifields_count, sizeof(GDexField *)); + + for (i = 0; i < result->ifields_count; i++) + { + field = g_dex_field_new(format, &data.instance_fields[i], &index); + if (field == NULL) goto gdcn_bad_field; + + result->instance_fields[i] = field; + + } + + /** + * Chargement des méthodes de classe. + */ + + /** * On évite ici les méthodes (virtuelles) non définies. */ if (def->access_flags & ACC_ANNOTATION) goto gdcn_done; @@ -241,7 +305,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) 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++) + for (i = 0; i < result->dmethods_count; i++) { method = g_dex_method_new_defined(format, &data.direct_methods[i], &index); if (method == NULL) goto gdcn_bad_method; @@ -267,7 +331,7 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) 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++) + for (i = 0; i < result->vmethods_count; i++) { method = g_dex_method_new_defined(format, &data.virtual_methods[i], &index); if (method == NULL) goto gdcn_bad_method; @@ -300,6 +364,8 @@ GDexClass *g_dex_class_new(GDexFormat *format, const class_def_item *def) gdcn_unknown_type: + gdcn_bad_field: + gdcn_bad_item: g_object_unref(G_OBJECT(result)); @@ -349,6 +415,166 @@ const class_data_item *g_dex_class_get_data(const GDexClass *class) /****************************************************************************** * * +* Paramètres : class = informations chargées à consulter. * +* * +* Description : Indique le type Android d'une classe. * +* * +* Retour : Type de classe ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDataType *g_dex_class_get_class_type(const GDexClass *class) +{ + GDataType *result; /* Type à renvoyer */ + + result = get_type_from_dex_pool(class->format, class->definition.class_idx); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* * +* Description : Indique le type Android parent d'une classe. * +* * +* Retour : Type de classe ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDataType *g_dex_class_get_superclass_type(const GDexClass *class) +{ + GDataType *result; /* Type à renvoyer */ + + result = get_type_from_dex_pool(class->format, class->definition.superclass_idx); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* count = taille de la liste constituée. [OUT] * +* * +* Description : Indique le type Android des interfaces d'une classe. * +* * +* Retour : Types d'interfaces ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDataType **g_dex_class_get_interface_types(const GDexClass *class, size_t *count) +{ + GDataType **result; /* Types à renvoyer */ + vmpa2t addr; /* Tête de lecture générique */ + type_list interfaces; /* Liste des interfaces */ + bool status; /* Bilan d'une lecture */ + size_t i; /* Boucle de parcours */ + + if (class->definition.interfaces_off == 0) + { + *count = 0; + result = NULL; + } + + else + { + init_vmpa(&addr, class->definition.interfaces_off, VMPA_NO_VIRTUAL); + + status = read_dex_type_list(class->format, &addr, &interfaces); + + if (status) + { + *count = interfaces.size; + result = (GDataType **)malloc(*count * sizeof(GDataType *)); + + for (i = 0; i < *count; i++) + result[i] = get_type_from_dex_pool(class->format, interfaces.list[i].type_idx); + + } + + else + { + *count = 0; + result = NULL; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* instance = précise la nature des champs ciblés. * +* * +* Description : Dénombre les champs de classe chargés d'une classe donnée. * +* * +* Retour : Quantité de champs trouvés. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_dex_class_count_fields(const GDexClass *class, bool instance) +{ + size_t result; /* Compte à retourner */ + + if (instance) + result = class->ifields_count; + else + result = class->sfields_count; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* instance = précise la nature des champs ciblés. * +* index = indique l'indice du champ désiré. * +* * +* Description : Fournit un champ chargé correspondant à une classe donnée. * +* * +* Retour : Champ intégré ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexField *g_dex_class_get_field(const GDexClass *class, bool instance, size_t index) +{ + GDexField *result; /* Instance à renvoyer */ + + if (instance) + result = class->instance_fields[index]; + else + result = class->static_fields[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : class = informations chargées à consulter. * * virtual = précise la nature des méthodes ciblées. * * * @@ -382,7 +608,7 @@ size_t g_dex_class_count_methods(const GDexClass *class, bool virtual) * * * Description : Fournit une méthode chargée correspondant à un type donné. * * * -* Retour : Quantité de méthodes trouvées. * +* Retour : Méthode intégrée ou NULL. * * * * Remarques : - * * * @@ -397,6 +623,9 @@ GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t else result = class->direct_methods[index]; + if (result != NULL) + g_object_ref(G_OBJECT(result)); + return result; } @@ -475,8 +704,7 @@ bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset) /****************************************************************************** * * -* Paramètres : class = informations chargées à consulter. * -* format = représentation interne du format DEX à compléter. * +* Paramètres : class = informations chargées à consulter. * * * * Description : Retrouve si possible le nom du fichier source d'une classe. * * * @@ -486,11 +714,11 @@ bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset) * * ******************************************************************************/ -const char *g_dex_class_get_source_file(const GDexClass *class, const GDexFormat *format) +const char *g_dex_class_get_source_file(const GDexClass *class) { const char *result; /* Trouvaille à renvoyer */ - result = get_string_from_dex_pool(format, class->definition.source_file_idx, NULL); + result = get_string_from_dex_pool(class->format, class->definition.source_file_idx, NULL); return result; diff --git a/plugins/dex/class.h b/plugins/dex/class.h index 71fd4c9..9d4e426 100644 --- a/plugins/dex/class.h +++ b/plugins/dex/class.h @@ -28,17 +28,18 @@ #include +#include "field.h" #include "format.h" #include "method.h" -#define G_TYPE_DEX_CLASS (g_dex_class_get_type()) -#define G_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_CLASS, GDexClass)) -#define G_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_CLASS, GDexClassClass)) -#define G_IS_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_CLASS)) -#define G_IS_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_CLASS)) -#define G_DEX_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_CLASS, GDexClassClass)) +#define G_TYPE_DEX_CLASS (g_dex_class_get_type()) +#define G_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_CLASS, GDexClass)) +#define G_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_CLASS, GDexClassClass)) +#define G_IS_DEX_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_CLASS)) +#define G_IS_DEX_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_CLASS)) +#define G_DEX_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_CLASS, GDexClassClass)) @@ -62,6 +63,21 @@ const class_def_item *g_dex_class_get_definition(const GDexClass *); /* Fournit la définition brute des données d'une classe. */ const class_data_item *g_dex_class_get_data(const GDexClass *); +/* Indique le type Android d'une classe. */ +GDataType *g_dex_class_get_class_type(const GDexClass *); + +/* Indique le type Android parent d'une classe. */ +GDataType *g_dex_class_get_superclass_type(const GDexClass *); + +/* Indique le type Android des interfaces d'une classe. */ +GDataType **g_dex_class_get_interface_types(const GDexClass *, size_t *); + +/* Dénombre les champs de classe chargés d'une classe donnée. */ +size_t g_dex_class_count_fields(const GDexClass *, bool); + +/* Fournit un champ chargé correspondant à une classe donnée. */ +GDexField *g_dex_class_get_field(const GDexClass *, bool, size_t); + /* Dénombre les méthodes chargées d'un type donné. */ size_t g_dex_class_count_methods(const GDexClass *, bool); @@ -75,7 +91,7 @@ void g_dex_class_include_as_portion(const GDexClass *, GExeFormat *); GDexMethod *g_dex_class_find_method_by_address(const GDexClass *, vmpa_t); /* Retrouve si possible le nom du fichier source d'une classe. */ -const char *g_dex_class_get_source_file(const GDexClass *, const GDexFormat *); +const char *g_dex_class_get_source_file(const GDexClass *); /* Procède à la décompilation complète d'une classe donnée. */ //void g_dex_class_decompile(const GDexClass *, GLangOutput *, GCodeBuffer *, const GDexFormat *); diff --git a/plugins/dex/dex-int.c b/plugins/dex/dex-int.c index 150d401..e3121b6 100644 --- a/plugins/dex/dex-int.c +++ b/plugins/dex/dex-int.c @@ -470,7 +470,7 @@ bool read_dex_type_list(const GDexFormat *format, vmpa2t *pos, type_list *list) result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &list->size); - list->list = (type_item *)g_binary_content_get_raw_access(content, pos, list->size * sizeof(type_item)); + list->list = (const type_item *)g_binary_content_get_raw_access(content, pos, list->size * sizeof(type_item)); result &= (list->list != NULL); return result; diff --git a/plugins/dex/dex_def.h b/plugins/dex/dex_def.h index 61f51c2..913e20c 100755 --- a/plugins/dex/dex_def.h +++ b/plugins/dex/dex_def.h @@ -206,7 +206,7 @@ typedef struct _type_item typedef struct _type_list { uint32_t size; /* Nombre d'éléments présents */ - type_item *list; /* Liste des éléments inscrits */ + const type_item *list; /* Liste des éléments inscrits */ } type_list; diff --git a/plugins/dex/field.c b/plugins/dex/field.c new file mode 100644 index 0000000..620d159 --- /dev/null +++ b/plugins/dex/field.c @@ -0,0 +1,230 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.c - manipulation des champs de classe du format DEX + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#include "field.h" + + +#include "dex-int.h" +#include "pool.h" + + + +/* Champ d'une classe Dex (instance) */ +struct _GDexField +{ + GObject parent; /* A laisser en premier */ + + GBinVariable *variable; /* Représentation interne */ + + encoded_field info; /* Propriétés de la méthode */ + +}; + +/* Champ d'une classe Dex (classe) */ +struct _GDexFieldClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation des champs de classe Dex. */ +static void g_dex_field_class_init(GDexFieldClass *); + +/* Procède à l'initialisation d'un champ de classe Dex. */ +static void g_dex_field_init(GDexField *); + +/* Supprime toutes les références externes. */ +static void g_dex_field_dispose(GDexField *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dex_field_finalize(GDexField *); + + + +/* Détermine le type d'une fielde issue du code source. */ +G_DEFINE_TYPE(GDexField, g_dex_field, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation des champs de classe Dex. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_field_class_init(GDexFieldClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_field_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_field_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : field = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'un champ de classe Dex. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_field_init(GDexField *field) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_field_dispose(GDexField *field) +{ + if (field->variable != NULL) + g_object_unref(G_OBJECT(field->variable)); + + G_OBJECT_CLASS(g_dex_field_parent_class)->dispose(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : field = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_field_finalize(GDexField *field) +{ + G_OBJECT_CLASS(g_dex_field_parent_class)->finalize(G_OBJECT(field)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* seed = graine des informations à extraire. * +* last = dernier indice utilisé (à mettre à jour). [OUT] * +* * +* Description : Crée une nouvelle représentation de champ de classe. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexField *g_dex_field_new(GDexFormat *format, const encoded_field *seed, uleb128_t *last) +{ + GDexField *result; /* Composant à retourner */ + GBinVariable *variable; /* Variable de représentation */ + + *last += seed->field_idx_diff; + + variable = get_field_from_dex_pool(format, *last); + + if (variable == NULL) + return NULL; + + result = g_object_new(G_TYPE_DEX_FIELD, NULL); + + result->variable = variable; + + result->info = *seed; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : field = représentation interne du champ à consulter. * +* * +* Description : Fournit les indications Dex concernant le champ de classe. * +* * +* Retour : Données brutes du binaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const encoded_field *g_dex_field_get_dex_info(const GDexField *field) +{ + return &field->info; + +} + + +/****************************************************************************** +* * +* Paramètres : field = représentation interne du format DEX à consulter. * +* * +* Description : Fournit la variable Chrysalide correspondant au champ. * +* * +* Retour : Instance de routine mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinVariable *g_dex_field_get_variable(const GDexField *field) +{ + GBinVariable *result; /* Instance à retourner */ + + result = field->variable; + + g_object_ref(G_OBJECT(result)); + + return result; + +} diff --git a/plugins/dex/field.h b/plugins/dex/field.h new file mode 100644 index 0000000..e430d7f --- /dev/null +++ b/plugins/dex/field.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.h - prototypes pour la manipulation des champs de classe du format DEX + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see . + */ + + +#ifndef _PLUGINS_DEX_FIELD_H +#define _PLUGINS_DEX_FIELD_H + + +#include + + +#include + + +#include "dex_def.h" +#include "format.h" + + + +#define G_TYPE_DEX_FIELD (g_dex_field_get_type()) +#define G_DEX_FIELD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_FIELD, GDexField)) +#define G_DEX_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_FIELD, GDexFieldClass)) +#define G_IS_DEX_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_FIELD)) +#define G_IS_DEX_FIELD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_FIELD)) +#define G_DEX_FIELD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_FIELD, GDexFieldClass)) + + + +/* Champ d'une classe Dex (instance) */ +typedef struct _GDexField GDexField; + +/* Champ d'une classe Dex (classe) */ +typedef struct _GDexFieldClass GDexFieldClass; + + + +/* Détermine le type d'une fielde issue du code source. */ +GType g_dex_field_get_type(void); + +/* Crée une nouvelle représentation de champ de classe. */ +GDexField *g_dex_field_new(GDexFormat *, const encoded_field *, uleb128_t *); + +/* Fournit les indications Dex concernant le champ de classe. */ +const encoded_field *g_dex_field_get_dex_info(const GDexField *); + +/* Fournit la variable Chrysalide correspondant au champ. */ +GBinVariable *g_dex_field_get_variable(const GDexField *); + + + +#endif /* _PLUGINS_DEX_FIELD_H */ diff --git a/plugins/dex/format.c b/plugins/dex/format.c index 371684f..1fa5a7d 100755 --- a/plugins/dex/format.c +++ b/plugins/dex/format.c @@ -657,9 +657,20 @@ size_t g_dex_format_count_classes(const GDexFormat *format) GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index) { - /* TODO : ref() */ + GDexClass *result; /* Classe trouvée à retourner */ - return format->classes[index]; + assert(index < format->header.class_defs_size); + + if (index < format->header.class_defs_size) + { + result = format->classes[index]; + g_object_ref(G_OBJECT(result)); + } + + else + result = NULL; + + return result; } diff --git a/plugins/dex/method.c b/plugins/dex/method.c index 409261f..4013436 100644 --- a/plugins/dex/method.c +++ b/plugins/dex/method.c @@ -36,7 +36,6 @@ - /* Methode issue du code source (instance) */ struct _GDexMethod { @@ -78,12 +77,11 @@ static void g_dex_method_finalize(GDexMethod *); G_DEFINE_TYPE(GDexMethod, g_dex_method, G_TYPE_OBJECT); - /****************************************************************************** * * * Paramètres : class = classe de composant GLib à initialiser. * * * -* Description : Procède à l'initialisation d'une methode issue du code. * +* Description : Procède à l'initialisation des methodes issues du code. * * * * Retour : - * * * @@ -123,7 +121,7 @@ static void g_dex_method_init(GDexMethod *method) /****************************************************************************** * * -* Paramètres : format = instance d'objet GLib à traiter. * +* Paramètres : method = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -335,7 +333,7 @@ const code_item *g_dex_method_get_dex_body(const GDexMethod *method) * * * Paramètres : method = représentation interne du format DEX à consulter. * * * -* Description : Fournit la routine Chrysalide correspondant à la méthode. * +* Description : Fournit la routine Chrysalide correspondant à la méthode. * * * * Retour : Instance de routine mise en place. * * * diff --git a/plugins/dex/method.h b/plugins/dex/method.h index fe6abf0..2b99715 100644 --- a/plugins/dex/method.h +++ b/plugins/dex/method.h @@ -36,12 +36,12 @@ -#define G_TYPE_DEX_METHOD (g_dex_method_get_type()) -#define G_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_METHOD, GDexMethod)) -#define G_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_METHOD, GDexMethodClass)) -#define G_IS_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_METHOD)) -#define G_IS_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_METHOD)) -#define G_DEX_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_METHOD, GDexMethodClass)) +#define G_TYPE_DEX_METHOD (g_dex_method_get_type()) +#define G_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DEX_METHOD, GDexMethod)) +#define G_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_METHOD, GDexMethodClass)) +#define G_IS_DEX_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DEX_METHOD)) +#define G_IS_DEX_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_METHOD)) +#define G_DEX_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_METHOD, GDexMethodClass)) diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c index 9f3d55d..bfc463a 100644 --- a/plugins/dex/pool.c +++ b/plugins/dex/pool.c @@ -53,6 +53,7 @@ bool find_all_dex_strings(GDexFormat *format) { GBinFormat *base; /* Autre version du format */ + uint32_t count; /* Nombre d'éléments présents */ uint32_t i; /* Boucle de parcours */ mrange_t range; /* Couverture associée */ const char *text; /* Texte issu du binaire */ @@ -61,7 +62,9 @@ bool find_all_dex_strings(GDexFormat *format) base = G_BIN_FORMAT(format); - for (i = 0; i < format->header.string_ids_size; i++) + count = count_strings_in_dex_pool(format); + + for (i = 0; i < count; i++) { text = get_string_from_dex_pool(format, i, &range); if (text == NULL) continue; @@ -86,6 +89,29 @@ bool find_all_dex_strings(GDexFormat *format) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * +* * +* Description : Compte le nombre de chaînes de caractères dans une table DEX.* +* * +* Retour : Valeur positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t count_strings_in_dex_pool(const GDexFormat *format) +{ + uint32_t result; /* Quantité à retourner */ + + result = format->header.string_ids_size; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * * index = index du type recherchée. * * range = éventuelle couverture à renseigner ou NULL. [OUT] * * * @@ -99,6 +125,7 @@ bool find_all_dex_strings(GDexFormat *format) const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, mrange_t *range) { + uint32_t count; /* Nombre d'éléments présents */ 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 */ @@ -106,7 +133,9 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m vmpa2t start; /* Début de la chaîne */ phys_t diff; /* Avancée de tête de lecture */ - if (index >= format->header.string_ids_size) + count = count_strings_in_dex_pool(format); + + if (index >= count) return NULL; pos = format->header.string_ids_off + index * sizeof(string_id_item); @@ -135,16 +164,6 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m } - - - - - - - - - - /****************************************************************************** * * * Paramètres : format = description de l'exécutable à compléter. * @@ -162,6 +181,7 @@ const char *get_string_from_dex_pool(const GDexFormat *format, uint32_t index, m bool load_all_dex_types(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status) { bool result; /* Bilan à retourner */ + uint32_t count; /* Nombre d'éléments présents */ guint runs_count; /* Qté d'exécutions parallèles */ uint32_t run_size; /* Volume réparti par exécution*/ GWorkQueue *queue; /* Gestionnaire de différés */ @@ -175,25 +195,26 @@ bool load_all_dex_types(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *sta /* Préparation du réceptacle */ - format->types = (GDataType **)calloc(format->header.type_ids_size, sizeof(GDataType *)); + count = count_types_in_dex_pool(format); + + format->types = (GDataType **)calloc(count, sizeof(GDataType *)); /* Lancement des chargements */ runs_count = g_get_num_processors(); - run_size = format->header.type_ids_size / runs_count; + run_size = count / runs_count; queue = get_work_queue(); - msg = gtk_status_stack_add_activity(status, _("Loading all types from the Dex pool..."), - format->header.type_ids_size); + msg = gtk_status_stack_add_activity(status, _("Loading all types from the Dex pool..."), count); for (i = 0; i < runs_count; i++) { begin = i * run_size; if ((i + 1) == runs_count) - end = format->header.type_ids_size; + end = count; else end = begin + run_size; @@ -216,6 +237,29 @@ bool load_all_dex_types(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *sta /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * +* * +* Description : Compte le nombre de types dans une table DEX. * +* * +* Retour : Valeur positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t count_types_in_dex_pool(const GDexFormat *format) +{ + uint32_t result; /* Quantité à retourner */ + + result = format->header.type_ids_size; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * * index = index du type recherchée. * * * * Description : Extrait une représentation de type d'une table DEX. * @@ -229,6 +273,7 @@ bool load_all_dex_types(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *sta GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) { GDataType *result; /* Instance à retourner */ + uint32_t count; /* Nombre d'éléments présents */ 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 */ @@ -238,7 +283,9 @@ GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) result = NULL; - if (index >= format->header.type_ids_size) + count = count_types_in_dex_pool(format); + + if (index >= count) goto gtfdp_error; if (format->types[index] == NULL) @@ -295,6 +342,7 @@ GDataType *get_type_from_dex_pool(GDexFormat *format, uint32_t index) bool load_all_dex_fields(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *status) { bool result; /* Bilan à retourner */ + uint32_t count; /* Nombre d'éléments présents */ guint runs_count; /* Qté d'exécutions parallèles */ uint32_t run_size; /* Volume réparti par exécution*/ GWorkQueue *queue; /* Gestionnaire de différés */ @@ -308,25 +356,27 @@ bool load_all_dex_fields(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *st /* Préparation du réceptacle */ - format->fields = (GBinVariable **)calloc(format->header.field_ids_size, sizeof(GBinVariable *)); + count = count_fields_in_dex_pool(format); + + format->fields = (GBinVariable **)calloc(count, sizeof(GBinVariable *)); /* Lancement des chargements */ runs_count = g_get_num_processors(); - run_size = format->header.field_ids_size / runs_count; + run_size = count / runs_count; queue = get_work_queue(); msg = gtk_status_stack_add_activity(status, _("Loading all fields from the Dex pool..."), - format->header.field_ids_size); + count); for (i = 0; i < runs_count; i++) { begin = i * run_size; if ((i + 1) == runs_count) - end = format->header.field_ids_size; + end = count; else end = begin + run_size; @@ -349,6 +399,29 @@ bool load_all_dex_fields(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *st /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * +* * +* Description : Compte le nombre de champs dans une table DEX. * +* * +* Retour : Valeur positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t count_fields_in_dex_pool(const GDexFormat *format) +{ + uint32_t result; /* Quantité à retourner */ + + result = format->header.field_ids_size; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * * index = index du champ recherché. * * * * Description : Extrait une représentation de champ d'une table DEX. * @@ -362,6 +435,7 @@ bool load_all_dex_fields(GDexFormat *format, wgroup_id_t gid, GtkStatusStack *st GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) { GBinVariable *result; /* Instance à retourner */ + uint32_t count; /* Nombre d'éléments présents */ phys_t pos; /* Tête de lecture */ vmpa2t addr; /* Tête de lecture générique */ field_id_item field_id; /* Description du champ */ @@ -372,7 +446,9 @@ GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) result = NULL; - if (index >= format->header.field_ids_size) + count = count_fields_in_dex_pool(format); + + if (index >= count) goto gffdp_error; if (format->fields[index] == NULL) @@ -430,6 +506,29 @@ GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * +* * +* Description : Compte le nombre de prototypes dans une table DEX. * +* * +* Retour : Valeur positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t count_prototypes_in_dex_pool(const GDexFormat *format) +{ + uint32_t result; /* Quantité à retourner */ + + result = format->header.proto_ids_size; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * * index = index de la routine recherchée. * * * * Description : Extrait une représentation de routine d'une table DEX. * @@ -443,6 +542,7 @@ GBinVariable *get_field_from_dex_pool(GDexFormat *format, uint32_t index) GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) { GBinRoutine *result; /* Instance à retourner */ + uint32_t count; /* Nombre d'éléments présents */ phys_t pos; /* Tête de lecture */ vmpa2t addr; /* Tête de lecture générique */ proto_id_item proto_id; /* Prototype de routine */ @@ -460,7 +560,9 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) * les autres éléments de la table des constantes. */ - if (index >= format->header.proto_ids_size) + count = count_prototypes_in_dex_pool(format); + + if (index >= count) goto grfdp_error; pos = format->header.proto_ids_off + index * sizeof(proto_id_item); @@ -499,7 +601,7 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) ///////result = demangle_routine(G_TYPE_DEX_DEMANGLER, name); - g_binary_routine_set_name(result, strdup("...")); + //g_binary_routine_set_name(result, strdup("...")); #if 1 if (result != NULL)/////////////////////// @@ -521,6 +623,29 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) /****************************************************************************** * * * Paramètres : format = représentation interne du format DEX à consulter. * +* * +* Description : Compte le nombre de méthodes dans une table DEX. * +* * +* Retour : Valeur positive ou nulle. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t count_methods_in_dex_pool(const GDexFormat *format) +{ + uint32_t result; /* Quantité à retourner */ + + result = format->header.method_ids_size; + + return result; + +} + + +/****************************************************************************** +* * +* 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. * @@ -534,13 +659,16 @@ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *format, uint32_t index) GDexMethod *get_method_from_dex_pool(GDexFormat *format, uint32_t index) { GDexMethod *result; /* Instance à retourner */ + uint32_t count; /* Nombre d'éléments présents */ 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 */ result = NULL; - if (index >= format->header.method_ids_size) + count = count_methods_in_dex_pool(format); + + if (index >= count) goto gmfdp_error; /** diff --git a/plugins/dex/pool.h b/plugins/dex/pool.h index 45df801..ed5b447 100644 --- a/plugins/dex/pool.h +++ b/plugins/dex/pool.h @@ -38,28 +38,39 @@ /* Charge en mémoire toutes les chaînes trouvées. */ bool find_all_dex_strings(GDexFormat *); +/* Compte le nombre de chaînes de caractères dans une table DEX. */ +uint32_t count_strings_in_dex_pool(const GDexFormat *); + /* Extrait une chaîne de caractères d'une table DEX. */ const char *get_string_from_dex_pool(const GDexFormat *, uint32_t, mrange_t *); - - - - /* Charge en mémoire l'ensemble des types du format DEX. */ bool load_all_dex_types(GDexFormat *, wgroup_id_t, GtkStatusStack *); +/* Compte le nombre de types dans une table DEX. */ +uint32_t count_types_in_dex_pool(const 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 *, wgroup_id_t, GtkStatusStack *); +/* Compte le nombre de champs dans une table DEX. */ +uint32_t count_fields_in_dex_pool(const GDexFormat *); + /* Extrait une représentation de champ d'une table DEX. */ GBinVariable *get_field_from_dex_pool(GDexFormat *, uint32_t); +/* Compte le nombre de prototypes dans une table DEX. */ +uint32_t count_prototypes_in_dex_pool(const GDexFormat *); + /* Extrait une représentation de routine d'une table DEX. */ GBinRoutine *get_prototype_from_dex_pool(GDexFormat *, uint32_t); +/* Compte le nombre de méthodes dans une table DEX. */ +uint32_t count_methods_in_dex_pool(const GDexFormat *); + /* Extrait une représentation de méthode d'une table DEX. */ GDexMethod *get_method_from_dex_pool(GDexFormat *, uint32_t); diff --git a/plugins/dex/python/Makefile.am b/plugins/dex/python/Makefile.am index d23ca65..8988eb8 100644 --- a/plugins/dex/python/Makefile.am +++ b/plugins/dex/python/Makefile.am @@ -3,8 +3,12 @@ noinst_LTLIBRARIES = libdexpython.la libdexpython_la_SOURCES = \ class.h class.c \ + constants.h constants.c \ + field.h field.c \ format.h format.c \ - module.h module.c + method.h method.c \ + module.h module.c \ + translate.h translate.c libdexpython_la_LDFLAGS = diff --git a/plugins/dex/python/class.c b/plugins/dex/python/class.c index ab7754e..a68e426 100644 --- a/plugins/dex/python/class.c +++ b/plugins/dex/python/class.c @@ -31,10 +31,419 @@ #include +#include "format.h" +#include "translate.h" #include "../class.h" +/* Fournit la définition brute d'une classe. */ +static PyObject *py_dex_class_get_definition(PyObject *, void *); + +/* Fournit la définition brute des données d'une classe. */ +static PyObject *py_dex_class_get_data(PyObject *, void *); + +/* Indique le type Android d'une classe. */ +static PyObject *py_dex_class_get_class_type(PyObject *, void *); + +/* Indique le type Android parent d'une classe. */ +static PyObject *py_dex_class_get_superclass_type(PyObject *, void *); + +/* Indique le type Android des interfaces d'une classe. */ +static PyObject *py_dex_class_get_interface_types(PyObject *, void *); + +/* Fournit les champs chargés correspondant à une classe donnée. */ +static PyObject *py_dex_class_get_fields(PyObject *, void *); + +/* Fournit les méthodes chargées correspondant à un type donné. */ +static PyObject *py_dex_class_get_methods(PyObject *, void *); + +/* Retrouve si possible le nom du fichier source d'une classe. */ +static PyObject *py_dex_class_get_source_file(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la définition brute d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_definition(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + const class_def_item *item; /* Elément à traiter */ + + class = G_DEX_CLASS(pygobject_get(self)); + + item = g_dex_class_get_definition(class); + + result = translate_dex_class_definition_to_python(item); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la définition brute des données d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé ou None si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_data(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + const class_data_item *item; /* Elément à traiter */ + + class = G_DEX_CLASS(pygobject_get(self)); + + item = g_dex_class_get_data(class); + + if (item == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + result = translate_dex_class_data_to_python(item); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique le type Android d'une classe. * +* * +* Retour : Type de classe ou None en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_class_type(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + GDataType *type; /* Type de classe */ + + class = G_DEX_CLASS(pygobject_get(self)); + + type = g_dex_class_get_class_type(class); + + if (type == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = pygobject_new(G_OBJECT(type)); + + g_object_unref(G_OBJECT(type)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique le type Android parent d'une classe. * +* * +* Retour : Type de classe ou None en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_superclass_type(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + GDataType *type; /* Type de classe */ + + class = G_DEX_CLASS(pygobject_get(self)); + + type = g_dex_class_get_superclass_type(class); + + if (type == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = pygobject_new(G_OBJECT(type)); + + g_object_unref(G_OBJECT(type)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique le type Android des interfaces d'une classe. * +* * +* Retour : Types de classe ou None en cas d'erreur ou d'absence. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_interface_types(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + size_t count; /* Nombre d'interfaces */ + GDataType **types; /* Types d'interfaces */ + size_t i; /* Boucle de parcours */ + PyObject *type; /* Type à ajouter à la liste */ + + class = G_DEX_CLASS(pygobject_get(self)); + + types = g_dex_class_get_interface_types(class, &count); + + if (count == 0) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + if (types[i] == NULL) + { + type = Py_None; + Py_INCREF(type); + } + else + { + type = pygobject_new(G_OBJECT(types[i])); + g_object_unref(G_OBJECT(types[i])); + } + + PyTuple_SetItem(result, i, type); + + } + + } + + if (types != NULL) + free(types); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = méthodes d'instance si non nul, statiques sinon. * +* * +* Description : Fournit les champs chargés correspondant à une classe donnée.* +* * +* Retour : Champs de classe ou None en cas d'erreur ou d'absence. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_fields(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + bool instance; /* Type de champs ciblés */ + size_t count; /* Nombre d'interfaces */ + size_t i; /* Boucle de parcours */ + GDexField *field; /* Champ à convertir */ + PyObject *fld; /* Objet à ajouter à la liste */ + + class = G_DEX_CLASS(pygobject_get(self)); + + instance = (closure != NULL); + + count = g_dex_class_count_fields(class, instance); + + if (count == 0) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + field = g_dex_class_get_field(class, instance, i); + + if (field == NULL) + { + fld = Py_None; + Py_INCREF(fld); + } + else + { + fld = pygobject_new(G_OBJECT(field)); + g_object_unref(G_OBJECT(field)); + } + + PyTuple_SetItem(result, i, fld); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = méthodes directes si non nul, virtuelles sinon. * +* * +* Description : Fournit les méthodes chargées correspondant à un type donné. * +* * +* Retour : Types de classe ou None en cas d'erreur ou d'absence. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_methods(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + bool virtual; /* Type de méthodes ciblées */ + size_t count; /* Nombre d'interfaces */ + size_t i; /* Boucle de parcours */ + GDexMethod *method; /* Méthode à convertir */ + PyObject *meth; /* Objet à ajouter à la liste */ + + class = G_DEX_CLASS(pygobject_get(self)); + + virtual = (closure == NULL); + + count = g_dex_class_count_methods(class, virtual); + + if (count == 0) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + method = g_dex_class_get_method(class, virtual, i); + + if (method == NULL) + { + meth = Py_None; + Py_INCREF(meth); + } + else + { + meth = pygobject_new(G_OBJECT(method)); + g_object_unref(G_OBJECT(method)); + } + + PyTuple_SetItem(result, i, meth); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Retrouve si possible le nom du fichier source d'une classe. * +* * +* Retour : Nom du fichier trouvé ou None si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_class_get_source_file(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexClass *class; /* Version native */ + const char *file; /* Fichier à l'origine du code */ + + class = G_DEX_CLASS(pygobject_get(self)); + + file = g_dex_class_get_source_file(class); + + if (file == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + result = PyUnicode_FromString(file); + + return result; + +} + + /****************************************************************************** * * * Paramètres : - * @@ -54,6 +463,46 @@ PyTypeObject *get_python_dex_class_type(void) }; static PyGetSetDef py_dex_class_getseters[] = { + { + "definition", py_dex_class_get_definition, NULL, + "Native definition of the Dex class.", NULL + }, + { + "data", py_dex_class_get_data, NULL, + "Native data of the Dex class, if any.", NULL + }, + { + "type", py_dex_class_get_class_type, NULL, + "Android type of the Dex class, None on error.", NULL + }, + { + "super", py_dex_class_get_superclass_type, NULL, + "Android type of the parent Dex class, None on error.", NULL + }, + { + "interfaces", py_dex_class_get_interface_types, NULL, + "Interface Android types of the Dex class, None if none and None on error.", NULL + }, + { + "static_fields", py_dex_class_get_fields, NULL, + "List of static fields of the Dex class, None if none and None on error.", NULL + }, + { + "instance_fields", py_dex_class_get_fields, NULL, + "List of static fields of the Dex class, None if none and None on error.", py_dex_class_get_fields + }, + { + "direct_methods", py_dex_class_get_methods, NULL, + "List of direct methods of the Dex class, None if none and None on error.", py_dex_class_get_methods + }, + { + "virtual_methods", py_dex_class_get_methods, NULL, + "List of virtual methods of the Dex class, None if none and None on error.", NULL + }, + { + "source_file", py_dex_class_get_source_file, NULL, + "Source file of the Dex class, None on error.", NULL + }, { NULL } }; diff --git a/plugins/dex/python/constants.c b/plugins/dex/python/constants.c new file mode 100644 index 0000000..ac50eb8 --- /dev/null +++ b/plugins/dex/python/constants.c @@ -0,0 +1,104 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.c - équivalent Python partiel du fichier "plugins/dex/dex_def.h" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "constants.h" + + +#include + + +#include "../dex_def.h" + + + +/* Définit les constantes communes pour le format Dex. */ +static bool define_python_dex_format_common_constants(PyTypeObject *); + + +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes communes pour le format Dex. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool define_python_dex_format_common_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + /* Définition des drapeaux d'accès */ + + if (result) result = PyDict_AddIntMacro(obj_type, ACC_PUBLIC); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_PRIVATE); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_PROTECTED); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_STATIC); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_FINAL); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_SYNCHRONIZED); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_VOLATILE); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_BRIDGE); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_TRANSIENT); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_VARARGS); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_NATIVE); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_INTERFACE); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_ABSTRACT); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_STRICT); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_SYNTHETIC); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_ANNOTATION); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_ENUM); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_CONSTRUCTOR); + if (result) result = PyDict_AddIntMacro(obj_type, ACC_DECLARED_SYNCHRONIZED); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour le format Dex. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_python_dex_format_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = define_python_dex_format_common_constants(obj_type); + + return result; + +} diff --git a/plugins/dex/python/constants.h b/plugins/dex/python/constants.h new file mode 100644 index 0000000..802bf2f --- /dev/null +++ b/plugins/dex/python/constants.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants.h - prototypes pour l'équivalent Python partiel du fichier "plugins/dex/dex_def.h" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_DEX_PYTHON_CONSTANTS_H +#define _PLUGINS_DEX_PYTHON_CONSTANTS_H + + +#include +#include + + + +/* Définit les constantes pour le format Dex. */ +bool define_python_dex_format_constants(PyTypeObject *); + + + +#endif /* _PLUGINS_DEX_PYTHON_CONSTANTS_H */ diff --git a/plugins/dex/python/field.c b/plugins/dex/python/field.c new file mode 100644 index 0000000..69faccc --- /dev/null +++ b/plugins/dex/python/field.c @@ -0,0 +1,186 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.c - équivalent Python du fichier "plugins/dex/field.c" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "field.h" + + +#include + + +#include + + +#include "translate.h" +#include "../field.h" + + + +/* Fournit les indications Dex concernant le champ de classe. */ +static PyObject *py_dex_field_get_encoded(PyObject *, void *); + +/* Fournit la variable Chrysalide correspondant au champ. */ +static PyObject *py_dex_field_get_variable(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les indications Dex concernant le champ de classe. * +* * +* Retour : Données brutes du binaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_field_get_encoded(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexField *field; /* Version native */ + const encoded_field *info; /* Elément à traiter */ + + field = G_DEX_FIELD(pygobject_get(self)); + + info = g_dex_field_get_dex_info(field); + + result = translate_dex_field_info_to_python(info); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la variable Chrysalide correspondant au champ. * +* * +* Retour : Instance de routine mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_field_get_variable(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexField *field; /* Version native */ + GBinVariable *variable; /* Variable correspondante */ + + field = G_DEX_FIELD(pygobject_get(self)); + + variable = g_dex_field_get_variable(field); + + result = pygobject_new(G_OBJECT(variable)); + + g_object_unref(G_OBJECT(variable)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_dex_field_type(void) +{ + static PyMethodDef py_dex_field_methods[] = { + { NULL } + }; + + static PyGetSetDef py_dex_field_getseters[] = { + { + "encoded", py_dex_field_get_encoded, NULL, + "Encoded information about the Dex field.", NULL + }, + { + "variable", py_dex_field_get_variable, NULL, + "Chrysalide variable for the Dex field.", NULL + }, + { NULL } + }; + + static PyTypeObject py_dex_field_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.dex.DexField", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide Dex class field.", + + .tp_methods = py_dex_field_methods, + .tp_getset = py_dex_field_getseters + + }; + + return &py_dex_field_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexField'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_dex_field(PyObject *module) +{ + PyTypeObject *py_dex_field_type; /* Type Python 'DexField' */ + PyObject *dict; /* Dictionnaire du module */ + + py_dex_field_type = get_python_dex_field_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_DEX_FIELD, py_dex_field_type, &PyGObject_Type)) + return false; + + return true; + +} diff --git a/plugins/dex/python/field.h b/plugins/dex/python/field.h new file mode 100644 index 0000000..fab0dce --- /dev/null +++ b/plugins/dex/python/field.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * field.h - prototypes pour l'équivalent Python du fichier "plugins/dex/field.h" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_DEX_PYTHON_FIELD_H +#define _PLUGINS_DEX_PYTHON_FIELD_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_dex_field_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.dex.DexField'. */ +bool register_python_dex_field(PyObject *module); + + + +#endif /* _PLUGINS_DEX_PYTHON_FIELD_H */ diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c index a421549..81db02f 100644 --- a/plugins/dex/python/format.c +++ b/plugins/dex/python/format.c @@ -36,8 +36,10 @@ #include +#include "constants.h" #include "../class.h" #include "../format.h" +#include "../pool.h" @@ -50,6 +52,24 @@ static PyObject *py_dex_format_count_classes(PyObject *, PyObject *); /* Fournit une classe du format chargée en mémoire. */ static PyObject *py_dex_format_get_class(PyObject *, PyObject *); +/* Fournit la liste de toutes les chaînes de la table globale. */ +static PyObject *py_dex_format_get_pool_strings(PyObject *, void *); + +/* Fournit la liste de tous les types de la table globale. */ +static PyObject *py_dex_format_get_pool_types(PyObject *, void *); + +/* Fournit la liste de tous les prototypes de la table globale. */ +static PyObject *py_dex_format_get_pool_prototypes(PyObject *, void *); + +/* Fournit la liste de tous les champs de la table globale. */ +static PyObject *py_dex_format_get_pool_fields(PyObject *, void *); + +/* Fournit la liste de toutes les méthodes de la table globale. */ +static PyObject *py_dex_format_get_pool_methods(PyObject *, void *); + +/* Fournit la liste de toutes les classes du format. */ +static PyObject *py_dex_format_get_classes(PyObject *, void *); + /****************************************************************************** @@ -152,6 +172,313 @@ static PyObject *py_dex_format_get_class(PyObject *self, PyObject *args) result = pygobject_new(G_OBJECT(class)); + g_object_unref(G_OBJECT(class)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de toutes les chaînes de la table globale. * +* * +* Retour : Liste vide ou remplie de chaînes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_pool_strings(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + uint32_t count; /* Nombre d'éléments à traiter */ + uint32_t i; /* Boucle de parcours */ + const char *string; /* Chaîne à intégrer */ + PyObject *str; /* Chaîne au format Python */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = count_strings_in_dex_pool(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + string = get_string_from_dex_pool(format, i, NULL); + + if (string == NULL) + { + str = Py_None; + Py_INCREF(str); + } + + else + str = PyUnicode_FromString(string); + + PyTuple_SetItem(result, i, str); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de tous les types de la table globale. * +* * +* Retour : Liste vide ou remplie de types. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_pool_types(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + uint32_t count; /* Nombre d'éléments à traiter */ + uint32_t i; /* Boucle de parcours */ + GDataType *type; /* Type à intégrer */ + PyObject *tp; /* Type au format Python */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = count_types_in_dex_pool(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + type = get_type_from_dex_pool(format, i); + + if (type == NULL) + { + tp = Py_None; + Py_INCREF(tp); + } + + else + { + tp = pygobject_new(G_OBJECT(type)); + g_object_unref(type); + } + + PyTuple_SetItem(result, i, tp); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de tous les champs de la table globale. * +* * +* Retour : Liste vide ou remplie de méthodes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_pool_fields(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + uint32_t count; /* Nombre d'éléments à traiter */ + uint32_t i; /* Boucle de parcours */ + GBinVariable *variable; /* Champ à intégrer */ + PyObject *var; /* Champ au format Python */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = count_fields_in_dex_pool(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + variable = get_field_from_dex_pool(format, i); + + if (variable == NULL) + { + var = Py_None; + Py_INCREF(var); + } + + else + { + var = pygobject_new(G_OBJECT(variable)); + g_object_unref(variable); + } + + PyTuple_SetItem(result, i, var); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de toutes les méthodes de la table globale. * +* * +* Retour : Liste vide ou remplie de méthodes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_pool_methods(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + uint32_t count; /* Nombre d'éléments à traiter */ + uint32_t i; /* Boucle de parcours */ + GDexMethod *method; /* Méthode à intégrer */ + PyObject *meth; /* Méthode au format Python */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = count_methods_in_dex_pool(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + method = get_method_from_dex_pool(format, i); + + if (method == NULL) + { + meth = Py_None; + Py_INCREF(meth); + } + + else + { + meth = pygobject_new(G_OBJECT(method)); + g_object_unref(method); + } + + PyTuple_SetItem(result, i, meth); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de tous les prototypes de la table globale. * +* * +* Retour : Liste vide ou remplie de méthodes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_pool_prototypes(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + uint32_t count; /* Nombre d'éléments à traiter */ + uint32_t i; /* Boucle de parcours */ + GBinRoutine *routine; /* Routine à intégrer */ + PyObject *rtn; /* Routine au format Python */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = count_prototypes_in_dex_pool(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + routine = get_prototype_from_dex_pool(format, i); + + if (routine == NULL) + { + rtn = Py_None; + Py_INCREF(rtn); + } + + else + { + rtn = pygobject_new(G_OBJECT(routine)); + g_object_unref(routine); + } + + PyTuple_SetItem(result, i, rtn); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la liste de toutes les classes du format. * +* * +* Retour : Liste vide ou remplie de classes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_format_get_classes(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexFormat *format; /* Version native */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + GDexClass *class; /* Classe du format à intégrer */ + + format = G_DEX_FORMAT(pygobject_get(self)); + + count = g_dex_format_count_classes(format); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { + class = g_dex_format_get_class(format, i); + assert(class != NULL); + + PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(class))); + + g_object_unref(G_OBJECT(class)); + + } + return result; } @@ -186,6 +513,30 @@ PyTypeObject *get_python_dex_format_type(void) }; static PyGetSetDef py_dex_format_getseters[] = { + { + "pool_strings", py_dex_format_get_pool_strings, NULL, + "Strings inside the Dex pool.", NULL + }, + { + "pool_types", py_dex_format_get_pool_types, NULL, + "Types inside the Dex pool.", NULL + }, + { + "pool_prototypes", py_dex_format_get_pool_prototypes, NULL, + "Prototypes inside the Dex pool.", NULL + }, + { + "pool_fields", py_dex_format_get_pool_fields, NULL, + "Fields inside the Dex pool.", NULL + }, + { + "pool_methods", py_dex_format_get_pool_methods, NULL, + "Methods inside the Dex pool.", NULL + }, + { + "classes", py_dex_format_get_classes, NULL, + "Classes inside the Dex format.", NULL + }, { NULL } }; @@ -236,6 +587,9 @@ bool register_python_dex_format(PyObject *module) py_dex_format_type, get_python_executable_format_type())) return false; + if (!define_python_dex_format_constants(py_dex_format_type)) + return false; + return true; } diff --git a/plugins/dex/python/method.c b/plugins/dex/python/method.c new file mode 100644 index 0000000..4f35e1a --- /dev/null +++ b/plugins/dex/python/method.c @@ -0,0 +1,223 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * method.c - équivalent Python du fichier "plugins/dex/method.c" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "method.h" + + +#include + + +#include + + +#include "translate.h" +#include "../method.h" + + + +/* Fournit les indications Dex concernant la méthode. */ +static PyObject *py_dex_method_get_encoded(PyObject *, void *); + +/* Fournit les indications Dex relatives au corps de la méthode. */ +static PyObject *py_dex_method_get_code_item(PyObject *, void *); + +/* Fournit la routine Chrysalide correspondant à la méthode. */ +static PyObject *py_dex_method_get_routine(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les indications Dex concernant la méthode. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_method_get_encoded(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexMethod *method; /* Version native */ + const encoded_method *info; /* Elément à traiter */ + + method = G_DEX_METHOD(pygobject_get(self)); + + info = g_dex_method_get_dex_info(method); + + result = translate_dex_method_info_to_python(info); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les indications Dex relatives au corps de la méthode.* +* * +* Retour : Données brutes du binaire, ou None si aucunes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_method_get_code_item(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexMethod *method; /* Version native */ + const code_item *body; /* Elément à traiter */ + + method = G_DEX_METHOD(pygobject_get(self)); + + body = g_dex_method_get_dex_body(method); + + result = translate_dex_method_body_to_python(body); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la routine Chrysalide correspondant à la méthode. * +* * +* Retour : Instance de routine mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_dex_method_get_routine(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDexMethod *method; /* Version native */ + GBinRoutine *routine; /* Routine correspondante */ + + method = G_DEX_METHOD(pygobject_get(self)); + + routine = g_dex_method_get_routine(method); + + result = pygobject_new(G_OBJECT(routine)); + + g_object_unref(G_OBJECT(routine)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_dex_method_type(void) +{ + static PyMethodDef py_dex_method_methods[] = { + { NULL } + }; + + static PyGetSetDef py_dex_method_getseters[] = { + { + "encoded", py_dex_method_get_encoded, NULL, + "Encoded information about the Dex method.", NULL + }, + { + "code_item", py_dex_method_get_code_item, NULL, + "Code information about the Dex method, None if none.", NULL + }, + { + "routine", py_dex_method_get_routine, NULL, + "Chrysalide routine for the Dex method.", NULL + }, + { NULL } + }; + + static PyTypeObject py_dex_method_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.dex.DexMethod", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide Dex method.", + + .tp_methods = py_dex_method_methods, + .tp_getset = py_dex_method_getseters + + }; + + return &py_dex_method_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.dex.DexMethod'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_dex_method(PyObject *module) +{ + PyTypeObject *py_dex_method_type; /* Type Python 'DexMethod' */ + PyObject *dict; /* Dictionnaire du module */ + + py_dex_method_type = get_python_dex_method_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_DEX_METHOD, py_dex_method_type, &PyGObject_Type)) + return false; + + return true; + +} diff --git a/plugins/dex/python/method.h b/plugins/dex/python/method.h new file mode 100644 index 0000000..9c0c917 --- /dev/null +++ b/plugins/dex/python/method.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * method.h - prototypes pour l'équivalent Python du fichier "plugins/dex/method.h" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_DEX_PYTHON_METHOD_H +#define _PLUGINS_DEX_PYTHON_METHOD_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_dex_method_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.dex.DexMethod'. */ +bool register_python_dex_method(PyObject *module); + + + +#endif /* _PLUGINS_DEX_PYTHON_METHOD_H */ diff --git a/plugins/dex/python/module.c b/plugins/dex/python/module.c index acb2370..6a84af3 100644 --- a/plugins/dex/python/module.c +++ b/plugins/dex/python/module.c @@ -32,7 +32,9 @@ #include "class.h" +#include "field.h" #include "format.h" +#include "method.h" @@ -86,8 +88,14 @@ bool add_format_dex_module_to_python_module(void) result = register_python_dex_class(module); if (result) + result = register_python_dex_field(module); + + if (result) result = register_python_dex_format(module); + if (result) + result = register_python_dex_method(module); + loading_failed: return result; diff --git a/plugins/dex/python/translate.c b/plugins/dex/python/translate.c new file mode 100644 index 0000000..eb80c43 --- /dev/null +++ b/plugins/dex/python/translate.c @@ -0,0 +1,293 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.c - conversion de structures Dex en objets Python + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "translate.h" + + +#include + + +#include + + +#include "../dex_def.h" + + + +/****************************************************************************** +* * +* Paramètres : info = ensemble d'informations Dex à décrire en Python. * +* * +* Description : Traduit des informations de champ de classe Dex en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_dex_field_info_to_python(const encoded_field *info) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_ENCODED_FIELD_PROP(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(info->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto tdcdtp_failed; \ + } \ + while (0); + + TRANSLATE_ENCODED_FIELD_PROP(field_idx_diff); + TRANSLATE_ENCODED_FIELD_PROP(access_flags); + + return result; + + tdcdtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble d'informations Dex à décrire en Python. * +* * +* Description : Traduit des informations de méthode Dex en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_dex_method_info_to_python(const encoded_method *info) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_ENCODED_METHOD_PROP(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(info->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto tdcdtp_failed; \ + } \ + while (0); + + TRANSLATE_ENCODED_METHOD_PROP(method_idx_diff); + TRANSLATE_ENCODED_METHOD_PROP(access_flags); + TRANSLATE_ENCODED_METHOD_PROP(code_off); + + return result; + + tdcdtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : info = ensemble d'informations Dex à décrire en Python. * +* * +* Description : Traduit des informations de corps de méthode Dex en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_dex_method_body_to_python(const code_item *body) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_CODE_ITEM_PROP(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(body->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto tdcdtp_failed; \ + } \ + while (0); + + TRANSLATE_CODE_ITEM_PROP(registers_size); + TRANSLATE_CODE_ITEM_PROP(ins_size); + TRANSLATE_CODE_ITEM_PROP(outs_size); + TRANSLATE_CODE_ITEM_PROP(tries_size); + TRANSLATE_CODE_ITEM_PROP(debug_info_off); + TRANSLATE_CODE_ITEM_PROP(insns_size); + + return result; + + tdcdtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : item = ensemble d'informations Dex à décrire en Python. * +* * +* Description : Traduit une définition de classe Dex en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_dex_class_definition_to_python(const class_def_item *item) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_CLASS_DEF_PROP(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(item->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto tdcdtp_failed; \ + } \ + while (0); + + TRANSLATE_CLASS_DEF_PROP(class_idx); + TRANSLATE_CLASS_DEF_PROP(access_flags); + TRANSLATE_CLASS_DEF_PROP(superclass_idx); + TRANSLATE_CLASS_DEF_PROP(interfaces_off); + TRANSLATE_CLASS_DEF_PROP(source_file_idx); + TRANSLATE_CLASS_DEF_PROP(annotations_off); + TRANSLATE_CLASS_DEF_PROP(class_data_off); + TRANSLATE_CLASS_DEF_PROP(static_values_off); + + return result; + + tdcdtp_failed: + + Py_DECREF(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : item = ensemble d'informations Dex à décrire en Python. * +* * +* Description : Traduit des données de classe Dex en Python. * +* * +* Retour : Structure mise en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *translate_dex_class_data_to_python(const class_data_item *item) +{ + PyObject *result; /* Construction à retourner */ + PyTypeObject *base; /* Modèle d'objet à créer */ + PyObject *attrib; /* Attribut à constituer */ + int ret; /* Bilan d'une mise en place */ + + base = get_python_py_struct_type(); + + result = PyObject_CallFunction((PyObject *)base, NULL); + assert(result != NULL); + + /* Champs réguliers */ + +#define TRANSLATE_CLASS_DATA_PROP(_f) \ + do \ + { \ + attrib = PyLong_FromUnsignedLongLong(item->_f); \ + ret = PyDict_SetItemString(result, #_f, attrib); \ + if (ret != 0) goto tdcdtp_failed; \ + } \ + while (0); + + TRANSLATE_CLASS_DATA_PROP(static_fields_size); + TRANSLATE_CLASS_DATA_PROP(instance_fields_size); + TRANSLATE_CLASS_DATA_PROP(direct_methods_size); + TRANSLATE_CLASS_DATA_PROP(virtual_methods_size); + + return result; + + tdcdtp_failed: + + Py_DECREF(result); + + return NULL; + +} diff --git a/plugins/dex/python/translate.h b/plugins/dex/python/translate.h new file mode 100644 index 0000000..29a0155 --- /dev/null +++ b/plugins/dex/python/translate.h @@ -0,0 +1,53 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * translate.h - prototypes pour la conversion de structures Dex en objets Python + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_DEX_PYTHON_TRANSLATE_H +#define _PLUGINS_DEX_PYTHON_TRANSLATE_H + + +#include + + +#include "../format.h" + + + +/* Traduit des informations de champ de classe Dex en Python. */ +PyObject *translate_dex_field_info_to_python(const encoded_field *); + +/* Traduit des informations de méthode Dex en Python. */ +PyObject *translate_dex_method_info_to_python(const encoded_method *); + +/* Traduit des informations de corps de méthode Dex en Python. */ +PyObject *translate_dex_method_body_to_python(const code_item *); + +/* Traduit une définition de classe Dex en Python. */ +PyObject *translate_dex_class_definition_to_python(const class_def_item *); + +/* Traduit des données de classe Dex en Python. */ +PyObject *translate_dex_class_data_to_python(const class_data_item *); + + + +#endif /* _PLUGINS_DEX_PYTHON_TRANSLATE_H */ diff --git a/plugins/elf/python/constants.c b/plugins/elf/python/constants.c index 098443c..25b739a 100644 --- a/plugins/elf/python/constants.c +++ b/plugins/elf/python/constants.c @@ -33,7 +33,7 @@ /* Définit les constantes communes pour le format Elf. */ -static bool define_python_binary_format_common_constants(PyTypeObject *); +static bool define_python_elf_format_common_constants(PyTypeObject *); /****************************************************************************** @@ -48,7 +48,7 @@ static bool define_python_binary_format_common_constants(PyTypeObject *); * * ******************************************************************************/ -static bool define_python_binary_format_common_constants(PyTypeObject *obj_type) +static bool define_python_elf_format_common_constants(PyTypeObject *obj_type) { bool result; /* Bilan à retourner */ @@ -379,11 +379,11 @@ static bool define_python_binary_format_common_constants(PyTypeObject *obj_type) * * ******************************************************************************/ -bool define_python_binary_format_constants(PyTypeObject *obj_type) +bool define_python_elf_format_constants(PyTypeObject *obj_type) { bool result; /* Bilan à retourner */ - result = define_python_binary_format_common_constants(obj_type); + result = define_python_elf_format_common_constants(obj_type); return result; diff --git a/plugins/elf/python/constants.h b/plugins/elf/python/constants.h index 95b840c..d395230 100644 --- a/plugins/elf/python/constants.h +++ b/plugins/elf/python/constants.h @@ -32,7 +32,7 @@ /* Définit les constantes pour le format Elf. */ -bool define_python_binary_format_constants(PyTypeObject *); +bool define_python_elf_format_constants(PyTypeObject *); diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c index 2d5bfd8..0319ba9 100644 --- a/plugins/elf/python/format.c +++ b/plugins/elf/python/format.c @@ -257,7 +257,7 @@ bool register_python_elf_format(PyObject *module) py_elf_format_type, get_python_executable_format_type())) return false; - if (!define_python_binary_format_constants(py_elf_format_type)) + if (!define_python_elf_format_constants(py_elf_format_type)) return false; return true; diff --git a/plugins/pychrysalide/analysis/Makefile.am b/plugins/pychrysalide/analysis/Makefile.am index 570235d..edac3c0 100644 --- a/plugins/pychrysalide/analysis/Makefile.am +++ b/plugins/pychrysalide/analysis/Makefile.am @@ -10,7 +10,8 @@ libpychrysaanalysis_la_SOURCES = \ module.h module.c \ project.h project.c \ routine.h routine.c \ - type.h type.c + type.h type.c \ + variable.h variable.c libpychrysaanalysis_la_LIBADD = \ contents/libpychrysaanalysiscontents.la \ diff --git a/plugins/pychrysalide/analysis/module.c b/plugins/pychrysalide/analysis/module.c index c9ab1e5..614adf0 100644 --- a/plugins/pychrysalide/analysis/module.c +++ b/plugins/pychrysalide/analysis/module.c @@ -36,6 +36,7 @@ #include "project.h" #include "routine.h" #include "type.h" +#include "variable.h" #include "contents/module.h" #include "db/module.h" #include "../access.h" @@ -98,6 +99,7 @@ bool add_analysis_module_to_python_module(PyObject *super) result &= register_python_binary_routine(module); result &= register_python_data_type(module); result &= register_python_study_project(module); + result &= register_python_binary_variable(module); result &= add_analysis_contents_module_to_python_module(module); result &= add_analysis_db_module_to_python_module(module); diff --git a/plugins/pychrysalide/analysis/type.c b/plugins/pychrysalide/analysis/type.c index eea9596..1d9e9f0 100644 --- a/plugins/pychrysalide/analysis/type.c +++ b/plugins/pychrysalide/analysis/type.c @@ -61,7 +61,7 @@ static PyObject *py_data_type_to_str(PyObject *self) type = G_DATA_TYPE(pygobject_get(self)); - desc = g_data_type_to_string(type); + desc = _g_data_type_to_string(type, false); result = PyUnicode_FromString(desc); diff --git a/plugins/pychrysalide/analysis/variable.c b/plugins/pychrysalide/analysis/variable.c new file mode 100644 index 0000000..7437e54 --- /dev/null +++ b/plugins/pychrysalide/analysis/variable.c @@ -0,0 +1,268 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * variable.c - équivalent Python du fichier "analysis/variable.c" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "variable.h" + + +#include +#include + + +#include + + +#include + + +#include "../helpers.h" + + + +/* Décrit la variable donnée sous forme de caractères. */ +static PyObject *py_binary_variable_to_str(PyObject *); + +/* Fournit le type d'une variable donnée. */ +static PyObject *py_binary_variable_get_type(PyObject *, void *); + +/* Fournit le nom d'une variable donnée. */ +static PyObject *py_binary_variable_get_name(PyObject *, void *); + +/* Définit le nom d'une variable donnée. */ +static int py_binary_variable_set_name(PyObject *, PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = instance d'une variable version Python à traiter. * +* * +* Description : Décrit la variable donnée sous forme de caractères. * +* * +* Retour : Chaîne de caractère construite pour l'occasion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_variable_to_str(PyObject *self) +{ + PyObject *result; /* Représentation à retourner */ + GBinVariable *variable; /* Version native de l'objet */ + char *desc; /* Description du type */ + + variable = G_BIN_VARIABLE(pygobject_get(self)); + + desc = g_binary_variable_to_string(variable, true); + + result = PyUnicode_FromString(desc); + + free(desc); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le type d'une variable donnée. * +* * +* Retour : Type de la variable. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_variable_get_type(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinVariable *variable; /* Elément à consulter */ + GDataType *type; /* Type natif de la variable */ + + variable = G_BIN_VARIABLE(pygobject_get(self)); + + type = g_binary_variable_get_vtype(variable); + + result = pygobject_new(G_OBJECT(type)); + + g_object_unref(G_OBJECT(type)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit le nom d'une variable donnée. * +* * +* Retour : Nom de la variable ou None si non précisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_variable_get_name(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GBinVariable *variable; /* Elément à consulter */ + const char *name; /* Désignation courante */ + + variable = G_BIN_VARIABLE(pygobject_get(self)); + name = g_binary_variable_get_name(variable); + + if (name != NULL) + result = PyUnicode_FromString(name); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * +* * +* Description : Définit le nom d'une variable donnée. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_variable_set_name(PyObject *self, PyObject *value, void *closure) +{ + GBinVariable *variable; /* Elément à consulter */ + + if (!PyUnicode_Check(value) && value != Py_None) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string.")); + return -1; + } + + variable = G_BIN_VARIABLE(pygobject_get(self)); + + if (!PyUnicode_Check(value)) + g_binary_variable_set_name(variable, PyUnicode_DATA(value)); + else + g_binary_variable_set_name(variable, NULL); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_variable_type(void) +{ + static PyMethodDef py_binary_variable_methods[] = { + { NULL } + }; + + static PyGetSetDef py_binary_variable_getseters[] = { + { + "type", py_binary_variable_get_type, NULL, + "Type of the current variable.", NULL + }, + { + "name", py_binary_variable_get_name, py_binary_variable_set_name, + "Name of the current variable.", NULL + }, + { NULL } + }; + + static PyTypeObject py_binary_variable_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.BinVariable", + + .tp_str = py_binary_variable_to_str, + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide binary variable", + + .tp_methods = py_binary_variable_methods, + .tp_getset = py_binary_variable_getseters + + }; + + return &py_binary_variable_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis.BinVariable'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_binary_variable(PyObject *module) +{ + PyTypeObject *py_binary_variable_type; /* Type Python 'BinVariable' */ + PyObject *dict; /* Dictionnaire du module */ + + py_binary_variable_type = get_python_binary_variable_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_BIN_VARIABLE, py_binary_variable_type, &PyGObject_Type)) + return false; + + return true; + +} diff --git a/plugins/pychrysalide/analysis/variable.h b/plugins/pychrysalide/analysis/variable.h new file mode 100644 index 0000000..dad56d6 --- /dev/null +++ b/plugins/pychrysalide/analysis/variable.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * variable.h - prototypes pour l'équivalent Python du fichier "analysis/variable.h" + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_VARIABLE_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_VARIABLE_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_variable_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.BinVariable'. */ +bool register_python_binary_variable(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_VARIABLE_H */ diff --git a/plugins/readdex/class.c b/plugins/readdex/class.c index 9aa4433..c414821 100644 --- a/plugins/readdex/class.c +++ b/plugins/readdex/class.c @@ -297,7 +297,7 @@ bool annotate_dex_class_defs(const GDexFormat *format, GPreloadInfo *info, GtkSt if (def->class_data_off > 0) result = annotate_dex_class_data(format, info, class, def->class_data_off); - /* TODO : g_object_unref(G_OBJECT(class));*/ + g_object_unref(G_OBJECT(class)); gtk_status_stack_update_activity_value(status, msg, 1); diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 336838b..6e56e2d 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -566,7 +566,7 @@ const char *g_binary_routine_get_declarator(GBinRoutine *routine, bool full) if (routine->full_name != NULL) new = _g_data_type_to_string(routine->full_name, false); else - new = routine->name; + new = strdup(routine->name != NULL ? routine->name : ""); if (routine->namespace != NULL) { diff --git a/src/analysis/variable.c b/src/analysis/variable.c index f30c659..95b7a9c 100644 --- a/src/analysis/variable.c +++ b/src/analysis/variable.c @@ -149,7 +149,13 @@ GBinVariable *g_binary_variable_new(GDataType *type) GDataType *g_binary_variable_get_vtype(const GBinVariable *var) { - return var->type; + GDataType *result; /* Instance à retourner */ + + result = var->type; + + g_object_ref(G_OBJECT(result)); + + return result; } diff --git a/src/analysis/variable.h b/src/analysis/variable.h index 9fbdc4e..bc284ae 100644 --- a/src/analysis/variable.h +++ b/src/analysis/variable.h @@ -37,12 +37,12 @@ /* ------------------- ASSOCIATION D'UN TYPE ET D'UNE DESIGNATION ------------------- */ -#define G_TYPE_BIN_VARIABLE g_binary_variable_get_type() -#define G_BINARY_VARIABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_variable_get_type(), GBinVariable)) -#define G_IS_BIN_VARIABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_variable_get_type())) -#define G_BINARY_VARIABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_VARIABLE, GBinVariableClass)) -#define G_IS_BIN_VARIABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_VARIABLE)) -#define G_BINARY_VARIABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_VARIABLE, GBinVariableClass)) +#define G_TYPE_BIN_VARIABLE g_binary_variable_get_type() +#define G_BIN_VARIABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_VARIABLE, GBinVariable)) +#define G_IS_BIN_VARIABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_VARIABLE)) +#define G_BIN_VARIABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_VARIABLE, GBinVariableClass)) +#define G_IS_BIN_VARIABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_VARIABLE)) +#define G_BIN_VARIABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_VARIABLE, GBinVariableClass)) /* Base de variable (instance) */ -- cgit v0.11.2-87-g4458