summaryrefslogtreecommitdiff
path: root/src/analysis/disass/disassembler.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-04-21 22:00:00 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-04-21 22:00:00 (GMT)
commit8eb95d316f7b6fbad0ff798abfe7f70f89e812d2 (patch)
tree4f310c7ffdb94d48fff236e63c7e6f0ed9f1dee1 /src/analysis/disass/disassembler.c
parent315146a49b5570294ca20beca720c4e3f74a86bd (diff)
Improved the way file formats are detected and loaded.
Diffstat (limited to 'src/analysis/disass/disassembler.c')
-rw-r--r--src/analysis/disass/disassembler.c534
1 files changed, 127 insertions, 407 deletions
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 6c63b0b..dded65b 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -33,13 +33,10 @@
#include "fetch.h"
-#include "output.h"
-
#include "instructions.h"
+#include "output.h"
#include "routines.h"
#include "../../core/global.h"
-#include "../../format/format.h"
-#include "../../glibext/delayed-int.h"
#include "../../glibext/generators/prologue.h"
#include "../../plugins/pglist.h"
@@ -49,190 +46,18 @@
-/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
-
-
-/* Ensembles binaires à désassembler (instance) */
-struct _GDelayedDisassembly
-{
- GDelayedWork parent; /* A laisser en premier */
-
- GLoadedBinary *binary; /* Destinataire final */
- GExeFormat *format; /* Format du binaire représenté*/
- GCodingLanguage *lang; /* Traduction en ASM préférée */
-
- GBufferCache *cache; /* Tampon pour le rendu */
-
-};
-
-/* Ensembles binaires à désassembler (classe) */
-struct _GDelayedDisassemblyClass
-{
- GDelayedWorkClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des tâches de désassemblage différé. */
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *);
-
-/* Initialise une tâche de désassemblage différé. */
-static void g_delayed_disassembly_init(GDelayedDisassembly *);
-
-/* Supprime toutes les références externes. */
-static void g_delayed_disassembly_dispose(GDelayedDisassembly *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_delayed_disassembly_finalize(GDelayedDisassembly *);
-
-/* Crée une tâche de désassemblage différé. */
-static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GBufferCache *);
-
/* Opère sur toutes les instructions. */
static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *);
/* Opère sur toutes les routines. */
static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GBinFormat *);
-/* Assure le désassemblage en différé. */
-static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkStatusStack *);
-
-
-
-/* -------------------------- GESTION GLOBALE DE PROCEDURE -------------------------- */
-
-
-/* Construit la description d'introduction du désassemblage. */
-static void build_disass_prologue(GBufferCache *, const GBinFormat *, const GCodingLanguage *, const char *, const char *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* DESASSEMBLAGE DE BINAIRE DIFFERE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les tâches de désassemblage différé. */
-G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des tâches de désassemblage différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GDelayedWorkClass *work; /* Version en classe parente */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_disassembly_dispose;
- object->finalize = (GObjectFinalizeFunc)g_delayed_disassembly_finalize;
-
- work = G_DELAYED_WORK_CLASS(klass);
-
- work->run = (run_task_fc)g_delayed_disassembly_process;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : disass = instance à initialiser. *
-* *
-* Description : Initialise une tâche de désassemblage différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_disassembly_init(GDelayedDisassembly *disass)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : disass = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_disassembly_dispose(GDelayedDisassembly *disass)
-{
- g_object_unref(G_OBJECT(disass->format));
- g_object_unref(G_OBJECT(disass->lang));
-
- G_OBJECT_CLASS(g_delayed_disassembly_parent_class)->dispose(G_OBJECT(disass));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : disass = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+/* Réalise un désassemblage effectif. */
+static void compute_disassembly(GLoadedBinary *, GProcContext *, wgroup_id_t, GtkStatusStack *);
-static void g_delayed_disassembly_finalize(GDelayedDisassembly *disass)
-{
- G_OBJECT_CLASS(g_delayed_disassembly_parent_class)->finalize(G_OBJECT(disass));
+/* Imprime le résultat d'un désassemblage. */
+static void output_disassembly(GLoadedBinary *, GProcContext *, GtkStatusStack *, GBufferCache **);
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = binaire chargé en attente des résultats. *
-* format = format du binaire représenté. *
-* buffer = tampon de sortie pour les instructions. *
-* *
-* Description : Crée une tâche de désassemblage différé. *
-* *
-* Retour : Tâche créée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GBufferCache *cache)
-{
- GDelayedDisassembly *result; /* Tâche à retourner */
-
- result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL);
-
- result->binary = binary;
- result->format = g_loaded_binary_get_format(binary);
- result->lang = g_asm_language_new();
-
- result->cache = cache;
-
- return result;
-
-}
/******************************************************************************
@@ -374,10 +199,12 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
/******************************************************************************
* *
-* Paramètres : disass = analyse à mener. *
-* status = barre de statut à tenir informée. *
+* Paramètres : binary = représentation de binaire chargé. *
+* context = contexte de désassemblage utilisé. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
* *
-* Description : Assure le désassemblage en différé. *
+* Description : Réalise un désassemblage effectif. *
* *
* Retour : - *
* *
@@ -385,249 +212,100 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const
* *
******************************************************************************/
-static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatusStack *status)
+static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wgroup_id_t gid, GtkStatusStack *status)
{
- wgroup_id_t gid; /* Identifiant pour les tâches */
-
- //GBinFormat *format; /* Format du fichier binaire */
GArchProcessor *proc; /* Architecture du binaire */
- GProcContext *ctx; /* Contexte de suivi dédié */
-
- //size_t i; /* Boucle de parcours */
-
+ GExeFormat *format; /* Format du binaire représenté*/
GArchInstruction **instrs; /* Instructions résultantes */
size_t count; /* Quantité de ces instructions*/
+ /**
+ * Récupération des objets utiles.
+ */
+ proc = g_loaded_binary_get_processor(binary);
- proc = g_loaded_binary_get_processor(disass->binary);
- ctx = g_arch_processor_get_context(proc);
-
-
-
- gid = g_work_queue_define_work_group(get_work_queue());
-
-
-
-
-
-
- /* Première étape */
-
- //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true);
-
-
-
- process_disassembly_event(PGA_DISASSEMBLY_STARTED, disass->binary);
-
-
+ format = g_loaded_binary_get_format(binary);
- instrs = disassemble_binary_content(disass->binary, ctx, gid, status, &count);
+ /**
+ * Première étape : collecte des instructions.
+ */
+ instrs = disassemble_binary_content(binary, context, gid, status, &count);
g_arch_processor_set_instructions(proc, instrs, count);
+ process_disassembly_event(PGA_DISASSEMBLY_RAW, binary);
- // plugins //////////////////////////
- process_disassembly_event(PGA_DISASSEMBLY_RAW, disass->binary);
-
-
+ /**
+ * Seconde étape : liaisons des instructions.
+ */
process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."),
g_instructions_study_do_link_operation,
- proc, ctx, disass->format);
-
-
- // plugins //////////////////////////
- process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, disass->binary);
-
-
-
- //gtk_extended_status_bar_remove(statusbar, id);
-
+ proc, context, format);
- //run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true);
+ process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, binary);
+ /**
+ * Troisième étape : exécution d'éventuels post-traitements.
+ */
process_all_instructions(gid, status, _("Calling 'post' hook on all instructions..."),
g_instructions_study_do_post_operation,
- proc, ctx, disass->format);
-
-
-
- // plugins //////////////////////////
- process_disassembly_event(PGA_DISASSEMBLY_HOOKED_POST, disass->binary);
-
+ proc, context, format);
+ process_disassembly_event(PGA_DISASSEMBLY_HOOKED_POST, binary);
/**
- * TODO : établir les couvertures de fonctions,
- * pour être en mesure de disposer de résolution de type XXX+yyy lors
- * de l'établissement des liens.
+ * Quatrième étape : établissement des couvertures de routines restantes.
*/
-
- /* Seconde étape */
-
-
-
-
process_all_routines(gid, status,
_("Finding remaining limits..."),
- g_routines_study_compute_limits, proc, G_BIN_FORMAT(disass->format));
-
-
-
- // plugins //////////////////////////
- process_disassembly_event(PGA_DISASSEMBLY_LIMITED, disass->binary);
+ g_routines_study_compute_limits, proc, G_BIN_FORMAT(format));
+ process_disassembly_event(PGA_DISASSEMBLY_LIMITED, binary);
-
- /* Troisième étape */
+ /**
+ * Cinquième étape : liaisons entre instructions.
+ */
process_all_instructions(gid, status, _("Establishing links betweek all instructions..."),
g_instructions_study_establish_links,
- proc, ctx, disass->format);
-
-
-
- // plugins //////////////////////////
- process_disassembly_event(PGA_DISASSEMBLY_LINKED, disass->binary);
-
-
-
-
-
- /* Quatrième étape */
-
- // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Detecting loops..."), true);
-
- // -- old -- detect_loops_in_code(proc, routines, routines_count, statusbar, 0/*id*/);
-
- // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
- ///
+ proc, context, format);
- // plugins //////////////////////////
- // -- old -- process_disassembly_event(PGA_DISASSEMBLY_LOOPS, disass->binary);
+ process_disassembly_event(PGA_DISASSEMBLY_LINKED, binary);
+ /**
+ * Sixième étape : regroupement en blocs basiques.
+ */
-
-
-
-
-
-
-
-
- //////////////////////////////////////
-
-
- // Control-flow analysis...
-
-#if 1
process_all_routines(gid, status,
_("Control-flow analysis for routines..."),
- g_routines_study_handle_blocks, proc, G_BIN_FORMAT(disass->format));
-#endif
-
-
-
-
- /* Cinquième étape */
-
- // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Grouping routines instructions..."), true);
-
- //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
+ g_routines_study_handle_blocks, proc, G_BIN_FORMAT(format));
- // -- old -- group_routines_instructions(proc, routines, routines_count, statusbar, 0/*id*/);
+ process_disassembly_event(PGA_DISASSEMBLY_GROUPED, binary);
- // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
- //run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true);
-
-
- // -- old -- process_disassembly_event(PGA_DISASSEMBLY_GROUPED, disass->binary);
-
-
-
-
-
- /* Sixième étape */
-
- // -- old -- id = gtk_extended_status_bar_push(statusbar, _("Ranking each instructions block..."), true);
-
- //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
-
- // -- old -- rank_routines_blocks(routines, routines_count, statusbar, 0/*id*/);
-
- // -- old -- gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
- //run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true);
-
-
- // -- old -- process_disassembly_event(PGA_DISASSEMBLY_RANKED, disass->binary);
-
-
-
- /* Septième étape */
-
- //id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
-
-
-
-
- print_disassembled_instructions(disass->cache, disass->lang, disass->binary, G_PRELOAD_INFO(ctx), status);
-
-
-
-
- /* Rajout de tous les éléments mis en place automatiquement */
-
- void add_to_collection(GDbItem *item, GLoadedBinary *binary)
- {
- g_object_ref(G_OBJECT(item));
-
- g_loaded_binary_add_to_collection(binary, item);
-
- }
-
- g_proc_context_foreach_db_item(ctx, (GFunc)add_to_collection, disass->binary);
-
- /* Nettoyage final et sortie ! */
+ /**
+ * Nettoyage final et sortie !
+ */
- g_object_unref(G_OBJECT(ctx));
+ g_object_unref(G_OBJECT(format));
g_object_unref(G_OBJECT(proc));
- process_disassembly_event(PGA_DISASSEMBLY_ENDED, disass->binary);
-
-
-
- //gtk_extended_status_bar_remove(statusbar, 0/*id*/);
-
- //run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED, true);
-
-
-
}
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION GLOBALE DE PROCEDURE */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : cache = tampon de destination pour le texte. *
-* format = format associé au contenu représenté. *
-* lang = trauducteur pour l'impression finale. *
-* filename = nom du fichier ciblé à décompiler. *
-* checksum = empreinte identifiant le binaire chargé. *
+* Paramètres : binary = représentation de binaire chargé. *
+* context = contexte de désassemblage utilisé. *
+* status = barre de statut à tenir informée. *
+* cache = tampon de code mis en place. [OUT] *
* *
-* Description : Construit la description d'introduction du désassemblage. *
+* Description : Imprime le résultat d'un désassemblage. *
* *
* Retour : - *
* *
@@ -635,31 +313,82 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus
* *
******************************************************************************/
-static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format, const GCodingLanguage *lang, const char *filename, const char *checksum)
+static void output_disassembly(GLoadedBinary *binary, GProcContext *context, GtkStatusStack *status, GBufferCache **cache)
{
+ GBinFormat *format; /* Format associé au binaire */
+ GBinContent *content; /* Contenu bianire manipulé */
+ GCodingLanguage *lang; /* Langage de sortie préféré */
char **text; /* Contenu brute à imprimer */
+ const char *desc; /* Désignation du binaire */
+ const gchar *checksum; /* Identifiant de binaire */
GIntroGenerator *generator; /* Générateur constitué */
+ /**
+ * Initialisation des biens communs.
+ */
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+ content = g_binary_format_get_content(format);
+ lang = g_asm_language_new();
+
+ *cache = g_buffer_cache_new(content);
+
+ /**
+ * Impression du prologue.
+ */
+
text = calloc(4, sizeof(char *));
/* Introduction */
text[0] = strdup(_("Disassembly generated by Chrysalide"));
- text[1] = strdup(_("Chrysalide is free software - © 2008-2016 Cyrille Bagard"));
+ text[1] = strdup(_("Chrysalide is free software - © 2008-2018 Cyrille Bagard"));
/* Fichier */
- asprintf(&text[2], "%s%s", _("File: "), filename);
+ desc = g_binary_content_describe(content, true);
+
+ asprintf(&text[2], "%s%s", _("Source: "), desc);
/* Checksum SHA256 */
+ checksum = g_binary_content_get_checksum(content);
+
asprintf(&text[3], "%s%s", _("Sha256: "), checksum);
/* Intégration finale */
generator = g_intro_generator_new(format, lang, text, 4);
- g_buffer_cache_append(cache, G_LINE_GENERATOR(generator), BLF_NONE);
+ g_buffer_cache_append(*cache, G_LINE_GENERATOR(generator), BLF_NONE);
+
+ /**
+ * Impression des instructions désassemblées.
+ */
+
+ print_disassembled_instructions(*cache, lang, binary, G_PRELOAD_INFO(context), status);
+
+ /**
+ * Rajout de tous les éléments mis en place automatiquement.
+ */
+
+ void add_to_collection(GDbItem *item, gpointer unused)
+ {
+ g_object_ref(G_OBJECT(item));
+
+ g_loaded_binary_add_to_collection(binary, item);
+
+ }
+
+ g_proc_context_foreach_db_item(context, (GFunc)add_to_collection, NULL);
+
+ /**
+ * Nettoyage avant sortie.
+ */
+
+ g_object_unref(G_OBJECT(lang));
+ g_object_unref(G_OBJECT(content));
+ g_object_unref(G_OBJECT(format));
}
@@ -667,11 +396,9 @@ static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format,
/******************************************************************************
* *
* Paramètres : binary = représentation de binaire chargé. *
-* parts = parties binaires à désassembler. *
-* count = nombre de parties à traiter. *
-* instrs = liste des instructions chargées. [OUT] *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
* cache = tampon de code mis en place. [OUT] *
-* ack = fonction à appeler une fois l'opération terminée. *
* *
* Description : Procède au désassemblage d'un contenu binaire donné. *
* *
@@ -681,38 +408,31 @@ static void build_disass_prologue(GBufferCache *cache, const GBinFormat *format,
* *
******************************************************************************/
-void disassemble_binary(GLoadedBinary *binary, GBufferCache **cache, disassembly_ack_fc ack)
+void disassemble_binary(GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status, GBufferCache **cache)
{
- GBinFormat *format; /* Format associé au binaire */
- GBinContent *content; /* Contenu bianire manipulé */
- GCodingLanguage *lang; /* Langage de sortie préféré */
- const char *desc; /* Désignation du binaire */
- const gchar *checksum; /* Identifiant de binaire */
- GDelayedDisassembly *disass; /* Désassemblage à mener */
- GWorkQueue *queue; /* Gestionnaire de différés */
+ GArchProcessor *proc; /* Architecture du binaire */
+ GProcContext *context; /* Contexte de suivi dédié */
- format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
- content = g_binary_format_get_content(format);
+ /* Préparatifs */
- *cache = g_buffer_cache_new(content);
+ process_disassembly_event(PGA_DISASSEMBLY_STARTED, binary);
- lang = g_asm_language_new();
+ proc = g_loaded_binary_get_processor(binary);
- desc = g_binary_content_describe(content, true);
- checksum = g_binary_content_get_checksum(content);
+ context = g_arch_processor_get_context(proc);
- build_disass_prologue(*cache, format, lang, desc, checksum);
+ /* Lancement des opérations ! */
- g_object_unref(G_OBJECT(lang));
- g_object_unref(G_OBJECT(content));
- g_object_unref(G_OBJECT(format));
+ compute_disassembly(binary, context, gid, status);
- disass = g_delayed_disassembly_new(binary, *cache);
+ process_disassembly_event(PGA_DISASSEMBLY_ENDED, binary);
- if (ack != NULL)
- g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary);
+ output_disassembly(binary, context, status, cache);
- queue = get_work_queue();
- g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass), DEFAULT_WORK_GROUP);
+ /* Nettoyage final et sortie ! */
+
+ g_object_unref(G_OBJECT(context));
+
+ g_object_unref(G_OBJECT(proc));
}