From 83da8ea946dc50941838ec8b3951108f5e16642e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 7 May 2018 17:00:14 +0200
Subject: Described binary formats and improved their loading.

---
 plugins/dex/core.c                   | 14 +------
 plugins/dex/format.c                 | 63 ++++++++++++++++++++++++++++++
 plugins/dex/format.h                 |  3 ++
 plugins/dex/python/format.c          | 15 ++++++--
 plugins/elf/core.c                   | 17 +--------
 plugins/elf/format.c                 | 60 ++++++++++++++++++-----------
 plugins/elf/format.h                 |  4 +-
 plugins/elf/python/format.c          | 15 ++++++--
 plugins/pychrysalide/format/format.c | 74 ++++++++++++++++++++++++++++++++++++
 src/format/format-int.h              |  4 ++
 src/format/format.c                  | 23 +++++++++++
 src/format/format.h                  |  3 ++
 12 files changed, 236 insertions(+), 59 deletions(-)

diff --git a/plugins/dex/core.c b/plugins/dex/core.c
index 869ef4b..da0a540 100644
--- a/plugins/dex/core.c
+++ b/plugins/dex/core.c
@@ -54,10 +54,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = register_format_loader("dex", "Dalvik Executable format", g_dex_format_new);
-
-    if (result)
-        result = add_format_dex_module_to_python_module();
+    result = add_format_dex_module_to_python_module();
 
     return result;
 
