summaryrefslogtreecommitdiff
path: root/plugins/winordinals/assign.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/winordinals/assign.c')
-rw-r--r--plugins/winordinals/assign.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/plugins/winordinals/assign.c b/plugins/winordinals/assign.c
new file mode 100644
index 0000000..16b7eaa
--- /dev/null
+++ b/plugins/winordinals/assign.c
@@ -0,0 +1,348 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * assign.c - renseignement des importations sous forme d'ordinaux
+ *
+ * Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "assign.h"
+
+
+#include <i18n.h>
+#include <core/global.h>
+#include <core/nproc.h>
+#include <glibext/delayed-int.h>
+#include <plugins/pe/routine.h>
+
+
+#include "ordinals.h"
+
+
+
+#define G_TYPE_ORDINAL_RESOLVER g_ordinal_resolver_get_type()
+#define G_ORDINAL_RESOLVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolver))
+#define G_IS_ORDINAL_RESOLVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ORDINAL_RESOLVER))
+#define G_ORDINAL_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolverClass))
+#define G_IS_ORDINAL_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ORDINAL_RESOLVER))
+#define G_ORDINAL_RESOLVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ORDINAL_RESOLVER, GOrdinalResolverClass))
+
+
+/* Tâche de résolution d'ordinaux (instance) */
+typedef struct _GOrdinalResolver
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ GPeFormat *format; /* Format à faire évoluer */
+
+ size_t begin; /* Point de départ du parcours */
+ size_t end; /* Point d'arrivée exclu */
+
+ activity_id_t id; /* Identifiant pour messages */
+
+} GOrdinalResolver;
+
+/* Tâche de résolution d'ordinaux (classe) */
+typedef struct _GOrdinalResolverClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+} GOrdinalResolverClass;
+
+
+/* Indique le type défini pour les tâches de résolution d'ordinaux. */
+GType g_ordinal_resolver_get_type(void);
+
+/* Initialise la classe des tâches des resolutions d'ordinaux. */
+static void g_ordinal_resolver_class_init(GOrdinalResolverClass *);
+
+/* Initialise une tâche de résolution d'ordinaux importés. */
+static void g_ordinal_resolver_init(GOrdinalResolver *);
+
+/* Supprime toutes les références externes. */
+static void g_ordinal_resolver_dispose(GOrdinalResolver *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_ordinal_resolver_finalize(GOrdinalResolver *);
+
+/* Crée une tâche de résolution des ordinaux importés. */
+static GOrdinalResolver *g_ordinal_resolver_new(GPeFormat *, size_t, size_t, activity_id_t);
+
+/* Effectue une résolution d'ordinaux importés. */
+static void g_ordinal_resolver_process(GOrdinalResolver *, GtkStatusStack *);
+
+
+
+/* Indique le type défini pour les tâches de résolution d'ordinaux. */
+G_DEFINE_TYPE(GOrdinalResolver, g_ordinal_resolver, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des tâches des resolutions d'ordinaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ordinal_resolver_class_init(GOrdinalResolverClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GDelayedWorkClass *work; /* Version en classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_ordinal_resolver_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_ordinal_resolver_finalize;
+
+ work = G_DELAYED_WORK_CLASS(klass);
+
+ work->run = (run_task_fc)g_ordinal_resolver_process;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance à initialiser. *
+* *
+* Description : Initialise une tâche de résolution d'ordinaux importés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ordinal_resolver_init(GOrdinalResolver *resolver)
+{
+ resolver->format = NULL;
+
+ resolver->begin = 0;
+ resolver->end = 0;
+
+ resolver->id = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ordinal_resolver_dispose(GOrdinalResolver *resolver)
+{
+ g_clear_object(&resolver->format);
+
+ G_OBJECT_CLASS(g_ordinal_resolver_parent_class)->dispose(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ordinal_resolver_finalize(GOrdinalResolver *resolver)
+{
+ G_OBJECT_CLASS(g_ordinal_resolver_parent_class)->finalize(G_OBJECT(resolver));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = ensemble d'instructions désassemblées. *
+* begin = point de départ du parcours de liste. *
+* end = point d'arrivée exclu du parcours. *
+* id = identifiant du message affiché à l'utilisateur. *
+* *
+* Description : Crée une tâche de résolution des ordinaux importés. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GOrdinalResolver *g_ordinal_resolver_new(GPeFormat *format, size_t begin, size_t end, activity_id_t id)
+{
+ GOrdinalResolver *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_ORDINAL_RESOLVER, NULL);
+
+ result->format = format;
+ g_object_ref(G_OBJECT(format));
+
+ result->begin = begin;
+ result->end = end;
+
+ result->id = id;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : resolver = étude de routines à mener. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Effectue une résolution d'ordinaux importés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ordinal_resolver_process(GOrdinalResolver *resolver, GtkStatusStack *status)
+{
+ GBinFormat *base; /* Format basique du binaire */
+ size_t i; /* Boucle de parcours #1 */
+ GBinSymbol *symbol; /* Commodité d'accès */
+ uint16_t ordinal; /* Ordinal défini */
+ const char *name; /* Désignation actuelle */
+ const char *library; /* Fichier DLL à charger */
+
+ base = G_BIN_FORMAT(resolver->format);
+
+ for (i = resolver->begin; i < resolver->end; i++)
+ {
+ symbol = g_binary_format_get_symbol(base, i);
+
+ if (!G_IS_PE_IMPORTED_ROUTINE(symbol))
+ goto next;
+
+ ordinal = g_pe_exported_routine_get_ordinal(G_PE_EXPORTED_ROUTINE(symbol));
+
+ if (ordinal == UNDEF_PE_ORDINAL)
+ goto next;
+
+ name = g_binary_routine_get_name(G_BIN_ROUTINE(symbol));
+
+ if (name != NULL)
+ goto next;
+
+ library = g_pe_imported_routine_get_library(G_PE_IMPORTED_ROUTINE(symbol));
+
+ if (library == NULL)
+ goto next;
+
+ name = get_symbol_by_ordinal(library, ordinal);
+
+ if (name != NULL)
+ g_binary_routine_set_name(G_BIN_ROUTINE(symbol), strdup(name));
+
+ next:
+
+ gtk_status_stack_update_activity_value(status, resolver->id, 1);
+
+ g_object_unref(G_OBJECT(symbol));
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = format PE à traiter. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Attribue un nom aux symboles PE importés par ordinal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void assign_name_imported_ordinals(GPeFormat *format, GtkStatusStack *status)
+{
+ GBinFormat *base; /* Format basique du binaire */
+ size_t sym_count; /* Nombre de ces symboles */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ size_t run_size; /* Volume réparti par exécution*/
+ activity_id_t id; /* Identifiant de progression */
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ wgroup_id_t gid; /* Identifiant pour les tâches */
+ guint i; /* Boucle de parcours */
+ size_t begin; /* Début de bloc de traitement */
+ size_t end; /* Fin d'un bloc de traitement */
+ GOrdinalResolver *resolver; /* Tâche d'étude à programmer */
+
+ base = G_BIN_FORMAT(format);
+
+ g_binary_format_lock_symbols_rd(base);
+
+ sym_count = g_binary_format_count_symbols(base);
+
+ run_size = compute_run_size(sym_count, &runs_count);
+
+ id = gtk_status_stack_add_activity(status, _("Resolving names for imported ordinals..."), sym_count);
+
+ queue = get_work_queue();
+
+ gid = g_work_queue_define_work_group(queue);
+
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = i * run_size;
+
+ if ((i + 1) == runs_count)
+ end = sym_count;
+ else
+ end = begin + run_size;
+
+ resolver = g_ordinal_resolver_new(format, begin, end, id);
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(resolver), gid);
+
+ }
+
+ g_work_queue_wait_for_completion(queue, gid);
+
+ g_work_queue_delete_work_group(queue, gid);
+
+ gtk_status_stack_remove_activity(status, id);
+
+ g_binary_format_unlock_symbols_rd(base);
+
+}