/* Chrysalide - Outil d'analyse de fichiers binaires * format.c - support des différents formats binaires * * Copyright (C) 2009-2013 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "format.h" #include #include "format-int.h" #include "dex/dex.h" #include "dwarf/dwarf.h" #include "elf/elf.h" #include "java/java.h" #include "pe/pe.h" #include "../arch/processor.h" #include "../decomp/expr/block.h" #include "../gui/panels/log.h" #include "../plugins/pglist.h" /* Initialise la classe des formats binaires génériques. */ static void g_binary_format_class_init(GBinFormatClass *); /* Initialise une instance de format binaire générique. */ static void g_binary_format_init(GBinFormat *); /* Indique le type défini pour un format binaire générique. */ G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des formats binaires génériques. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_format_class_init(GBinFormatClass *klass) { } /****************************************************************************** * * * Paramètres : format = instance à initialiser. * * * * Description : Initialise une instance de format binaire générique. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_binary_format_init(GBinFormat *format) { } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * content = contenu binaire à parcourir. * * length = taille du contenu fourni. * * * * Description : Définit le contenu binaire à analyser. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_format_set_content(GBinFormat *format, GBinContent *content) { format->content = g_binary_content_get(content, &format->length); } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * length = taille du contenu à fournir. [OUT] * * * * Description : Fournit une référence vers le contenu binaire analysé. * * * * Retour : Adresse du tampon contenant le contenu du binaire. * * * * Remarques : - * * * ******************************************************************************/ const bin_t *g_binary_format_get_content(const GBinFormat *format, off_t *length) { if (length != NULL) *length = format->length; return format->content; } /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * * ctx = contexte de désassemblage à préparer. * * * * Description : Fournit un contexte initialisé pour un désassemblage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_format_setup_disassembling_context(const GBinFormat *format, GProcContext *ctx) { size_t i; /* Boucle de parcours */ for (i = 0; i < format->ep_count; i++) g_proc_context_push_drop_point(ctx, format->entry_points[i]); } /****************************************************************************** * * * Paramètres : format = informations chargées à compléter. * * symbol = symbole à ajouter à la liste. * * * * Description : Ajoute un symbole à la collection du format binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) { format->symbols = (GBinSymbol **)realloc(format->symbols, ++format->symbols_count * sizeof(GBinSymbol *)); format->symbols[format->symbols_count - 1] = symbol; qsort(format->symbols, format->symbols_count, sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp); } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * count = taille du tableau créé. [OUT] * * * * Description : Fournit la liste de tous les symboles détectés. * * * * Retour : Tableau créé ou NULL si aucun symbole trouvé. * * * * Remarques : - * * * ******************************************************************************/ GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count) { *count = format->symbols_count; return format->symbols; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * addr = adresse à cibler lors des recherches. * * symbol = éventuel symbole trouvé à déréfenrencer. [OUT] * * * * Description : Recherche le symbole correspondant à une adresse. * * * * Retour : true si l'opération a été un succès, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool g_binary_format_find_symbol_at(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ const mrange_t *range; /* Espace mémoire parcouru */ result = false; for (i = 0; i < format->symbols_count && !result; i++) { range = g_binary_symbol_get_range(format->symbols[i]); if (cmp_vmpa(get_mrange_addr(range), addr) == 0) { *symbol = format->symbols[i]; g_object_ref(G_OBJECT(*symbol)); result = true; } } return result; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * addr = adresse à cibler lors des recherches. * * symbol = éventuel symbole trouvé à déréfenrencer. [OUT] * * diff = décallage entre l'adresse et le symbole. [OUT] * * * * Description : Recherche le symbole correspondant à une adresse. * * * * Retour : true si l'opération a été un succès, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool g_binary_format_resolve_symbol(const GBinFormat *format, const vmpa2t *addr, GBinSymbol **symbol, phys_t *diff) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ const mrange_t *range; /* Espace mémoire parcouru */ result = false; //for (i = 0; i < format->symbols_count && !result; i++) for (i = format->symbols_count; i > 0 && !result; i--) { range = g_binary_symbol_get_range(format->symbols[i - 1]); if (mrange_contains_addr(range, addr)) { *symbol = format->symbols[i - 1]; g_object_ref(G_OBJECT(*symbol)); *diff = compute_vmpa_diff(get_mrange_addr(range), addr); result = true; } } return result; } /****************************************************************************** * * * Paramètres : format = informations chargées à compléter. * * routine = routine à ajouter à la liste. * * * * Description : Ajoute une routine à la collection du format binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_binary_format_add_routine(GBinFormat *format, GBinRoutine *routine) { format->routines = (GBinRoutine **)realloc(format->routines, ++format->routines_count * sizeof(GBinRoutine *)); format->routines[format->routines_count - 1] = routine; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * count = taille du tableau créé. [OUT] * * * * Description : Fournit le prototype de toutes les routines détectées. * * * * Retour : Tableau créé ou NULL si aucun symbole de routine trouvé. * * * * Remarques : - * * * ******************************************************************************/ GBinRoutine **g_binary_format_get_routines(const GBinFormat *format, size_t *count) { *count = format->routines_count; return format->routines; } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * count = taille de la liste retournée. [OUT] * * defsrc = fichier de code principal. [OUT] * * * * Description : Fournit la liste des fichiers source détectés. * * * * Retour : Liste de noms de fichier ou NULL si aucun. * * * * Remarques : - * * * ******************************************************************************/ const char * const *g_binary_format_get_source_files(const GBinFormat *format, size_t *count, size_t *defsrc) { *count = format->src_count; *defsrc = format->def_source; return format->src_files; } /****************************************************************************** * * * 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 : - * * * ******************************************************************************/ void g_binary_format_decompile(const GBinFormat *format, GCodeBuffer *buffer, const char *filename) { GBinRoutine **routines; size_t count; size_t i; GDecInstruction *instr; if (format->decompile != NULL) format->decompile(format, buffer, filename); routines = g_binary_format_get_routines(format, &count); for (i = 0; i < count; i++) { //printf(" -- %s --\n", g_binary_routine_get_name(routines[i])); //if (strcmp("cryptself", g_binary_routine_get_name(routines[i])) == 0) { instr = g_binary_routine_get_decomp_instructions(routines[i]); if (instr == NULL) continue; //g_dec_instruction_print(instr, buffer, NULL, g_java_output_new()); } } } /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * label = étiquette du symbole si trouvé. [OUT] * * address = adresse à cibler, puis décallage final. [OUT] * * * * Description : Recherche une position dans une routine selon une adresse. * * * * Retour : true si l'opération a été un succès, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool g_binary_format_resolve_relative_routine(const GBinFormat *format, const char **label, vmpa_t *address) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ vmpa_t addr; /* Adresse de symbole */ off_t size; /* Taille du symole */ result = false; for (i = 0; i < format->routines_count && !result; i++) { addr = g_binary_routine_get_address(format->routines[i]); size = g_binary_routine_get_size(format->routines[i]); if (addr <= *address && *address < (addr + size)) { *label = g_binary_routine_get_long_name(format->routines[i]); *address -= addr; result = true; } } return result; }