diff options
Diffstat (limited to 'plugins/dex/format.c')
-rwxr-xr-x | plugins/dex/format.c | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/plugins/dex/format.c b/plugins/dex/format.c new file mode 100755 index 0000000..72d0dd5 --- /dev/null +++ b/plugins/dex/format.c @@ -0,0 +1,611 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * format.c - support 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 "format.h" + + +#include <string.h> + + +#include <i18n.h> +#include <core/global.h> +#include <plugins/pglist.h> + + +#include "dex-int.h" +#include "pool.h" + + + +/* Initialise la classe des formats d'exécutables DEX. */ +static void g_dex_format_class_init(GDexFormatClass *); + +/* Initialise une instance de format d'exécutable DEX. */ +static void g_dex_format_init(GDexFormat *); + +/* Supprime toutes les références externes. */ +static void g_dex_format_dispose(GDexFormat *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dex_format_finalize(GDexFormat *); + +/* Informe quant au boutisme utilisé. */ +static SourceEndian g_dex_format_get_endianness(const GDexFormat *); + +/* Indique le type d'architecture visée par le format. */ +static const char *g_dex_format_get_target_machine(const GDexFormat *); + +/* Etend la définition des portions au sein d'un binaire. */ +static void g_dex_format_refine_portions(GDexFormat *); + +/* Fournit l'emplacement d'une section donnée. */ +static bool g_dex_format_get_section_range_by_name(const GDexFormat *, const char *, mrange_t *); + + + + + + + + + + + + + +/* Détermine tous les fichiers source indiqués. */ +//static void g_dex_format_find_all_sources(GDexFormat *); + +/* Procède à la décompilation complète du format. */ +static void g_dex_format_decompile(const GDexFormat *, void/*GCodeBuffer*/ *, const char *); + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* parent = éventuel format exécutable déjà chargé. * +* unused = adresse non utilisée ici. * +* key = identifiant de format trouvé ou NULL. [OUT] * +* * +* Description : Indique si le format peut être pris en charge ici. * +* * +* Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +FormatMatchStatus dex_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) +{ + FormatMatchStatus result; /* Bilan à renvoyer */ + vmpa2t addr; /* Tête de lecture initiale */ + bool status; /* Bilan des accès mémoire */ + char magic[DEX_FILE_MAGIC_LEN]; /* Idenfiant standard */ + + + /* REMME */ + if (parent != NULL) return FMS_UNKNOWN; + + + init_vmpa(&addr, 0, VMPA_NO_VIRTUAL); + + status = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic); + + status &= (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0); + + if (status) + { + result = FMS_MATCHED; + *key = strdup(parent == NULL ? "dex" : "dexdbg"); + } + else + result = FMS_UNKNOWN; + + return result; + +} + + +/* Indique le type défini pour un format d'exécutable DEX. */ +G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des formats d'exécutables DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_class_init(GDexFormatClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GBinFormatClass *fmt; /* Version en format basique */ + GExeFormatClass *exe; /* Version en exécutable */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_format_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_format_finalize; + + fmt = G_BIN_FORMAT_CLASS(klass); + + fmt->get_endian = (format_get_endian_fc)g_dex_format_get_endianness; + + exe = G_EXE_FORMAT_CLASS(klass); + + exe->get_machine = (get_target_machine_fc)g_dex_format_get_target_machine; + exe->refine_portions = (refine_portions_fc)g_dex_format_refine_portions; + + exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa; + exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa; + + exe->get_range_by_name = (get_range_by_name_fc)g_dex_format_get_section_range_by_name; + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance à initialiser. * +* * +* Description : Initialise une instance de format d'exécutable DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_init(GDexFormat *format) +{ + GBinFormat *bin_format; /* Format parent à compléter #1*/ + + bin_format = G_BIN_FORMAT(format); + + bin_format->decompile = (format_decompile_fc)g_dex_format_decompile; + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_dispose(GDexFormat *format) +{ + G_OBJECT_CLASS(g_dex_format_parent_class)->dispose(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_finalize(GDexFormat *format) +{ + G_OBJECT_CLASS(g_dex_format_parent_class)->finalize(G_OBJECT(format)); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à parcourir. * +* parent = éventuel format exécutable déjà chargé. * + status = barre de statut à tenir informée. * +* * +* Description : Prend en charge un nouveau format Dex. * +* * +* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status) +{ + GDexFormat *result; /* Structure à retourner */ + GBinFormat *base; /* Version basique du format */ + GExeFormat *exe_format; /* Autre version du format */ + vmpa2t pos; /* Position de tête de lecture */ + wgroup_id_t gid; /* Identifiant pour les tâches */ + + result = g_object_new(G_TYPE_DEX_FORMAT, NULL); + + base = G_BIN_FORMAT(result); + exe_format = G_EXE_FORMAT(result); + + g_binary_format_set_content(base, content); + + init_vmpa(&pos, 0, VMPA_NO_VIRTUAL); + + if (!read_dex_header(result, &pos, &result->header)) + goto gdfn_error; + + + + /* TODO : vérifier que les *_id ne se chevauchent pas */ + + + gid = g_work_queue_define_work_group(get_work_queue()); + + if (!load_all_dex_types(result, gid, status)) + goto gdfn_error; + + if (!load_all_dex_fields(result, gid, status)) + goto gdfn_error; + + if (!load_all_dex_classes(result, gid, status)) + goto gdfn_error; + + preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status); + + if (!g_executable_format_complete_loading(exe_format, status)) + goto gdfn_error; + + return base; + + gdfn_error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Informe quant au boutisme utilisé. * +* * +* Retour : Indicateur de boutisme. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static SourceEndian g_dex_format_get_endianness(const GDexFormat *format) +{ + return SRE_LITTLE; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Indique le type d'architecture visée par le format. * +* * +* Retour : Identifiant de l'architecture ciblée par le format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_dex_format_get_target_machine(const GDexFormat *format) +{ + return "dalvik"; + +} + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* main = couche de portions principale à raffiner. * +* * +* Description : Etend la définition des portions au sein d'un binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_refine_portions(GDexFormat *format) +{ + GExeFormat *exe_format; /* Autre version du format */ + size_t max; /* Nombre d'itérations prévues */ + size_t i; /* Boucle de parcours */ + + exe_format = G_EXE_FORMAT(format); + + max = g_dex_format_count_classes(format); + + for (i = 0; i < max; i++) + g_dex_class_include_as_portion(format->classes[i], exe_format); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* name = nom de la section recherchée. * +* range = emplacement en mémoire à renseigner. [OUT] * +* * +* Description : Fournit l'emplacement d'une section donnée. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dex_format_get_section_range_by_name(const GDexFormat *format, const char *name, mrange_t *range) +{ + bool result; /* Bilan à retourner */ + + result = false; + + return result; + +} + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* addr = adresse de la routine à retrouver. * +* * +* 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_format_find_method_by_address(const GDexFormat *format, vmpa_t addr) +{ + + return NULL; + + +#if 0 + GDexMethod *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < format->classes_count && result == NULL; i++) + result = g_dex_class_find_method_by_address(format->classes[i], addr); + + return result; +#endif + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à mettre à jour. * +* * +* Description : Détermine tous les fichiers source indiqués. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#if 0 +static void g_dex_format_find_all_sources(GDexFormat *format) +{ + +#if 0 + + GBinFormat *bf; /* Instance parente */ + size_t i; /* Boucle de parcours #1 */ + const char *source; /* Fichier source trouvé */ + bool found; /* Présence dans la liste */ + size_t k; /* Boucle de parcours #2 */ + + bf = G_BIN_FORMAT(format); + + for (i = 0; i < format->classes_count; i++) + { + source = g_dex_class_get_source_file(format->classes[i], format); + if (source == NULL) continue; + + found = false; + + for (k = 0; k < bf->src_count && !found; k++) + found = (strcmp(source, bf->src_files[k]) == 0); + + if (!found) + { + bf->src_files = (const char **)realloc(bf->src_files, + ++bf->src_count * sizeof(const char **)); + bf->src_files[bf->src_count - 1] = source; + } + + } + +#endif + +} +#endif + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* buffer = tampon mis à disposition pour la sortie. * +* filename = nom du fichier source à cibler. * +* * +* Description : Procède à la décompilation complète du format. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_format_decompile(const GDexFormat *format, void/*GCodeBuffer*/ *buffer, const char *filename) +{ + +#if 0 + + GLangOutput *lang; /* Langage de sortie */ + size_t i; /* Boucle de parcours */ + const char *source; /* Fichier source trouvé */ + + lang = g_java_output_new(); + + for (i = 0; i < format->classes_count; i++) + { + source = g_dex_class_get_source_file(format->classes[i], format); + if (source == NULL || strcmp(source, filename) != 0) continue; + + g_dex_class_decompile(format->classes[i], lang, buffer, format); + + + +#if 0 + GDataType *get_type_from_dex_pool(const GDexFormat *format, uint16_t index) + + + Décrit le type fourni sous forme de caractères. * +* * +* Retour : Chaîne à libérer de la mémoire après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *_g_data_type_to_string(const GDataType *type, bool simple) + +#endif + + } + + +#endif + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* * +* Description : Présente l'en-tête DEX du format chargé. * +* * +* Retour : Pointeur vers la description principale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const dex_header *g_dex_format_get_header(const GDexFormat *format) +{ + return &format->header; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* * +* Description : Dénombre le nombre de classes trouvées. * +* * +* Retour : Quantité de classes présentes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_dex_format_count_classes(const GDexFormat *format) +{ + return format->header.class_defs_size; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* index = indice de la classe visée. * +* * +* Description : Fournit une classe du format chargée en mémoire. * +* * +* Retour : Instance représentant une classe chargée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDexClass *g_dex_format_get_class(const GDexFormat *format, size_t index) +{ + /* TODO : ref() */ + + return format->classes[index]; + +} + + + + + |