@@ -82,19 +79,12 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 
 G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
 {
-    vmpa2t addr;                            /* Tête de lecture initiale    */
     bool test;                              /* Bilan des accès mémoire     */
-    char magic[DEX_FILE_MAGIC_LEN];         /* Idenfiant standard          */
     GExeFormat *format;                     /* Format DEX reconnu          */
     GLoadedContent *loaded;                 /* Représentation chargée      */
     GContentResolver *resolver;             /* Resolveur de contenus       */
 
-    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
-
-    test = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic);
-
-    if (test)
-        test = (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0);
+    test = check_dex_format(content);
 
     if (test)
     {
diff --git a/plugins/dex/format.c b/plugins/dex/format.c
index 1fa5a7d..b9b6ca9 100755
--- a/plugins/dex/format.c
+++ b/plugins/dex/format.c
@@ -55,6 +55,9 @@ static void g_dex_format_finalize(GDexFormat *);
 /* Indique la désignation interne du format. */
 static const char *g_dex_format_get_name(const GDexFormat *);
 
+/* Fournit une description humaine du format. */
+static const char *g_dex_format_get_description(const GDexFormat *);
+
 /* Assure l'interprétation d'un format en différé. */
 static bool g_dex_format_analyze(GDexFormat *, wgroup_id_t, GtkStatusStack *);
 
@@ -90,6 +93,39 @@ static void g_dex_format_decompile(const GDexFormat *, void/*GCodeBuffer*/ *, co
 
 
 
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : content = contenu binaire à traiter.                         *
+*                                                                             *
+*  Description : Valide un contenu comme étant un format Dex.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool check_dex_format(const GBinContent *content)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    vmpa2t addr;                            /* Tête de lecture initiale    */
+    char magic[DEX_FILE_MAGIC_LEN];         /* Idenfiant standard          */
+
+    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+
+    result = g_binary_content_read_raw(content, &addr, DEX_FILE_MAGIC_LEN, (bin_t *)magic);
+
+    if (result)
+        result = (memcmp(magic, DEX_FILE_MAGIC, DEX_FILE_MAGIC_LEN) == 0);
+
+    return result;
+
+}
+
+
 /* Indique le type défini pour un format d'exécutable DEX. */
 G_DEFINE_TYPE(GDexFormat, g_dex_format, G_TYPE_EXE_FORMAT);
 
@@ -120,6 +156,7 @@ static void g_dex_format_class_init(GDexFormatClass *klass)
     fmt = G_BIN_FORMAT_CLASS(klass);
 
     fmt->get_name = (format_get_name_fc)g_dex_format_get_name;
+    fmt->get_desc = (format_get_desc_fc)g_dex_format_get_description;
     fmt->analyze = (format_analyze_fc)g_dex_format_analyze;
     fmt->get_endian = (format_get_endian_fc)g_dex_format_get_endianness;
 
@@ -216,6 +253,9 @@ GExeFormat *g_dex_format_new(GBinContent *content)
 {
     GDexFormat *result;                     /* Structure à retourner       */
 
+    if (!check_dex_format(content))
+        return NULL;
+
     result = g_object_new(G_TYPE_DEX_FORMAT, NULL);
 
     g_binary_format_set_content(G_BIN_FORMAT(result), content);
@@ -250,6 +290,29 @@ static const char *g_dex_format_get_name(const GDexFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Fournit une description humaine du format.                   *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_dex_format_get_description(const GDexFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = "Dalvik Executable format (version '035')";
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = format chargé dont l'analyse est lancée.            *
 *                gid    = groupe de travail dédié.                            *
 *                status = barre de statut à tenir informée.                   *
diff --git a/plugins/dex/format.h b/plugins/dex/format.h
index 6850ed1..1879da3 100755
--- a/plugins/dex/format.h
+++ b/plugins/dex/format.h
@@ -52,6 +52,9 @@ typedef struct _GDexFormat GDexFormat;
 typedef struct _GDexFormatClass GDexFormatClass;
 
 
+/* Valide un contenu comme étant un format Dex. */
+bool check_dex_format(const GBinContent *);
+
 /* Indique le type défini pour un format d'exécutable DEX. */
 GType g_dex_format_get_type(void);
 
diff --git a/plugins/dex/python/format.c b/plugins/dex/python/format.c
index 81db02f..8bcd2fa 100644
--- a/plugins/dex/python/format.c
+++ b/plugins/dex/python/format.c
@@ -100,13 +100,20 @@ static PyObject *py_dex_format_new(PyTypeObject *type, PyObject *args, PyObject
     content = G_BIN_CONTENT(pygobject_get(content_obj));
 
     format = g_dex_format_new(content);
-    assert(format != NULL);
 
-    result = pygobject_new(G_OBJECT(format));
+    if (format == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
 
-    g_object_unref(format);
+    else
+    {
+        result = pygobject_new(G_OBJECT(format));
+        g_object_unref(format);
+    }
 
-    return (PyObject *)result;
+    return result;
 
 }
 
diff --git a/plugins/elf/core.c b/plugins/elf/core.c
index 7486242..03d5964 100644
--- a/plugins/elf/core.c
+++ b/plugins/elf/core.c
@@ -54,13 +54,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 {
     bool result;                            /* Bilan à retourner           */
 
-    result = register_format_matcher(elf_is_matching, NULL);
-
-    if (result)
-        result = register_format_loader("elf", "Executable and Linkable Format", g_elf_format_new);
-
-    if (result)
-        result = add_format_elf_module_to_python_module();
+    result = add_format_elf_module_to_python_module();
 
     return result;
 
@@ -85,19 +79,12 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
 
 G_MODULE_EXPORT void chrysalide_plugin_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, gid_t gid, GtkStatusStack *status)
 {
-    vmpa2t addr;                            /* Tête de lecture initiale    */
     bool test;                              /* Bilan des accès mémoire     */
-    char magic[SELFMAG];                    /* Idenfiant standard          */
     GExeFormat *format;                     /* Format ELF reconnu          */
     GLoadedContent *loaded;                 /* Représentation chargée      */
     GContentResolver *resolver;             /* Resolveur de contenus       */
 
-    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
-
-    test = g_binary_content_read_raw(content, &addr, SELFMAG, (bin_t *)magic);
-
-    if (test)
-        test = (memcmp(magic, ELFMAG, SELFMAG) == 0);
+    test = check_elf_format(content);
 
     if (test)
     {
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index 86682a2..9e29a11 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -63,6 +63,9 @@ static void g_elf_format_finalize(GElfFormat *);
 /* Indique la désignation interne du format. */
 static const char *g_elf_format_get_name(const GElfFormat *);
 
+/* Fournit une description humaine du format. */
+static const char *g_elf_format_get_description(const GElfFormat *);
+
 /* Assure l'interprétation d'un format en différé. */
 static bool g_elf_format_analyze(GElfFormat *, wgroup_id_t, GtkStatusStack *);
 
@@ -94,42 +97,28 @@ static bool g_elf_format_get_section_range_by_name(const GElfFormat *, const cha
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = contenu binaire à parcourir.                       *
-*                parent  = éventuel format exécutable déjà chargé.            *
-*                unused  = adresse non utilisée ici.                          *
-*                key     = identifiant de format trouvé ou NULL. [OUT]        *
+*  Paramètres  : content = contenu binaire à traiter.                         *
 *                                                                             *
-*  Description : Indique si le format peut être pris en charge ici.           *
+*  Description : Valide un contenu comme étant un format Elf.                 *
 *                                                                             *
-*  Retour      : Conclusion de haut niveau sur la reconnaissance effectuée.   *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-FormatMatchStatus elf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key)
+bool check_elf_format(const GBinContent *content)
 {
-    FormatMatchStatus result;               /* Bilan à renvoyer            */
+    bool result;                            /* Bilan à faire remonter      */
     vmpa2t addr;                            /* Tête de lecture initiale    */
-    bool status;                            /* Bilan des accès mémoire     */
     char magic[4];                          /* Idenfiant standard          */
 
-    if (parent != NULL)
-        return FMS_UNKNOWN;
-
     init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
 
-    status = g_binary_content_read_raw(content, &addr, 4, (bin_t *)magic);
+    result = g_binary_content_read_raw(content, &addr, 4, (bin_t *)magic);
 
-    status &= (memcmp(magic, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0);
-
-    if (status)
-    {
-        result = FMS_MATCHED;
-        *key = strdup("elf");
-    }
-    else
-        result = FMS_UNKNOWN;
+    if (result)
+        result = (memcmp(magic, "\x7f\x45\x4c\x46" /* .ELF */, 4) == 0);
 
     return result;
 
@@ -166,6 +155,7 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
     fmt = G_BIN_FORMAT_CLASS(klass);
 
     fmt->get_name = (format_get_name_fc)g_elf_format_get_name;
+    fmt->get_desc = (format_get_desc_fc)g_elf_format_get_description;
     fmt->analyze = (format_analyze_fc)g_elf_format_analyze;
     fmt->get_endian = (format_get_endian_fc)g_elf_format_get_endianness;
 
@@ -257,6 +247,9 @@ GExeFormat *g_elf_format_new(GBinContent *content)
 {
     GElfFormat *result;                     /* Structure à retourner       */
 
+    if (!check_elf_format(content))
+        return NULL;
+
     result = g_object_new(G_TYPE_ELF_FORMAT, NULL);
 
     g_binary_format_set_content(G_BIN_FORMAT(result), content);
@@ -291,6 +284,29 @@ static const char *g_elf_format_get_name(const GElfFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Fournit une description humaine du format.                   *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const char *g_elf_format_get_description(const GElfFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = "Executable and Linkable Format";
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = format chargé dont l'analyse est lancée.            *
 *                gid    = groupe de travail dédié.                            *
 *                status = barre de statut à tenir informée.                   *
diff --git a/plugins/elf/format.h b/plugins/elf/format.h
index 47b3171..c97ed67 100644
--- a/plugins/elf/format.h
+++ b/plugins/elf/format.h
@@ -52,8 +52,8 @@ typedef struct _GElfFormat GElfFormat;
 typedef struct _GElfFormatClass GElfFormatClass;
 
 
-/* Indique si le format peut être pris en charge ici. */
-FormatMatchStatus elf_is_matching(GBinContent *, GExeFormat *, void *, char **);
+/* Valide un contenu comme étant un format Elf. */
+bool check_elf_format(const GBinContent *);
 
 /* Indique le type défini pour un format d'exécutable ELF. */
 GType g_elf_format_get_type(void);
diff --git a/plugins/elf/python/format.c b/plugins/elf/python/format.c
index 0319ba9..87b590b 100644
--- a/plugins/elf/python/format.c
+++ b/plugins/elf/python/format.c
@@ -82,13 +82,20 @@ static PyObject *py_elf_format_new(PyTypeObject *type, PyObject *args, PyObject
     content = G_BIN_CONTENT(pygobject_get(content_obj));
 
     format = g_elf_format_new(content);
-    assert(format != NULL);
 
-    result = pygobject_new(G_OBJECT(format));
+    if (format == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
 
-    g_object_unref(format);
+    else
+    {
+        result = pygobject_new(G_OBJECT(format));
+        g_object_unref(format);
+    }
 
-    return (PyObject *)result;
+    return result;
 
 }
 
diff --git a/plugins/pychrysalide/format/format.c b/plugins/pychrysalide/format/format.c
index 15abcf7..561c0c2 100644
--- a/plugins/pychrysalide/format/format.c
+++ b/plugins/pychrysalide/format/format.c
@@ -60,6 +60,12 @@ static PyObject *py_binary_format_find_next_symbol_at(PyObject *, PyObject *);
 /* Recherche le symbole correspondant à une adresse. */
 static PyObject *py_binary_format_resolve_symbol(PyObject *, PyObject *);
 
+/* Indique la désignation interne du format. */
+static PyObject *py_binary_format_get_name(PyObject *, void *);
+
+/* Indique la désignation humaine du format. */
+static PyObject *py_binary_format_get_description(PyObject *, void *);
+
 /* Fournit une référence vers le contenu binaire analysé. */
 static PyObject *py_binary_format_get_content(PyObject *, void *);
 
@@ -370,6 +376,66 @@ static PyObject *py_binary_format_resolve_symbol(PyObject *self, PyObject *args)
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
+*  Description : Indique la désignation interne du format.                    *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_format_get_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GBinFormat *format;                     /* Format de binaire manipulé  */
+    const char *name;                       /* Description interne         */
+
+    format = G_BIN_FORMAT(pygobject_get(self));
+
+    name = g_binary_format_get_name(format);
+
+    result = PyUnicode_FromString(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Indique la désignation humaine du format.                    *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_format_get_description(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Trouvailles à retourner     */
+    GBinFormat *format;                     /* Format de binaire manipulé  */
+    const char *desc;                       /* Description humaine         */
+
+    format = G_BIN_FORMAT(pygobject_get(self));
+
+    desc = g_binary_format_get_description(format);
+
+    result = PyUnicode_FromString(desc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
 *  Description : Fournit une référence vers le contenu binaire analysé.       *
 *                                                                             *
 *  Retour      : Gestionnaire de contenu binaire en place.                    *
@@ -611,6 +677,14 @@ PyTypeObject *get_python_binary_format_type(void)
 
     static PyGetSetDef py_bin_format_getseters[] = {
         {
+            "name", py_binary_format_get_name, NULL,
+            "Internal name of the binary format.", NULL
+        },
+        {
+            "description", py_binary_format_get_description, NULL,
+            "Human description of the binary format.", NULL
+        },
+        {
             "content", py_binary_format_get_content, NULL,
             "Content of the binary format.", NULL
         },
diff --git a/src/format/format-int.h b/src/format/format-int.h
index 09586b9..354e616 100644
--- a/src/format/format-int.h
+++ b/src/format/format-int.h
@@ -40,6 +40,9 @@
 /* Indique la désignation interne du format. */
 typedef const char * (* format_get_name_fc) (const GBinFormat *);
 
+/* Fournit une description humaine du format. */
+typedef const char * (* format_get_desc_fc) (const GBinFormat *);
+
 /*Assure l'interprétation d'un format en différé. */
 typedef bool (* format_analyze_fc) (GBinFormat *, wgroup_id_t, GtkStatusStack *);
 
@@ -116,6 +119,7 @@ struct _GBinFormatClass
     GObjectClass parent;                    /* A laisser en premier        */
 
     format_get_name_fc get_name;            /* Désignation interne         */
+    format_get_desc_fc get_desc;            /* Désignation humaine         */
 
     format_analyze_fc analyze;              /* Interprétation du format    */
 
diff --git a/src/format/format.c b/src/format/format.c
index b28f4a7..e6cefc8 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -283,6 +283,29 @@ const char *g_binary_format_get_name(const GBinFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                                                                             *
+*  Description : Fournit une description humaine du format.                   *
+*                                                                             *
+*  Retour      : Description du format.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_binary_format_get_description(const GBinFormat *format)
+{
+    const char *result;                     /* Désignation à retourner     */
+
+    result = G_BIN_FORMAT_GET_CLASS(format)->get_desc(format);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = format chargé dont l'analyse est lancée.            *
 *                gid    = groupe de travail dédié.                            *
 *                status = barre de statut à tenir informée.                   *
diff --git a/src/format/format.h b/src/format/format.h
index 44d005c..e552f0c 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -61,6 +61,9 @@ GBinContent *g_binary_format_get_content(const GBinFormat *);
 /* Indique la désignation interne du format. */
 const char *g_binary_format_get_name(const GBinFormat *);
 
+/* Fournit une description humaine du format. */
+const char *g_binary_format_get_description(const GBinFormat *);
+
 /* Assure l'interprétation d'un format en différé. */
 bool g_binary_format_analyze(GBinFormat *, wgroup_id_t, GtkStatusStack *);
 
-- 
cgit v0.11.2-87-g4458