summaryrefslogtreecommitdiff
path: root/src/analysis/project.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/project.c')
-rw-r--r--src/analysis/project.c530
1 files changed, 514 insertions, 16 deletions
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 5bb028f..db00f09 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -29,14 +29,20 @@
#include <string.h>
+#include <i18n.h>
+
+
#include "binaries/file.h"
#include "../common/xml.h"
+#include "../core/formats.h"
#include "../core/params.h"
#include "../glibext/signal.h"
#include "../gtkext/easygtk.h"
+#include "../glibext/delayed-int.h"
#include "../gtkext/gtkblockview.h"
#include "../gtkext/gtkgraphview.h"
#include "../gtkext/gtksourceview.h"
+#include "../gui/panels/log.h"
#include "../gui/panels/panel.h"
@@ -44,6 +50,14 @@
/* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
+/* Conservation d'un contenu chargé */
+typedef struct _loaded_content
+{
+ GBinContent *content; /* Contenu binaire en place */
+ ProjectContentState state; /* Renseigne le type de contenu*/
+
+} loaded_content;
+
/* Conservation d'un binaire chargé */
typedef struct _loaded_binary
{
@@ -65,9 +79,13 @@ struct _GStudyProject
char *filename; /* Lieu d'enregistrement */
+ loaded_content *contents; /* Contenus binaires chargés */
+ size_t contents_count; /* Nombre de ces contenus */
+ GMutex cnt_mutex; /* Modification de la liste */
+
loaded_binary **binaries; /* Fichiers binaires associés */
size_t binaries_count; /* Nombre de ces fichiers */
- GMutex mutex; /* Modification de la liste */
+ GMutex bin_mutex; /* Modification de la liste */
};
@@ -91,6 +109,49 @@ static void g_study_project_hide(const GStudyProject *);
+
+
+/* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
+
+
+/* Ensembles binaires à désassembler (instance) */
+struct _GDelayedStudy
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ GStudyProject *project; /* Projet de rattachement */
+ GBinContent *content; /* Contenu binaire à traiter */
+ ProjectContentState state; /* Renseigne le type de contenu*/
+
+ bool only_preload; /* Enregistrement seulement ? */
+
+};
+
+/* Ensembles binaires à désassembler (classe) */
+struct _GDelayedStudyClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des intégrations de binaires à étudier. */
+static void g_delayed_study_class_init(GDelayedStudyClass *);
+
+/* Initialise une intégration de binaire à étudier. */
+static void g_delayed_study_init(GDelayedStudy *);
+
+/* Supprime toutes les références externes. */
+static void g_delayed_study_dispose(GDelayedStudy *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_delayed_study_finalize(GDelayedStudy *);
+
+/* Prépare une intégration de binaire au projet courant. */
+static void g_delayed_study_process(GDelayedStudy *, GtkExtStatusBar *);
+
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION D'UN PROJET INTERNE */
/* ---------------------------------------------------------------------------------- */
@@ -132,7 +193,9 @@ static void g_study_project_class_init(GStudyProjectClass *klass)
static void g_study_project_init(GStudyProject *project)
{
- g_mutex_init(&project->mutex);
+ g_mutex_init(&project->cnt_mutex);
+
+ g_mutex_init(&project->bin_mutex);
}
@@ -180,11 +243,17 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename)
GStudyProject *result; /* Adresse à retourner */
xmlDocPtr xdoc; /* Structure XML chargée */
xmlXPathContextPtr context; /* Contexte pour les XPath */
+ unsigned int root_contents; /* Quantité de contenus majeurs*/
+ GAsyncQueue *sema; /* Sémaphore taisant son nom */
xmlXPathObjectPtr xobject; /* Cible d'une recherche */
unsigned int i; /* Boucle de parcours */
size_t access_len; /* Taille d'un chemin interne */
char *access; /* Chemin pour une sous-config.*/
- GLoadedBinary *binary; /* Représentation à intégrer */
+ GBinContent *content; /* Contenu binaire retrouvé */
+ long state; /* Etat de ce contenu binaire */
+ bool status; /* Bilan d'une lecture */
+ GDelayedStudy *dstudy; /* Etude complémentaire à mener*/
+ GLoadedBinary *binary; /* Représentation à intégrer */
if (!open_xml_file(filename, &xdoc, &context)) return NULL;
@@ -192,19 +261,78 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename)
result->filename = strdup(filename);
- /* Chargement des éléments binaires attachés */
+ /* Préparations aux traitements parallèles */
+
+ root_contents = 0;
+
+ sema = g_async_queue_new();
+
+ void ack_content_processing(GDelayedStudy *dstudy, GAsyncQueue *aqueue)
+ {
+ g_async_queue_push(aqueue, GINT_TO_POINTER(1));
+ }
+
+ /* Chargement des contenus binaires attachés */
+
+ xobject = get_node_xpath_object(context, "/ChrysalideProject/Contents/Content");
+
+ for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
+ {
+ access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+
+ access = calloc(access_len, sizeof(char));
+ snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%u]", i + 1);
+
+ content = g_binary_content_new_from_xml(context, access);
+ status = get_node_prop_long_value(context, access, "state", &state);
+
+ free(access);
+
+ if (!status)
+ {
+ log_variadic_message(LMT_PROCESS, _("bad state for content '%s' ; skipping..."),
+ g_binary_content_describe(content, true));
+ continue;
+ }
+
+ /* Le contenu peut être un conteneur ? */
+ if (state == PCS_ROOT)
+ {
+ dstudy = g_delayed_study_new(result, content, state);
+ g_signal_connect(dstudy, "work-completed", G_CALLBACK(ack_content_processing), sema);
+
+ g_delayed_study_preload_only(dstudy);
+
+ root_contents++;
+
+ study_new_content(dstudy);
+
+ }
+
+ }
+
+ if(xobject != NULL)
+ xmlXPathFreeObject(xobject);
+
+ /* Attente pour la réception de contenus supplémentaires éventuels */
+
+ for (i = 0; i < root_contents; i++)
+ g_async_queue_pop(sema);
+
+ g_async_queue_unref(sema);
- xobject = get_node_xpath_object(context, "/OpenIDAProject/Binaries/Binary");
+ /* Chargement des binaires analysés */
+
+ xobject = get_node_xpath_object(context, "/ChrysalideProject/Binaries/Binary");
for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++)
{
- access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=")
- + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1;
+ access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
access = calloc(access_len, sizeof(char));
- snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%u]", i + 1);
+ snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%u]", i + 1);
- binary = g_loaded_binary_new_from_xml(context, access);
+ binary = g_loaded_binary_new_from_xml(context, access, result);
free(access);
@@ -254,17 +382,36 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
result = create_new_xml_file(&xdoc, &context);
- result &= (ensure_node_exist(xdoc, context, "/OpenIDAProject") != NULL);
+ result &= (ensure_node_exist(xdoc, context, "/ChrysalideProject") != NULL);
+
+ /* Enregistrement des contenus binaires attachés */
- /* Enregistrement des éléments binaires attachés */
+ for (i = 0; i < project->contents_count && result; i++)
+ {
+ if (!project->contents[i].state == PCS_INTERNAL) continue;
+
+ access_len = strlen("/ChrysalideProject/Contents/Content[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
+
+ access = calloc(access_len, sizeof(char));
+ snprintf(access, access_len, "/ChrysalideProject/Contents/Content[position()=%zu]", i + 1);
+
+ result = g_binary_content_save(project->contents[i].content, xdoc, context, access);
+
+ if (result)
+ result = add_long_attribute_to_node(xdoc, context, access, "state", project->contents[i].state);
+
+ free(access);
+
+ }
+
+ /* Enregistrement des binaires analysés */
for (i = 0; i < project->binaries_count && result; i++)
{
- access_len = strlen("/OpenIDAProject/Binaries/Binary[position()=")
- + strlen("4294967295" /* UINT_MAX */) + strlen("]") + 1;
+ access_len = strlen("/ChrysalideProject/Binaries/Binary[position()=") + SIZE_T_MAXLEN + strlen("]") + 1;
access = calloc(access_len, sizeof(char));
- snprintf(access, access_len, "/OpenIDAProject/Binaries/Binary[position()=%zu]", i + 1);
+ snprintf(access, access_len, "/ChrysalideProject/Binaries/Binary[position()=%zu]", i + 1);
result = g_loaded_binary_save(project->binaries[i]->binary, xdoc, context, access);
@@ -311,6 +458,88 @@ const char *g_study_project_get_filename(const GStudyProject *project)
/******************************************************************************
* *
+* Paramètres : project = projet dont le contenu est à compléter. *
+* content = contenu binaire à mémoriser pour le projet. *
+* state = état du contenu à conserver. *
+* *
+* Description : Assure l'intégration d'un contenu binaire dans un projet. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_study_project_add_binary_content(GStudyProject *project, GBinContent *content, ProjectContentState state)
+{
+ loaded_content *new; /* Nouveau contenu à définir */
+
+ g_mutex_lock(&project->cnt_mutex);
+
+ project->contents = (loaded_content *)realloc(project->contents,
+ ++project->contents_count * sizeof(loaded_content));
+
+ new = &project->contents[project->contents_count - 1];
+
+ g_object_ref(G_OBJECT(content));
+
+ new->content = content;
+ new->state = state;
+
+ g_mutex_unlock(&project->cnt_mutex);
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : project = projet dont le contenu est à compléter. *
+* hash = empreinte du contenu à retrouver. *
+* *
+* Description : Recherche un contenu binaire du projet selon son empreinte. *
+* *
+* Retour : Contenu avec propriété transférée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project, const char *hash)
+{
+ GBinContent *result; /* Trouvaille à retourner */
+ size_t i; /* Boucle de parcours */
+ GBinContent *iter; /* Contenu binaire analysé */
+ const gchar *other; /* Autre empreinte à comparer */
+
+ result = NULL;
+
+ g_mutex_lock(&project->cnt_mutex);
+
+ for (i = 0; i < project->contents_count && result == NULL; i++)
+ {
+ iter = project->contents[i].content;
+ other = g_binary_content_get_cheksum(iter);
+
+ if (strcmp(hash, other) == 0)
+ {
+ g_object_ref(G_OBJECT(iter));
+ result = iter;
+ }
+
+ }
+
+ g_mutex_unlock(&project->cnt_mutex);
+
+ return result;
+
+}
+
+
+
+
+/******************************************************************************
+* *
* Paramètres : binary = élément binaire tout juste désassemblé. *
* project = projet dont le contenu est à compléter. *
* *
@@ -431,7 +660,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
/* Enregistrement dans le projet */
- g_mutex_lock(&project->mutex);
+ g_mutex_lock(&project->bin_mutex);
project->binaries = (loaded_binary **)realloc(project->binaries,
++project->binaries_count * sizeof(loaded_binary *));
@@ -440,7 +669,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
project->binaries[result] = loaded;
- g_mutex_unlock(&project->mutex);
+ g_mutex_unlock(&project->bin_mutex);
update_project_area(project);
@@ -714,3 +943,272 @@ void push_project_into_recent_list(const GStudyProject *project)
g_generic_config_set_value(get_main_configuration(), MPK_LAST_PROJECT, project->filename);
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* AMORCE POUR CHARGEMENT DE CONTENUS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de préparations d'étude. */
+G_DEFINE_TYPE(GDelayedStudy, g_delayed_study, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des intégrations de binaires à étudier. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_study_class_init(GDelayedStudyClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_study_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_delayed_study_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dstudy = instance à initialiser. *
+* *
+* Description : Initialise une intégration de binaire à étudier. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_study_init(GDelayedStudy *dstudy)
+{
+ G_DELAYED_WORK(dstudy)->run = (run_task_fc)g_delayed_study_process;
+
+ dstudy->only_preload = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_study_dispose(GDelayedStudy *dstudy)
+{
+ g_object_unref(G_OBJECT(dstudy->project));
+ g_object_unref(G_OBJECT(dstudy->content));
+
+ G_OBJECT_CLASS(g_delayed_study_parent_class)->dispose(G_OBJECT(dstudy));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_study_finalize(GDelayedStudy *dstudy)
+{
+ G_OBJECT_CLASS(g_delayed_study_parent_class)->finalize(G_OBJECT(dstudy));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : project = projet dont le contenu est à compléter. *
+* content = contenu binaire chargé à analyser. *
+* state = état du contenu à conserver. *
+* *
+* Description : Crée une tâche d'intégration de contenu binaire. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : L'appelant perd la propriété du contenu. *
+* *
+******************************************************************************/
+
+GDelayedStudy *g_delayed_study_new(GStudyProject *project, GBinContent *content, ProjectContentState state)
+{
+ GDelayedStudy *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_DELAYED_STUDY, NULL);
+
+ g_object_ref(G_OBJECT(project));
+ result->project = project;
+
+ g_object_ref(G_OBJECT(content));
+ result->content = content;
+
+ result->state = state;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dstudy = intégration à mener. *
+* statusbar = barre de statut à tenir informée. *
+* *
+* Description : Prépare une intégration de binaire au projet courant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_study_process(GDelayedStudy *dstudy, GtkExtStatusBar *statusbar)
+{
+ FormatMatchStatus status; /* Statut d'une reconnaissance */
+ char *target; /* Sous-traitance requise */
+ GLoadedBinary *binary; /* Représentation chargée */
+
+ status = find_matching_format(dstudy->content, NULL, &target);
+
+ switch (status)
+ {
+ case FMS_MATCHED:
+
+ if (dstudy->only_preload)
+ g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+
+ else
+ {
+ binary = g_loaded_binary_new(dstudy->content);
+
+ if (binary != NULL)
+ {
+ g_study_project_add_binary_content(dstudy->project, dstudy->content, dstudy->state);
+
+ g_signal_connect_to_main(binary, "disassembly-done",
+ G_CALLBACK(g_study_project_add_loaded_binary),
+ dstudy->project, g_cclosure_marshal_VOID__VOID);
+
+ g_loaded_binary_analyse(binary);
+
+ }
+
+ }
+
+ break;
+
+ case FMS_FORWARDED:
+ /**
+ * L'émetteur de ce type de réponse a pour charge de
+ * reprogrammer lui même l'analyse de nouveaux contenus.
+ */
+ log_variadic_message(LMT_PROCESS, _("binary '%s' contains other binaries..."),
+ g_binary_content_describe(dstudy->content, true));
+
+ if (dstudy->state == PCS_ROOT)
+ g_study_project_add_binary_content(dstudy->project, dstudy->content, PCS_ROOT);
+
+ break;
+
+ default:
+ /**
+ * Les jeux sont faits pour le contenu binaire courant.
+ */
+ log_variadic_message(LMT_PROCESS, _("Unknown binary format for '%s'..."),
+ g_binary_content_describe(dstudy->content, true));
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dstudy = tâche d'analyse de contenu pour projet à mener. *
+* *
+* Description : Limite l'étude et l'intégration d'un contenu binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_delayed_study_preload_only(GDelayedStudy *dstudy)
+{
+ dstudy->only_preload = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire chargé à analyser. *
+* state = état du contenu à conserver. *
+* *
+* Description : Programme l'étude et l'intégration d'un contenu binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void qck_study_new_content(GBinContent *content, ProjectContentState state)
+{
+ GDelayedStudy *dstudy; /* Etude à conduire */
+
+ dstudy = g_delayed_study_new(get_current_project(), content, state);
+
+ study_new_content(dstudy);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu binaire chargé à analyser. *
+* state = état du contenu à conserver. *
+* *
+* Description : Programme l'étude et l'intégration d'un contenu binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void study_new_content(GDelayedStudy *dstudy)
+{
+ GWorkQueue *queue; /* Gestionnaire de différés */
+
+ queue = get_work_queue();
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(dstudy));
+
+}