From 929150f18d23d82e8390bd98e31b1edb34bc09f1 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 5 Apr 2010 19:22:50 +0000
Subject: Created a plugin to follow the control.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@149 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                   |  30 +++
 configure.ac                |   1 +
 plugins/Makefile.am         |   2 +-
 plugins/pyoida/pyoida.c     |   3 +
 plugins/theseus/Makefile.am |  14 +
 plugins/theseus/theseus.c   | 620 ++++++++++++++++++++++++++++++++++++++++++++
 plugins/theseus/theseus.h   |  49 ++++
 src/analysis/binary.c       |  19 ++
 src/analysis/binary.h       |   3 +
 src/analysis/line-int.h     |   2 +
 src/analysis/line.c         |  63 +++++
 src/analysis/line.h         |   6 +
 src/plugins/plugin-def.h    |   5 +-
 src/plugins/plugin.c        |   5 +-
 14 files changed, 815 insertions(+), 7 deletions(-)
 create mode 100644 plugins/theseus/Makefile.am
 create mode 100644 plugins/theseus/theseus.c
 create mode 100644 plugins/theseus/theseus.h

diff --git a/ChangeLog b/ChangeLog
index 3a1a18b..33225ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,35 @@
 10-04-05  Cyrille Bagard <nocbos@gmail.com>
 
+	* configure.ac:
+	Add the new Makefile from the 'plugins/theseus' directory to AC_CONFIG_FILES.
+
+	* plugins/Makefile.am:
+	Add theseus to SUBDIRS.
+
+	* plugins/pyoida/pyoida.c:
+	Disable the Python plugin.
+
+	* plugins/theseus/Makefile.am:
+	* plugins/theseus/theseus.c:
+	* plugins/theseus/theseus.h:
+	New entries: create a plugin to follow the control flow in order to avoid
+	showing garbage. Not yet fully working. Tested with the grainne crackme.
+
+	* src/analysis/binary.c:
+	* src/analysis/binary.h:
+	Provide the storage address of the rendering lines.
+
+	* src/analysis/line.c:
+	* src/analysis/line.h:
+	* src/analysis/line-int.h:
+	Add some useful functions to remove or insert lines.
+
+	* src/plugins/plugin.c:
+	* src/plugins/plugin-def.h:
+	Add a missing argument (the plugin address) when calling exec_on_bin().
+
+10-04-05  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/format/elf/elf.c:
 	* src/format/elf/elf_def.h:
 	* src/format/elf/elf-int.c:
