diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-10-18 20:50:10 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-10-18 20:50:10 (GMT) |
commit | dce9d9cdfef1d37ef11a987a21f36e83b6b1944f (patch) | |
tree | 830623ade20e892954fcbddd3b7b05d09aac1dd7 /plugins/dex/class.c | |
parent | 1e7c7de85438749d3faf7b76984b86a9c088fbc1 (diff) |
Created plugins for the Dex and Dalvik support.
Diffstat (limited to 'plugins/dex/class.c')
-rw-r--r-- | plugins/dex/class.c | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/plugins/dex/class.c b/plugins/dex/class.c new file mode 100644 index 0000000..bb2ae71 --- /dev/null +++ b/plugins/dex/class.c @@ -0,0 +1,576 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * class.c - manipulation des classes du format DEX + * + * Copyright (C) 2010-2017 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "class.h" + + +#include <malloc.h> + + +#include "dex-int.h" +#include "method.h" +#include "pool.h" + + + +/* Classe issue du code source (instance) */ +struct _GDexClass +{ + GObject parent; /* A laisser en premier */ + + class_def_item definition; /* Définition de la classe */ + bool has_data; /* Indicateur de présence */ + class_data_item data; /* Contenu de la classe */ + + GDexMethod **direct_methods; /* Méthodes propres */ + size_t dmethods_count; /* Quantité de ces méthodes */ + GDexMethod **virtual_methods; /* Méthodes virtuelles */ + size_t vmethods_count; /* Quantité de ces méthodes */ + +}; + +/* Classe issue du code source (classe) */ +struct _GDexClassClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Procède à l'initialisation d'une classe issue du code source. */ +static void g_dex_class_class_init(GDexClassClass *); + +/* Procède à l'initialisation d'une classe issue du code source. */ +static void g_dex_class_init(GDexClass *); + +/* Supprime toutes les références externes. */ +static void g_dex_class_dispose(GDexClass *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dex_class_finalize(GDexClass *); + +/* Inscrit les méthodes d'une classe en tant que routines. */ +//static void g_dex_class_register_method(const GDexClass *, GBinFormat *); + + + +/* Détermine le type d'une classe issue du code source. */ +G_DEFINE_TYPE(GDexClass, g_dex_class, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe issue du code source.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_class_init(GDexClassClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_class_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_class_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : class = composant GLib à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe issue du code source.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_init(GDexClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : class = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_dispose(GDexClass *class) +{ + size_t i; /* Boucle de parcours */ + + if (class->direct_methods != NULL) + for (i = 0; i < class->dmethods_count; i++) + if (class->direct_methods[i] != NULL) + g_object_unref(G_OBJECT(class->direct_methods[i])); + + if (class->virtual_methods != NULL) + for (i = 0; i < class->vmethods_count; i++) + if (class->virtual_methods[i] != NULL) + g_object_unref(G_OBJECT(class->virtual_methods[i])); + + G_OBJECT_CLASS(g_dex_class_parent_class)->dispose(G_OBJECT(class)); + +} + + +/****************************************************************************** +* * +* Paramètres : class = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_class_finalize(GDexClass *class) +{ + if (class->direct_methods != NULL) + free(class->direct_methods); + + if (class->virtual_methods != NULL) + free(class->virtual_methods); + + G_OBJECT_CLASS(g_dex_class_parent_class)->finalize(G_OBJECT(class)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = représentation interne du format DEX à consulter. * +* def = définitions générales associées à la classe. * +* * +* Description : Crée une nouvelle représentation de classe issue de code. * +* * +* Retour : Composant GLib créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 */ + GDexMethod *method; /* Méthode chargée */ + GBinRoutine *routine; /* Version interne de méthode */ + + result = g_object_new(G_TYPE_DEX_CLASS, NULL); + + result->definition = *def; + result->has_data = (def->class_data_off != 0); + + /* Interface vide ? */ + if (!result->has_data) + { + result->dmethods_count = 0; + result->direct_methods = NULL; + + result->vmethods_count = 0; + result->virtual_methods = NULL; + + goto gdcn_done; + + } + + init_vmpa(&addr, def->class_data_off, VMPA_NO_VIRTUAL); + + if (!read_dex_class_data_item(format, &addr, &data)) + goto gdcn_bad_item; + + result->data = data; + + /** + * On évite ici les méthodes (virtuelles) non définies. + */ + if (def->access_flags & ACC_ANNOTATION) goto gdcn_done; + + ctype = get_type_from_dex_pool(format, def->class_idx); + if (ctype == NULL) goto gdcn_unknown_type; + + base = G_BIN_FORMAT(format); + + index = 0; + + result->dmethods_count = data.direct_methods_size; + result->direct_methods = (GDexMethod **)calloc(result->dmethods_count, sizeof(GDexMethod *)); + + for (i = 0; i < data.direct_methods_size; i++) + { + method = g_dex_method_new_defined(format, &data.direct_methods[i], &index); + if (method == NULL) goto gdcn_bad_method; + + result->direct_methods[i] = method; + + /* Ajout à la liste des symboles */ + if (g_dex_method_has_dex_body(method)) + { + routine = g_dex_method_get_routine(method); + + g_object_ref(G_OBJECT(ctype)); + g_binary_routine_set_namespace(routine, ctype, "."); + + g_binary_format_add_symbol(base, G_BIN_SYMBOL(routine)); + + } + + } + + index = 0; + + result->vmethods_count = data.virtual_methods_size; + result->virtual_methods = (GDexMethod **)calloc(result->vmethods_count, sizeof(GDexMethod *)); + + for (i = 0; i < data.virtual_methods_size; i++) + { + method = g_dex_method_new_defined(format, &data.virtual_methods[i], &index); + if (method == NULL) goto gdcn_bad_method; + + result->virtual_methods[i] = method; + + /* Ajout à la liste des symboles */ + if (g_dex_method_has_dex_body(method)) + { + routine = g_dex_method_get_routine(method); + + g_object_ref(G_OBJECT(ctype)); + g_binary_routine_set_namespace(routine, ctype, "."); + + g_binary_format_add_symbol(base, G_BIN_SYMBOL(routine)); + + } + + } + + g_object_unref(G_OBJECT(ctype)); + + gdcn_done: + + return result; + + gdcn_bad_method: + + g_object_unref(G_OBJECT(ctype)); + + gdcn_unknown_type: + + gdcn_bad_item: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* * +* Description : Fournit la définition brute d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const class_def_item *g_dex_class_get_definition(const GDexClass *class) +{ + return &class->definition; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* * +* Description : Fournit la définition brute des données d'une classe. * +* * +* Retour : Données brutes issues du binaire chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const class_data_item *g_dex_class_get_data(const GDexClass *class) +{ + return (class->has_data ? &class->data : NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* virtual = précise la nature des méthodes ciblées. * +* * +* Description : Dénombre les méthodes chargées d'un type donné. * +* * +* Retour : Quantité de méthodes trouvées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_dex_class_count_methods(const GDexClass *class, bool virtual) +{ + size_t result; /* Compte à retourner */ + + if (virtual) + result = class->vmethods_count; + else + result = class->dmethods_count; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* virtual = précise la nature des méthodes ciblées. * +* index = indique l'indice de la méthode désirée. * +* * +* Description : Fournit une méthode chargée correspondant à un type donné. * +* * +* Retour : Quantité de méthodes trouvées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexMethod *g_dex_class_get_method(const GDexClass *class, bool virtual, size_t index) +{ + GDexMethod *result; /* Instance à renvoyer */ + + if (virtual) + result = class->virtual_methods[index]; + else + result = class->direct_methods[index]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* format = format permettant d'obtenir une adresse complète. * +* * +* Description : Intègre la méthode en tant que portion de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dex_class_include_as_portion(const GDexClass *class, GExeFormat *format) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < class->dmethods_count; i++) + g_dex_method_include_as_portion(class->direct_methods[i], format); + + for (i = 0; i < class->vmethods_count; i++) + g_dex_method_include_as_portion(class->virtual_methods[i], format); + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* addr = adresse de la routine à retrouver. * +* * +* Description : Retrouve si possible la méthode associée à une adresse. * +* * +* Retour : Méthde retrouvée ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexMethod *g_dex_class_find_method_by_address(const GDexClass *class, vmpa_t addr) +{ + GDexMethod *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + phys_t offset; /* Emplacement de méthode */ + + result = NULL; + +#if 0 /* FIXME */ + /* + +bool g_dex_method_get_offset(const GDexMethod *method, phys_t *offset) + + if (!g_exe_format_translate_offset_into_vmpa(G_EXE_FORMAT(format), method->offset, &addr)) + return; + + */ + + for (i = 0; i < class->dmethods_count && result == NULL; i++) + if (addr == (vmpa_t)g_dex_method_get_offset(class->direct_methods[i])) + result = class->direct_methods[i]; + + for (i = 0; i < class->vmethods_count && result == NULL; i++) + if (addr == (vmpa_t)g_dex_method_get_offset(class->virtual_methods[i])) + result = class->virtual_methods[i]; +#endif + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* format = représentation interne du format DEX à compléter. * +* * +* Description : Retrouve si possible le nom du fichier source d'une classe. * +* * +* Retour : Nom du fichier trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_dex_class_get_source_file(const GDexClass *class, const GDexFormat *format) +{ + const char *result; /* Trouvaille à renvoyer */ + + result = get_string_from_dex_pool(format, class->definition.source_file_idx, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = informations chargées à consulter. * +* lang = langage à utiliser pour la sortie humaine. * +* buffer = tampon mis à disposition pour la sortie. * +* format = informations chargées à consulter. * +* * +* Description : Procède à la décompilation complète d'une classe donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#if 0 +void g_dex_class_decompile(const GDexClass *class, GLangOutput *lang, GCodeBuffer *buffer, const GDexFormat *format) +{ + +#if 0 + GDataType *type; + + + size_t i; /* Boucle de parcours */ + + + /* +GBufferLine *line, GLangOutput *output) + + for (i = 0; i < block->count; i++) + { + if (i > 0) + line = g_code_buffer_append_new_line(buffer); + +*/ + + + + type = get_type_from_dex_pool(format, class->definition.class_idx); + + //g_buffer_line_append_text(line, BLC_ASSEMBLY, "{", 3, RTT_SIGNS, NULL); + + //printf("Output :: %s\n", _g_data_type_to_string(type, true)); + + + + g_lang_output_start_class(lang, buffer, type); + + + + for (i = 0; i < class->vmethods_count; i++) + { + g_dex_method_decompile(class->virtual_methods[i], lang, buffer); + g_code_buffer_append_new_line_fixme(buffer); + } + + for (i = 0; i < class->dmethods_count; i++) + { + g_dex_method_decompile(class->direct_methods[i], lang, buffer); + g_code_buffer_append_new_line_fixme(buffer); + } + + + + + + + + + g_lang_output_end_class(lang, buffer); + + + +#endif + + +} +#endif |