From 5dcc4df15a8d84b214bb3f6f0fcfe30f21cb0972 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 28 May 2020 09:14:16 +0200 Subject: Saved the first steps for a new loading process. --- plugins/dex/format.c | 14 +- plugins/elf/format.c | 9 +- src/gui/dialogs/Makefile.am | 2 + src/gui/dialogs/gresource.xml | 1 + src/gui/dialogs/loading.c | 517 ++++++++++++++++++++++++++++++++++++++++++ src/gui/dialogs/loading.h | 44 ++++ src/gui/dialogs/loading.ui | 320 ++++++++++++++++++++++++++ src/gui/editor.c | 15 +- 8 files changed, 908 insertions(+), 14 deletions(-) create mode 100644 src/gui/dialogs/loading.c create mode 100644 src/gui/dialogs/loading.h create mode 100644 src/gui/dialogs/loading.ui diff --git a/plugins/dex/format.c b/plugins/dex/format.c index 84ddb4d..ccf21a8 100644 --- a/plugins/dex/format.c +++ b/plugins/dex/format.c @@ -250,6 +250,7 @@ static void g_dex_format_finalize(GDexFormat *format) GExeFormat *g_dex_format_new(GBinContent *content) { GDexFormat *result; /* Structure à retourner */ + vmpa2t pos; /* Position de tête de lecture */ if (!check_dex_format(content)) return NULL; @@ -260,6 +261,14 @@ GExeFormat *g_dex_format_new(GBinContent *content) result->pool = g_dex_pool_new(result); + init_vmpa(&pos, 0, VMPA_NO_VIRTUAL); + + if (!read_dex_header(result, &pos, &result->header)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + return G_EXE_FORMAT(result); } @@ -341,11 +350,6 @@ static bool g_dex_format_analyze(GDexFormat *format, wgroup_id_t gid, GtkStatusS base = G_BIN_FORMAT(format); exe = G_EXE_FORMAT(format); - init_vmpa(&pos, 0, VMPA_NO_VIRTUAL); - - if (!read_dex_header(format, &pos, &format->header)) - goto gdfa_error; - /* Vérification des tailles fournies */ size = g_binary_content_compute_size(G_KNOWN_FORMAT(base)->content); diff --git a/plugins/elf/format.c b/plugins/elf/format.c index 75b9a6c..9cf48ce 100644 --- a/plugins/elf/format.c +++ b/plugins/elf/format.c @@ -255,6 +255,12 @@ GExeFormat *g_elf_format_new(GBinContent *content) g_known_format_set_content(G_KNOWN_FORMAT(result), content); + if (!read_elf_header(result, &result->header, &result->is_32b, &result->endian)) + { + g_object_unref(G_OBJECT(result)); + return NULL; + } + return G_EXE_FORMAT(result); } @@ -331,9 +337,6 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS base = G_BIN_FORMAT(format); exe = G_EXE_FORMAT(format); - if (!read_elf_header(format, &format->header, &format->is_32b, &format->endian)) - goto error; - /* Vérification des tailles d'entrée de table */ if (ELF_HDR(format, format->header, e_phentsize) != ELF_SIZEOF_PHDR(format)) diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am index 575defd..7d3518c 100644 --- a/src/gui/dialogs/Makefile.am +++ b/src/gui/dialogs/Makefile.am @@ -7,6 +7,7 @@ UI_FILES = \ bookmark.ui \ export_graph.ui \ identity.ui \ + loading.ui \ preferences.ui \ prefs_fgraph.ui \ prefs_labels.ui \ @@ -21,6 +22,7 @@ libguidialogs_la_SOURCES = \ goto.h goto.c \ gotox.h gotox.c \ identity.h identity.c \ + loading.h loading.c \ plugins.h plugins.c \ preferences.h preferences.c \ prefs_fgraph.h prefs_fgraph.c \ diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml index bf81af4..f54d5b4 100644 --- a/src/gui/dialogs/gresource.xml +++ b/src/gui/dialogs/gresource.xml @@ -4,6 +4,7 @@ bookmark.ui export_graph.ui identity.ui + loading.ui preferences.ui prefs_fgraph.ui prefs_labels.ui diff --git a/src/gui/dialogs/loading.c b/src/gui/dialogs/loading.c new file mode 100644 index 0000000..62992fa --- /dev/null +++ b/src/gui/dialogs/loading.c @@ -0,0 +1,517 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * loading.c - fenêtre de chargement de nouveaux contenus + * + * Copyright (C) 2020 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 Chrysalide. If not, see . + */ + + +#include "loading.h" + + +#include +#include +#include +#include + + +#include + + +#include "../../analysis/binary.h" +#include "../../core/processors.h" + + + +/* Colonnes de la liste des contenus chargés */ +typedef enum _LoadedContentColumn +{ + LCC_NAME, /* Désignation humaine */ + LCC_CONTENT, /* Contenu chargé */ + LCC_PROJECT, /* Cadre du chargement */ + LCC_RECOGNIZED, /* Binaire brut ? */ + +} LoadedContentColumn; + + +/* Réagit à un changement de sélection des contenus chargés. */ +static void on_loaded_selection_changed(GtkTreeSelection *, GtkBuilder *); + +/* Réagit à un changement de mode de chargement. */ +static void on_load_mode_toggled(GtkToggleButton *, GtkBuilder *); + +/* Réagit à une pression de la touche "Echappe". */ +static gboolean on_key_press_event(GtkWidget *, GdkEventKey *, GtkBuilder *); + +/* Réagit à un clic sur la bouton "Annuler". */ +static void on_cancel_clicked(GtkButton *, GtkBuilder *); + +/* Réagit à un clic sur la bouton "Valider". */ +static void on_validate_clicked(GtkButton *, GtkBuilder *); + +/* Actualise les moyens affichés dans la boîte de chargement. */ +static void update_loading_dialog(GtkBuilder *); + +/* Actualise le décompte des différents types de binaires. */ +static void update_loading_dialog_counter(GtkBuilder *); + + + +/****************************************************************************** +* * +* Paramètres : parent = fenêtre principale de l'éditeur. * +* outb = constructeur à détruire après usage. [OUT] * +* * +* Description : Construit une boîte de dialogue dédiée aux chargements. * +* * +* Retour : Adresse de la fenêtre mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *create_loading_dialog(GtkWindow *parent, GtkBuilder **outb) +{ + GtkWidget *result; /* Fenêtre à renvoyer */ + GtkBuilder *builder; /* Constructeur utilisé */ + GtkTreeModelFilter *filter; /* Modèle filtrant */ + + builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/loading.ui"); + *outb = builder; + + result = GTK_WIDGET(gtk_builder_get_object(builder, "window")); + + gtk_window_set_transient_for(GTK_WINDOW(result), parent); + + filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filtered_store")); + gtk_tree_model_filter_set_visible_column(filter, LCC_RECOGNIZED); + + /* Connexion des signaux */ + + gtk_builder_add_callback_symbols(builder, + "on_loaded_selection_changed", G_CALLBACK(on_loaded_selection_changed), + "on_load_mode_toggled", G_CALLBACK(on_load_mode_toggled), + "on_key_press_event", G_CALLBACK(on_key_press_event), + "on_cancel_clicked", G_CALLBACK(on_cancel_clicked), + "on_validate_clicked", G_CALLBACK(on_validate_clicked), + NULL); + + gtk_builder_connect_signals(builder, builder); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : selection = gestionnaire de sélection impacté. * +* builder = constructeur à utiliser. * +* * +* Description : Réagit à un changement de sélection des contenus chargés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_loaded_selection_changed(GtkTreeSelection *selection, GtkBuilder *builder) +{ + GtkTreeModel *model; /* Modèle de gestion */ + GtkTreeIter iter; /* Point de sélection */ + gboolean state; /* Présence d'une sélection */ + GtkWidget *widget; /* Composant à actualiser */ + const char *id; /* Identifiant d'architecture */ + GLoadedContent *loaded; /* Contenu chargé */ + GExeFormat *format; /* Format binaire reconnu */ + GtkComboBox *combobox; /* Sélection d'architecture */ + + /* Mise à jour des accès */ + + state = gtk_tree_selection_get_selected(selection, &model, &iter); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "load_all")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "load_one")); + gtk_widget_set_sensitive(widget, state); + + on_load_mode_toggled(NULL, builder); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "ok_button")); + gtk_widget_set_sensitive(widget, state); + + /* Mise à jour de l'architecture */ + + id = "none"; + + if (state) + { + gtk_tree_model_get(model, &iter, LCC_CONTENT, &loaded, -1); + + if (G_IS_LOADED_BINARY(loaded)) + { + format = g_loaded_binary_get_format(G_LOADED_BINARY(loaded)); + + id = g_exe_format_get_target_machine(format); + + g_object_unref(G_OBJECT(format)); + + } + + g_object_unref(G_OBJECT(loaded)); + + } + + combobox = GTK_COMBO_BOX(gtk_builder_get_object(builder, "arch_sel")); + + gtk_combo_box_set_active_id(combobox, id); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réagit à un changement de mode de chargement. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_load_mode_toggled(GtkToggleButton *button, GtkBuilder *builder) +{ + GtkToggleButton *all_button; /* Selection de mode */ + gboolean state; /* Chargement fin ? */ + GtkTreeView *treeview; /* Vue en arboresence */ + GtkTreeSelection *selection; /* Sélection associée */ + GtkWidget *widget; /* Composant à actualiser */ + + all_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "load_all")); + + state = !gtk_toggle_button_get_active(all_button); + + if (state) + { + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + selection = gtk_tree_view_get_selection(treeview); + + state = gtk_tree_selection_get_selected(selection, NULL, NULL); + + } + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "arch_label")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "arch_sel")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "config_and_run")); + gtk_widget_set_sensitive(widget, state); + + widget = GTK_WIDGET(gtk_builder_get_object(builder, "process_remaining")); + gtk_widget_set_sensitive(widget, state); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant graphique visé par la procédure. * +* event = informations liées à l'événement. * +* builder = espace de référencement global. * +* * +* Description : Réagit à une pression de la touche "Echappe". * +* * +* Retour : TRUE pour indiquer une prise en compte, FALSE sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean on_key_press_event(GtkWidget *widget, GdkEventKey *event, GtkBuilder *builder) +{ + gboolean result; /* Bilan à retourner */ + + if (event->keyval == GDK_KEY_Escape) + { + on_cancel_clicked(NULL, builder); + result = TRUE; + } + + else + result = FALSE; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réagit à un clic sur la bouton "Annuler". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_cancel_clicked(GtkButton *button, GtkBuilder *builder) +{ + GtkWidget *window; /* Fenêtre à cacher */ + + + + + /* Disparition de la fenêtre */ + + window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); + + gtk_widget_hide(window); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* builder = espace de référencement global. * +* * +* Description : Réagit à un clic sur la bouton "Valider". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_validate_clicked(GtkButton *button, GtkBuilder *builder) +{ + GtkTreeView *treeview; /* Vue en arboresence */ + GtkTreeSelection *selection; /* Sélection associée */ + GtkTreeModel *model; /* Modèle de gestion */ + GtkTreeIter iter; /* Point de sélection */ + GLoadedContent *loaded; /* Contenu chargé */ + GStudyProject *project; /* projet associé */ + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + selection = gtk_tree_view_get_selection(treeview); + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, LCC_CONTENT, &loaded, LCC_PROJECT, &project, -1); + + g_signal_connect(loaded, "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + + g_loaded_content_analyze(loaded, true, true); + + g_object_unref(G_OBJECT(loaded)); + + } + + + + /* Disparition de la fenêtre ? */ + + if (true) + on_cancel_clicked(NULL, builder); + +} + + +/****************************************************************************** +* * +* Paramètres : builder = constructeur à utiliser. * +* * +* Description : Actualise les moyens affichés dans la boîte de chargement. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_loading_dialog(GtkBuilder *builder) +{ + GtkComboBoxText *combobox; /* Sélection d'architecture */ + char **keys; /* Liste des architectures */ + size_t count; /* Taille de cette liste */ + size_t i; /* Boucle de parcours */ + GArchProcessor *proc; /* Processeur à consulter */ + char *desc; /* Description humaine */ + + /* Mise à jour de la liste des architectures */ + + combobox = GTK_COMBO_BOX_TEXT(gtk_builder_get_object(builder, "arch_sel")); + + gtk_combo_box_text_remove_all(combobox); + + gtk_combo_box_text_append(combobox, "none", _("None")); + + keys = get_all_processor_keys(&count); + + for (i = 0; i < count; i++) + { + proc = get_arch_processor_for_key(keys[i]); + + desc = g_arch_processor_get_desc(proc); + + gtk_combo_box_text_append(combobox, keys[i], desc); + + g_object_unref(G_OBJECT(proc)); + free(keys[i]); + + } + + if (keys != NULL) + free(keys); + +} + + +/****************************************************************************** +* * +* Paramètres : builder = constructeur à utiliser. * +* * +* Description : Actualise le décompte des différents types de binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_loading_dialog_counter(GtkBuilder *builder) +{ + + unsigned int recognized_counter; /* Compteur de reconnus */ + unsigned int total_counter; /* Compteur de binaires */ + GtkTreeModel *model; /* Modèle de gestion */ + GtkTreeIter iter; /* Point de sélection */ + gboolean valid; /* Validité de l'itérateur */ + gboolean recognized; /* Nature du contenu */ + char *msg; /* Message à faire apparaître */ + GtkLabel *label; /* Etiquette à mettre à jour */ + + recognized_counter = 0; + total_counter = 0; + + model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store")); + + for (valid = gtk_tree_model_get_iter_first(model, &iter); + valid; + valid = gtk_tree_model_iter_next(model, &iter)) + { + gtk_tree_model_get(model, &iter, LCC_RECOGNIZED, &recognized, -1); + + if (recognized) + recognized_counter++; + + total_counter++; + + } + + asprintf(&msg, "(%u / %u)", total_counter - recognized_counter, total_counter); + + label = GTK_LABEL(gtk_builder_get_object(builder, "hidden_counter")); + gtk_label_set_text(label, msg); + + free(msg); + +} + + +/****************************************************************************** +* * +* Paramètres : builder = constructeur à utiliser. * +* content = nouveau contenu chargé à intégrer. * +* project = project impliqué dans l'opération. * +* * +* Description : Ajoute un binaire à la liste à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void add_content_to_loading_dialog(GtkBuilder *builder, GLoadedContent *content, GStudyProject *project) +{ + GtkListStore *store; /* Modèle de gestion */ + char *name; /* Désignation complète */ + gboolean recognized; /* Nature du contenu */ + GtkTreeIter iter; /* Point d'insertion */ + GtkTreeView *treeview; /* Vue en arboresence */ + GtkTreeSelection *selection; /* Gestionnaire de sélection */ + GtkTreeModelFilter *filter; /* Modèle filtrant */ + GtkTreeIter filtered_iter; /* Point d'insertion */ + gboolean status; /* Bilan d'une conversion */ + + /* Mise à jour de l'interface (#0) */ + + update_loading_dialog(builder); + + /* Inscription */ + + asprintf(&name, "%s (%s)", + g_loaded_content_describe(content, false), + g_loaded_content_get_format_name(content)); + + recognized = TRUE; + + store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store")); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + LCC_NAME, name, + LCC_CONTENT, content, + LCC_PROJECT, project, + LCC_RECOGNIZED, recognized, + -1); + + free(name); + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview")); + selection = gtk_tree_view_get_selection(treeview); + + if (!gtk_tree_selection_get_selected(selection, NULL, NULL)) + { + filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filtered_store")); + + status = gtk_tree_model_filter_convert_child_iter_to_iter(filter, &filtered_iter, &iter); + assert(status); + + if (status) + gtk_tree_selection_select_iter(selection, &filtered_iter); + + } + + /* Mise à jour de l'interface (#1) */ + + update_loading_dialog_counter(builder); + +} diff --git a/src/gui/dialogs/loading.h b/src/gui/dialogs/loading.h new file mode 100644 index 0000000..71f84f4 --- /dev/null +++ b/src/gui/dialogs/loading.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * loading.h - prototypes pour la fenêtre de chargement de nouveaux contenus + * + * Copyright (C) 2020 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 Chrysalide. If not, see . + */ + + +#ifndef _GUI_DIALOGS_LOADING_H +#define _GUI_DIALOGS_LOADING_H + + +#include + + +#include "../../analysis/loaded.h" +#include "../../analysis/project.h" + + + +/* Construit une boîte de dialogue dédiée aux chargements. */ +GtkWidget *create_loading_dialog(GtkWindow *, GtkBuilder **); + +/* Ajoute un binaire à la liste à charger. */ +void add_content_to_loading_dialog(GtkBuilder *, GLoadedContent *, GStudyProject *); + + + +#endif /* _GUI_DIALOGS_LOADING_H */ diff --git a/src/gui/dialogs/loading.ui b/src/gui/dialogs/loading.ui new file mode 100644 index 0000000..a9ec7aa --- /dev/null +++ b/src/gui/dialogs/loading.ui @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + store + + + False + New loading + True + center + 540 + 430 + + + + + + + + True + False + 8 + 8 + 8 + 8 + vertical + 8 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + vertical + 4 + + + True + True + in + + + True + True + filtered_store + False + True + + + + + + + + column + + + + 0 + + + + + + + + + True + True + 0 + + + + + True + False + + + Hide unrecognized contents + True + True + False + True + True + + + False + True + 0 + + + + + True + False + (0 / 0) + + + False + True + 1 + + + + + False + True + 1 + + + + + + + + + True + False + Available contents + + + + + True + True + 0 + + + + + Load all contents at once with default options + True + True + False + 8 + True + True + + + + False + True + 1 + + + + + Load one content with specific options + True + True + False + True + True + load_all + + + False + True + 2 + + + + + True + False + 24 + + + True + False + vertical + 8 + + + True + False + 8 + + + True + False + False + Set architecture: + + + False + True + 0 + + + + + True + False + False + + + True + True + 1 + + + + + False + True + 0 + + + + + Configure and run the analysis + True + False + True + False + True + True + + + False + True + 1 + + + + + Process the remaining contents + True + True + False + True + True + + + False + True + 2 + + + + + + + False + True + 3 + + + + + True + False + 8 + end + + + gtk-cancel + True + True + True + True + + + + True + True + 0 + + + + + gtk-ok + True + True + True + True + True + + + + True + True + 1 + + + + + False + True + 4 + + + + + + diff --git a/src/gui/editor.c b/src/gui/editor.c index f45acbd..bdd9a78 100644 --- a/src/gui/editor.c +++ b/src/gui/editor.c @@ -36,6 +36,7 @@ #include "agroup.h" #include "status.h" +#include "dialogs/loading.h" #include "menus/file.h" #include "menus/menubar.h" #include "core/core.h" @@ -59,7 +60,9 @@ - +/* Fenêtre de chargement de binaires */ +static GtkWidget *_load_dialog = NULL; +static GtkBuilder *_load_dialog_builder = NULL; @@ -308,7 +311,9 @@ GtkWidget *create_editor(void) change_editor_items_current_content(NULL); change_editor_items_current_view(NULL); + /* Préparation des fenêtres complémentaires */ + _load_dialog = create_loading_dialog(GTK_WINDOW(result), &_load_dialog_builder); return result; @@ -323,7 +328,7 @@ GtkWidget *create_editor(void) * * * Description : Quitte le programme en sortie de la boucle de GTK. * * * -* Retour : - * +* Retour : TRUE pour éviter la fermeture, FALSE sinon. * * * * Remarques : - * * * @@ -897,11 +902,9 @@ static void notify_editor_project_change(GStudyProject *project, bool new) static void on_editor_content_available(GStudyProject *project, GLoadedContent *content, void *unused) { - g_object_ref(G_OBJECT(content)); - - g_signal_connect(content, "analyzed", G_CALLBACK(on_loaded_content_analyzed), project); + add_content_to_loading_dialog(_load_dialog_builder, content, project); - g_loaded_content_analyze(content, true, true); + gtk_widget_show(_load_dialog); } -- cgit v0.11.2-87-g4458