diff --git a/configure.ac b/configure.ac
index 502e4c3..98d60c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -238,6 +238,7 @@ AC_CONFIG_FILES([Makefile
                  plugins/pyoida/arch/Makefile
                  plugins/pyoida/format/Makefile
                  plugins/stackvars/Makefile
+                 plugins/theseus/Makefile
                  src/Makefile
                  src/analysis/Makefile
                  src/arch/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 379beaa..63811b0 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,2 +1,2 @@
 
-SUBDIRS = pyoida stackvars
+SUBDIRS = pyoida stackvars theseus
diff --git a/plugins/pyoida/pyoida.c b/plugins/pyoida/pyoida.c
index 82f9980..4a79bfd 100644
--- a/plugins/pyoida/pyoida.c
+++ b/plugins/pyoida/pyoida.c
@@ -95,6 +95,9 @@ bool init_plugin(GObject *ref)
     add_to_env_var("PYTHONPATH", "/home/ocb/prog/openida/plugins/python", ";");
 
 
+    return false;
+
+
     Py_Initialize();
 
     initpyoida();
diff --git a/plugins/theseus/Makefile.am b/plugins/theseus/Makefile.am
new file mode 100644
index 0000000..8040bb4
--- /dev/null
+++ b/plugins/theseus/Makefile.am
@@ -0,0 +1,14 @@
+
+lib_LTLIBRARIES = libtheseus.la
+
+libtheseus_la_SOURCES =					\
+	theseus.h theseus.c
+
+libtheseus_la_CFLAGS = $(AM_CFLAGS)
+
+
+INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I../../src
+
+AM_CPPFLAGS = 
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/theseus/theseus.c b/plugins/theseus/theseus.c
new file mode 100644
index 0000000..aec5353
--- /dev/null
+++ b/plugins/theseus/theseus.c
@@ -0,0 +1,620 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * theseus.c - décompilation en fonction du flot d'exécution
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "theseus.h"
+
+
+#include <analysis/exporter.h>
+#include <analysis/line_code.h>
+#include <arch/artificial.h>
+
+
+/* Traite en premier lieu les adresses marquées "impératives". */
+static bool register_white_list(GOpenidaBinary *);
+
+/* Indique si une ligne peut faire l'objet d'un nouveau suivi. */
+static bool can_line_be_followed(const GRenderingLine *);
+
+/* Indique si une ligne a déjà été traitée lors d'un suivi. */
+static bool can_line_be_processed(const GRenderingLine *);
+
+/* Marque une ligne comme ayant été traitée. */
+static void mark_line_as_done(GRenderingLine *, bool);
+
+/* Suit le flot d'exécution à partir d'un point donné. */
+static bool follow_flow_from_line(GOpenidaBinary *, vmpa_t);
+
+/* Désassemble une nouvelle instruction à partir d'une adresse. */
+static GRenderingLine *disassemble_target_address(GOpenidaBinary *, GRenderingLine *, vmpa_t);
+
+/* Insère dans le flux existant les nouvelles lignes crées. */
+static bool insert_new_lines_into_flow(GOpenidaBinary *, GRenderingLine *, GRenderingLine *);
+
+
+
+
+
+/*
+mov	edx, 0x80480fb
+call	[edx]
+mov	edx, 0x80480fb
+add	edx, 0x8
+call	[edx]
+mov	edx, 0x80480fb
+add	edx, 0x10
+call	[edx]
+mov	edx, 0x80480fb
+add	edx, 0xc
+call	[edx]
+mov	edx, 0x80480fb
+add	edx, 0x14
+call	[edx]
+mov	edx, 0x80480fb
+add	edx, 0x4
+call	[edx]
+*/
+
+
+static const vmpa_t _white_list[] = {
+    0x80480fbull,
+    0x8048103ull,
+    0x804810bull,
+    0x8048107ull,
+    0x804810full,
+    0x80480ffull
+};
+
+static const size_t _white_list_count = 6;
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ref = espace de référencement global.                        *
+*                                                                             *
+*  Description : Initialise le greffon pour les bornes de routine.            *
+*                                                                             *
+*  Retour      : true.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool init_plugin(GObject *ref)
+{
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit une indication sur le type d'opération(s) menée(s).  *
+*                                                                             *
+*  Retour      : Description d'une action.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT PluginAction get_plugin_action(void)
+{
+    return PGA_CODE_PROCESS;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = représentation binaire à traiter.                   *
+*                action = action attendue.                                    *
+*                                                                             *
+*  Description : Exécute une action définie sur un binaire chargé.            *
+*                                                                             *
+*  Retour      : true si une action a été menée, false sinon.                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool execute_action_on_binary(GOpenidaBinary *binary, PluginAction action)
+{
+    bool result;                            /* Bilan à retourner           */
+    GRenderingLine *lines;                  /* Lignes désassemblées        */
+    GExeFormat *format;                     /* Format du binaire traité    */
+    vmpa_t start;                           /* Point de départ de l'action */
+
+
+
+    GRenderingOptions *options;
+    GRenderingLine *iter;
+
+
+    lines = g_openida_binary_get_lines(binary);
+
+
+
+
+    format = g_openida_binary_get_format(binary);
+
+    start = g_exe_format_get_entry_point(format);
+
+    result = register_white_list(binary);
+
+    result &= follow_flow_from_line(binary, start);
+
+
+    //follow_flow_from_line(binary, 0x0804810bull);
+
+
+
+
+
+    options = g_openida_binary_get_options(binary);
+
+    for (iter = lines; iter != NULL; iter = g_rendering_line_get_next_iter(lines, iter, NULL))
+    {
+
+        printf(" >>>>>> %c%c  ",
+               g_object_get_data(G_OBJECT(iter), "theseus_white") != NULL ? '!' : ' ',
+               g_object_get_data(G_OBJECT(iter), "theseus_done") != NULL ? '*' : ' ');
+        g_content_exporter_add_text(G_CONTENT_EXPORTER(iter), options, 0/*MRD_BLOCK*/, stdout);
+        fflush(stdout);
+        printf("\n");
+
+
+    }
+
+
+
+    //exit(-1);
+
+
+
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = représentation binaire à traiter.                   *
+*                                                                             *
+*  Description : Traite en premier lieu les adresses marquées "impératives".  *
+*                                                                             *
+*  Retour      : true si le déroulement s'est bien effectué, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool register_white_list(GOpenidaBinary *binary)
+{
+    bool result;                            /* Bilan à retourner           */
+    GRenderingLine *lines;                  /* Lignes désassemblées        */
+    size_t i;                               /* Boucle de parcours          */
+    GRenderingLine *target;                 /* Ligne à transformer ?       */
+    GRenderingLine *last;                   /* Nouvelle ligne principale   */
+    GRenderingLine *new;                    /* Nouvelles lignes de rendu   */
+
+    result = true;
+
+    lines = g_openida_binary_get_lines(binary);
+
+    for (i = 0; i < _white_list_count && result; i++)
+    {
+        target = g_rendering_line_find_by_address(lines, NULL, _white_list[i]);
+        target = g_rendering_line_loop_for_code(target, NULL);
+
+        new = disassemble_target_address(binary, target, _white_list[i]);
+
+        last = g_rendering_line_get_last_iter(new, NULL);
+        mark_line_as_done(last, true);
+
+        result = insert_new_lines_into_flow(binary, target, new);
+
+        result &= follow_flow_from_line(binary, _white_list[i]);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne de rendu à analyser.                            *
+*                                                                             *
+*  Description : Indique si une ligne peut faire l'objet d'un nouveau suivi.  *
+*                                                                             *
+*  Retour      : true si le suivi peut continuer, false sinon.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool can_line_be_followed(const GRenderingLine *line)
+{
+    bool result;                            /* Bilan d'analyse à renvoyer  */
+
+    result = true;
+
+    if (g_object_get_data(G_OBJECT(line), "theseus_done") != NULL)
+        result = (g_object_get_data(G_OBJECT(line), "theseus_white") != NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne de rendu à analyser.                            *
+*                                                                             *
+*  Description : Indique si une ligne a déjà été traitée lors d'un suivi.     *
+*                                                                             *
+*  Retour      : true si le suivi peut continuer, false sinon.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool can_line_be_processed(const GRenderingLine *line)
+{
+    return (g_object_get_data(G_OBJECT(line), "theseus_done") == NULL);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line  = ligne de rendu à traiter.                            *
+*                white = type de marquage à apposer (liste blanche ou normal).*
+*                                                                             *
+*  Description : Marque une ligne comme ayant été traitée.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void mark_line_as_done(GRenderingLine *line, bool white)
+{
+    if (white)
+        g_object_set_data(G_OBJECT(line), "theseus_white", line);
+    else
+        g_object_set_data(G_OBJECT(line), "theseus_done", line);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = représentation binaire à traiter.                   *
+*                start  = point de départ de la procédure.                    *
+*                                                                             *
+*  Description : Suit le flot d'exécution à partir d'un point donné.          *
+*                                                                             *
+*  Retour      : true si le déroulement s'est bien effectué, false sinon.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool follow_flow_from_line(GOpenidaBinary *binary, vmpa_t start)
+{
+    bool result;                            /* Bilan de opérations         */
+    GRenderingLine *lines;                  /* Lignes désassemblées        */
+    GRenderingLine *first;                  /* Première ligne à traiter    */
+    vmpa_t addr;                            /* Adresse référencée          */
+    GRenderingLine *new;                    /* Nouvelles lignes de rendu   */
+    GRenderingLine *iter;                   /* Boucle de parcours          */
+    GArchInstruction *instr;                /* Instruction à ausculter     */
+    InstructionLinkType type;               /* Type de référence           */
+    GRenderingLine *target;                 /* Ligne visée par la référence*/
+
+    lines = g_openida_binary_get_lines(binary);
+
+    first = g_rendering_line_find_by_address(lines, NULL, start);
+    first = g_rendering_line_loop_for_code(first, NULL);
+
+    if (!can_line_be_followed(first))
+        return true;
+
+    //if (start != 0x0804810bull) return true;
+
+    printf("###################################### Passage\n");
+
+    /* Alignement sur le point d'entrée */
+
+    result = true;
+
+    addr = get_rendering_line_address(first);
+
+    if (addr < start)
+    {
+        new = disassemble_target_address(binary, first, start);
+
+        result = insert_new_lines_into_flow(binary, target, new);
+
+        first = g_rendering_line_find_by_address(lines, NULL, start);
+
+        //return true;
+
+    }
+    else g_object_set_data(G_OBJECT(first), "theseus_done", binary);
+
+
+
+
+    printf("Analyse :: 0x%016llx\n", get_rendering_line_address(first));
+
+
+
+
+
+    /* Poursuite du suivi du flot... */
+
+    for (iter = g_rendering_line_get_next_iter(lines, first, NULL);
+         iter != NULL/* && result*/;
+         iter = g_rendering_line_get_next_iter(lines, iter, NULL))
+    {
+        /* On ne traite que du code ici ! */
+        if (!G_IS_CODE_LINE(iter)) continue;
+
+        /*
+        printf("testing... 0x%08llx => %d\n",
+               get_rendering_line_address(iter),
+               can_line_be_processed(iter));
+        */
+
+        if (!can_line_be_processed(iter))
+            break;
+
+        instr = g_code_line_get_instruction(G_CODE_LINE(iter));
+
+        /* Si le code n'es pas désassemblé ! */
+        if (G_IS_DB_INSTRUCTION(instr))
+        {
+            new = disassemble_target_address(binary, iter, get_rendering_line_address(iter));
+            result = insert_new_lines_into_flow(binary, iter, new);
+
+            if (!result)
+            {
+                mark_line_as_done(iter, false);
+                break;
+            }
+            else
+            {
+                iter = new;
+                mark_line_as_done(iter, false);
+
+                instr = g_code_line_get_instruction(G_CODE_LINE(iter));
+                if (!G_IS_DB_INSTRUCTION(instr)) break;
+
+            }
+
+        }
+        else mark_line_as_done(iter, false);
+
+        type = g_arch_instruction_get_link(instr, &addr);
+
+        if (get_rendering_line_address(iter) ==  0x0804811aull)
+            printf(" == got it !! ==\n");
+
+
+        switch (type)
+        {
+            case ILT_JUMP:
+            case ILT_JUMP_IF_FALSE:
+            case ILT_JUMP_IF_TRUE:
+                result = follow_flow_from_line(binary, addr);
+                break;
+
+           default:
+               break;
+
+        }
+
+        if (get_rendering_line_address(iter) ==  0x0804811aull)
+            printf(" == continue ? %d\n", result);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = représentation binaire à traiter.                   *
+*                old    = ligne contenant l'adresse visée à remplacer.        *
+*                target = adresse de la nouvelle instruction à voir.          *
+*                                                                             *
+*  Description : Désassemble une nouvelle instruction à partir d'une adresse. *
+*                                                                             *
+*  Retour      : Nouvelle(s) ligne(s) en place ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GRenderingLine *disassemble_target_address(GOpenidaBinary *binary, GRenderingLine *old, vmpa_t target)
+{
+    GRenderingLine *result;                 /* Lignes en place à renvoyer  */
+    GExeFormat *format;                     /* Format du binaire fourni    */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    GRenderingOptions *options;             /* Options de désassemblage    */
+    bin_t *data;                            /* Données binaires chargées   */
+    off_t length;                           /* Taille du code binaire      */
+    vmpa_t old_addr;                        /* Adresse de ligne à casser   */
+    off_t offset;                           /* Position dans le contenu    */
+    vmpa_t i;                               /* Boucle de parcours          */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    GRenderingLine *line;                   /* Nouvelle ligne de rendu     */
+
+    result = NULL;
+
+    format = g_openida_binary_get_format(binary);
+    proc = get_arch_processor_from_format(format);
+    options = g_openida_binary_get_options(binary);
+
+    data = g_openida_binary_get_data(binary, &length);
+
+    old_addr = get_rendering_line_address(old);
+    if (!g_exe_format_translate_address_into_offset(format, old_addr, &offset))
+        return NULL;
+
+    /* Si on doit laisser sur le carreau quelques octets perdus... */
+    for (i = 0; i < (target - old_addr); i++)
+    {
+        instr = g_db_instruction_new_from_data(data, &offset, length, 0/*base*/, proc);
+        g_arch_instruction_set_location(instr, 0/*base*/ + offset - 1, 1, old_addr + i);
+
+        line = g_code_line_new(old_addr + i, instr, options);
+        g_rendering_line_add_to_lines(&result, line);
+
+    }
+
+    /* Décodage des instructions */
+
+    instr = g_arch_processor_decode_instruction(proc, data,
+                                                &offset, length, 0/*offset*/, target);
+
+    line = g_code_line_new(target, instr, options);
+    g_rendering_line_add_to_lines(&result, line);
+
+    mark_line_as_done(line, false);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = représentation binaire à traiter.                   *
+*                old    = ancienne ligne, point de départ des remplacements.  *
+*                new    = nouvelle(s) ligne(s) de représentation.             *
+*                                                                             *
+*  Description : Insère dans le flux existant les nouvelles lignes crées.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool insert_new_lines_into_flow(GOpenidaBinary *binary, GRenderingLine *old, GRenderingLine *new)
+{
+    bool result;                            /* Bilan de opérations         */
+    GExeFormat *format;                     /* Format du binaire fourni    */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    GRenderingOptions *options;             /* Options de désassemblage    */
+    bin_t *data;                            /* Données binaires chargées   */
+    off_t length;                           /* Taille du code binaire      */
+    GRenderingLine **root;                  /* Racine des lignes de rendu  */
+    GRenderingLine *iter;                   /* Boucle de parcours          */
+    vmpa_t start;                           /* Adresse de début du bloc    */
+    vmpa_t end;                             /* Adresse de fin du bloc      */
+    vmpa_t max;                             /* Adresse de fin de ligne     */
+    vmpa_t i;                               /* Boucle de parcours          */
+    off_t offset;                           /* Position dans le contenu    */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    GRenderingLine *line;                   /* Nouvelle ligne de rendu     */
+    GRenderingLine *last;                   /* Dernière ligne à vérifier   */
+
+    format = g_openida_binary_get_format(binary);
+    proc = get_arch_processor_from_format(format);
+    options = g_openida_binary_get_options(binary);
+
+    data = g_openida_binary_get_data(binary, &length);
+
+    /* Etendue du bloc de remplacement */
+
+    iter = g_rendering_line_get_last_iter(new, NULL);
+
+    start = get_rendering_line_address(new);
+
+    end = get_rendering_line_address(iter);
+    end += get_rendering_line_length(iter) - 1;
+
+    /* Bourrage nécessaire ? */
+
+    root = g_openida_binary_get_lines_root(binary);
+
+    iter = g_rendering_line_find_by_address(*root, NULL, end);
+
+    max = get_rendering_line_address(iter);
+    max += get_rendering_line_length(iter);
+
+    for (i = end + 1; i < max; i++)
+    {
+        if (!g_exe_format_translate_address_into_offset(format, i, &offset))
+            /**
+             * Comme les adresses proviennent à l'origine de partie valide,
+             * on considère que l'appel est toujours un succès.
+             * Cela permet d'avoir deux bilan possible : procédure bien déroulée,
+             * ou bien remplacement impossible pour cause de place déjà prise.
+             */
+            /*return false*/;
+
+        instr = g_db_instruction_new_from_data(data, &offset, length, 0/*base*/, proc);
+        g_arch_instruction_set_location(instr, 0/*base*/ + offset - 1, 1, i);
+
+        line = g_code_line_new(i, instr, options);
+        g_rendering_line_add_to_lines(&new, line);
+
+    }
+
+    /* S'assure qu'on ne touche à rien de sacré */
+
+    result = true;
+
+    last = g_rendering_line_find_by_address(*root, NULL, end);
+
+    for (iter = g_rendering_line_find_by_address(*root, NULL, start);
+         iter != NULL && result;
+         iter = g_rendering_line_get_next_iter(*root, iter, last))
+    {
+        result = can_line_be_processed(iter);
+    }
+
+    /* Remplacement en bonne et due forme */
+
+    if (result)
+    {
+        g_rendering_line_remove_range(root, start, end);
+        g_rendering_line_insert_lines(root, &new);
+    }
+
+    return result;
+
+}
diff --git a/plugins/theseus/theseus.h b/plugins/theseus/theseus.h
new file mode 100644
index 0000000..2fa4ac1
--- /dev/null
+++ b/plugins/theseus/theseus.h
@@ -0,0 +1,49 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * theseus.h - prototypes pour la décompilation en fonction du flot d'exécution
+ *
+ * Copyright (C) 2010 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA 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.
+ *
+ *  OpenIDA 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_THESEUS_THESEUS_H
+#define _PLUGINS_THESEUS_THESEUS_H
+
+
+#include <glib-object.h>
+#include <gmodule.h>
+#include <stdbool.h>
+
+
+#include <analysis/binary.h>
+#include <plugins/plugin-def.h>
+
+
+
+/* Initialise le greffon pour les bornes de routine. */
+G_MODULE_EXPORT bool init_plugin(GObject *);
+
+/* Fournit une indication sur le type d'opération(s) menée(s). */
+G_MODULE_EXPORT PluginAction get_plugin_action(void);
+
+/* Exécute une action définie sur un binaire chargé. */
+G_MODULE_EXPORT bool execute_action_on_binary(GOpenidaBinary *, PluginAction);
+
+
+
+#endif  /* _PLUGINS_THESEUS_THESEUS_H */
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 66cc26d..c35118e 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -1220,6 +1220,25 @@ GRenderingOptions *g_openida_binary_get_options(const GOpenidaBinary *binary)
 *                                                                             *
 *  Paramètres  : binary = élément binaire à consulter.                        *
 *                                                                             *
+*  Description : Donne la racine des lignes de rendu issues du désassemblage. *
+*                                                                             *
+*  Retour      : Lieu d'enregistrement des lignes issues du désassemblage.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GRenderingLine **g_openida_binary_get_lines_root(const GOpenidaBinary *binary)
+{
+    return &binary->lines;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary = élément binaire à consulter.                        *
+*                                                                             *
 *  Description : Fournit les lignes de rendu issues du désassemblage.         *
 *                                                                             *
 *  Retour      : Lignes issues du désassemblage.                              *
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 533264b..f556c4a 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -98,6 +98,9 @@ GExeFormat *g_openida_binary_get_format(const GOpenidaBinary *);
 /* Fournit les options d'affichage définies pour le binaire. */
 GRenderingOptions *g_openida_binary_get_options(const GOpenidaBinary *);
 
+/* Donne la racine des lignes de rendu issues du désassemblage. */
+GRenderingLine **g_openida_binary_get_lines_root(const GOpenidaBinary *);
+
 /* Fournit les lignes de rendu issues du désassemblage. */
 GRenderingLine *g_openida_binary_get_lines(const GOpenidaBinary *);
 
diff --git a/src/analysis/line-int.h b/src/analysis/line-int.h
index e240815..38efeda 100644
--- a/src/analysis/line-int.h
+++ b/src/analysis/line-int.h
@@ -62,7 +62,9 @@ struct _GRenderingLine
 #define lines_list_prev_iter(iter, head) dl_list_prev_iter(iter, head, GRenderingLine, link)
 #define lines_list_add_before(new, head, pos) dl_list_add_before(new, head, pos, link)
 #define lines_list_add_tail(new, head) dl_list_add_tail(new, head, GRenderingLine, link)
+#define lines_list_del(item, head) dl_list_del(item, head, GRenderingLine, link)
 #define lines_list_for_each(pos, head) dl_list_for_each(pos, head, GRenderingLine, link)
+#define lines_list_for_each_safe(pos, head, next) dl_list_for_each_safe(pos, head, next, GRenderingLine, link)
 
 
 /* Ligne de représentation générique (classe) */
diff --git a/src/analysis/line.c b/src/analysis/line.c
index a3ba7a5..bb4188a 100644
--- a/src/analysis/line.c
+++ b/src/analysis/line.c
@@ -477,6 +477,69 @@ void g_rendering_line_insert_into_lines(GRenderingLine **lines, GRenderingLine *
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : lines = liste de lignes à compléter, ou NULL.                *
+*                new   = nouvelles lignes à intégrer à l'ensemble.            *
+*                                                                             *
+*  Description : Insère des lignes dans un ensemble existant.                 *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_rendering_line_insert_lines(GRenderingLine **lines, GRenderingLine **new)
+{
+    GRenderingLine *iter;                   /* Boucle de parcours          */
+    GRenderingLine *next;                   /* Ligne suivante à traiter    */
+
+    lines_list_for_each_safe(iter, new, next)
+    {
+        lines_list_del(iter, new);
+        g_rendering_line_insert_into_lines(lines, iter, true);
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : lines = liste de lignes à traiter.                           *
+*                start = borne inférieure de l'intervalle (incluse).          *
+*                end   = borne supérieure de l'intervalle (incluse).          *
+*                                                                             *
+*  Description : Supprime une série de lignes comprises dans un intervalle.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_rendering_line_remove_range(GRenderingLine **lines, vmpa_t start, vmpa_t end)
+{
+    GRenderingLine *first;                  /* Première ligne à traiter    */
+    GRenderingLine *last;                   /* Dernière ligne à traiter    */
+    GRenderingLine *iter;                   /* Boucle de parcours          */
+    GRenderingLine *next;                   /* Ligne suivante à traiter    */
+
+    first = g_rendering_line_find_by_address(*lines, NULL, start);
+    last = g_rendering_line_find_by_address(*lines, NULL, end);
+
+    for (iter = first; iter != NULL; iter = next)
+    {
+        next = g_rendering_line_get_next_iter(*lines, iter, last);
+
+        lines_list_del(iter, lines);
+        g_object_unref(G_OBJECT(iter));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : lines = liste de lignes de représentation à actualiser.      *
 *              : iter  = position actuelle dans la liste.                     *
 *                last  = dernière élément imposé du parcours ou NULL.         *
diff --git a/src/analysis/line.h b/src/analysis/line.h
index 5061dcd..fbc560f 100644
--- a/src/analysis/line.h
+++ b/src/analysis/line.h
@@ -122,6 +122,12 @@ void g_rendering_line_add_to_lines(GRenderingLine **, GRenderingLine *);
 /* Insère une ligne dans un ensemble existant.  */
 void g_rendering_line_insert_into_lines(GRenderingLine **, GRenderingLine *, bool);
 
+/* Insère des lignes dans un ensemble existant. */
+void g_rendering_line_insert_lines(GRenderingLine **, GRenderingLine **);
+
+/* Supprime une série de lignes comprises dans un intervalle. */
+void g_rendering_line_remove_range(GRenderingLine **, vmpa_t, vmpa_t);
+
 /* Fournit l'élement suivant un autre pour un parcours. */
 GRenderingLine *g_rendering_line_get_next_iter(GRenderingLine *, const GRenderingLine *, const GRenderingLine *);
 
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 1b47bd6..adbabd4 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -41,14 +41,11 @@ typedef enum _PluginAction
 
 
 
-struct _GPluginModule;
-
-
 /* Fournit une indication sur le type d'opération(s) menée(s). */
 typedef PluginAction (* get_plugin_action_fc) (void);
 
 /* Exécute une action définie sur un binaire chargé. */
-typedef bool (* execute_action_on_binary_fc) (struct _GPluginModule *, GOpenidaBinary *, PluginAction);
+typedef bool (* execute_action_on_binary_fc) (GOpenidaBinary *, PluginAction);
 
 
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index ed4c39d..42bef63 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -107,7 +107,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
     result->module = g_module_open(filename, G_MODULE_BIND_LAZY);
 
 
-#if 0
+#if 1
     if (!g_module_symbol(result->module, "get_plugin_action", (gpointer *)&__get_action))
     {
         printf("Err plugin get_action sym\n");
@@ -144,6 +144,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
     if (!result->init(ref))
         printf("Err loading pg\n");
+    else printf("Loaded '%s' : ok (%p)\n", filename, result);
 
     return result;
 
@@ -185,6 +186,6 @@ PluginAction g_plugin_module_get_action(const GPluginModule *plugin)
 
 bool g_plugin_module_execute_action_on_binary(const GPluginModule *plugin, GOpenidaBinary *binary, PluginAction action)
 {
-    return plugin->exec_on_bin(plugin, binary, action);
+    return plugin->exec_on_bin(binary, action);
 
 }
-- 
cgit v0.11.2-87-g4458