diff options
Diffstat (limited to 'src/analysis')
| -rwxr-xr-x | src/analysis/Makefile.am | 11 | ||||
| -rw-r--r-- | src/analysis/binary.c | 593 | ||||
| -rw-r--r-- | src/analysis/binary.h | 73 | ||||
| -rw-r--r-- | src/analysis/line.c | 13 | 
4 files changed, 683 insertions, 7 deletions
| diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am index e5f7689..8d986a1 100755 --- a/src/analysis/Makefile.am +++ b/src/analysis/Makefile.am @@ -1,7 +1,8 @@ -lib_LIBRARIES = libanalysis.a +lib_LTLIBRARIES = libanalysis.la -libanalysis_a_SOURCES =					\ +libanalysis_la_SOURCES =				\ +	binary.h binary.c					\  	line.h line.c						\  	line-int.h							\  	line_code.h line_code.c				\ @@ -10,10 +11,12 @@ libanalysis_a_SOURCES =					\  	prototype.h prototype.c				\  	variable.h variable.c -libanalysis_a_CFLAGS = $(AM_CFLAGS) +libanalysis_la_LDFLAGS = $(LIBGTK_LIBS)	$(LIBXML_LIBS) \ +	-L../common/.libs -lcommon			\ +	-L../format/.libs -lformat -INCLUDES = $(LIBGTK_CFLAGS) +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)  AM_CPPFLAGS =  diff --git a/src/analysis/binary.c b/src/analysis/binary.c new file mode 100644 index 0000000..95b24b1 --- /dev/null +++ b/src/analysis/binary.c @@ -0,0 +1,593 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * binary.c - traitement des flots de code binaire + * + * Copyright (C) 2008 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 "binary.h" + + +#include <fcntl.h> +#include <malloc.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + + +#include "line_code.h" +#include "line_comment.h" +#include "line_prologue.h" +#include "prototype.h" +#include "../arch/processor.h" + + +#include "../format/dbg_format.h" +#include "../format/exe_format.h" + + + + +#ifndef _ +#   define _(str) str +#endif + + + +extern bool find_line_info(const uint8_t *content, off_t *size); + + + + +/* Description d'un fichier binaire */ +struct _openida_binary +{ +    char *filename;                         /* Fichier chargé en mémoire   */ + +    off_t bin_length;                       /* Taille des données brutes   */ +    uint8_t *bin_data;                      /* Données binaires brutes     */ + +    exe_format *format;                     /* Format du binaire           */ +    asm_processor *proc;                    /* Architecture du binaire     */ + +    GRenderingLine *lines;                  /* Lignes de rendu en place    */ +    disass_options options;                 /* Options de désassemblage    */ + +}; + + +/* Charge en mémoire le contenu d'un fichier à partir d'XML. */ +openida_binary *load_binary_file_from_xml(xmlXPathObjectPtr); + +/* Charge en mémoire le contenu d'un fichier. */ +uint8_t *map_binary_file(const char *, off_t *); + +/* Construit la description d'introduction du désassemblage. */ +GRenderingLine *build_binary_prologue(const char *, const uint8_t *, off_t); + +/* Procède au désassemblage basique d'un contenu binaire. */ +void disassemble_openida_binary(openida_binary *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : filename = nom du fichier à charger.                         * +*                                                                             * +*  Description : Charge en mémoire le contenu d'un fichier.                   * +*                                                                             * +*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +openida_binary *load_binary_file(const char *filename) +{ +    openida_binary *result;                 /* Adresse à retourner         */ + +    result = (openida_binary *)calloc(1, sizeof(openida_binary)); + +    result->filename = strdup(filename); + +    result->bin_data = map_binary_file(filename, &result->bin_length); +    if (result->bin_data == NULL) goto lbf_error; + +    result->format = load_new_exe_format(result->bin_data, result->bin_length); +    if (result->format == NULL) goto lbf_error; + + +    result->proc = create_processor(); + + +    result->options.show_address = true; +    result->options.show_code = true; + +    result->options.format = result->format; +    result->options.proc = result->proc; + +    disassemble_openida_binary(result); + +    return result; + + lbf_error: + +    unload_binary_file(result); + +    return NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : xpathObj = point de lecture de tous les éléments.            * +*                                                                             * +*  Description : Charge en mémoire le contenu d'un fichier à partir d'XML.    * +*                                                                             * +*  Retour      : Adresse de la représentation ou NULL en cas d'échec.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +openida_binary *load_binary_file_from_xml(xmlXPathObjectPtr xpathObj) +{ +    openida_binary *result;                 /* Adresse à retourner         */ + +    int i; + +    result = (openida_binary *)calloc(1, sizeof(openida_binary)); + +    for (i = 0; i < XPATH_OBJ_NODES_COUNT(xpathObj); i++) +        if (xmlStrEqual(NODE_FROM_PATH_OBJ(xpathObj, i)->name, BAD_CAST "Filename")) +            result->filename = qck_get_node_text_value(NODE_FROM_PATH_OBJ(xpathObj, i)); + + + + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = élément binaire à supprimer de la mémoire.          * +*                                                                             * +*  Description : Décharge de la mémoire le contenu d'un fichier.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void unload_binary_file(openida_binary *binary) +{ +    free(binary->filename); + +    free(binary); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = élément binaire à consulter.                        * +*                                                                             * +*  Description : Fournit le fichier correspondant à l'élément binaire.        * +*                                                                             * +*  Retour      : Nom de fichier avec chemin absolu.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const char *openida_binary_get_filename(const openida_binary *binary) +{ +    return binary->filename; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = élément binaire à consulter.                        * +*                                                                             * +*  Description : Fournit une description humaine d'un élément binaire.        * +*                                                                             * +*  Retour      : Chaîne de caractères humainenement lisible de représentation.* +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +const char *openida_binary_to_string(const openida_binary *binary) +{ +    return binary->filename; + +} + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = élément binaire à consulter.                        * +*                                                                             * +*  Description : Fournit les lignes de rendu issues du désassemblage.         * +*                                                                             * +*  Retour      : Lignes issues du désassemblage.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRenderingLine *get_openida_binary_lines(const openida_binary *binary) +{ +    return binary->lines; + +} + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : xpathCtx = contexte à utiliser pour mener les parcours.      * +*                base     = première partie de l'expression XPath d'accès.    * +*                index    = indice de la élément dans la liste des voisins.   * +*                                                                             * +*  Description : Lit un élément binaire depuis un fichier XML.                * +*                                                                             * +*  Retour      : Représentation mise en place à libérer de la mémoire.        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +openida_binary *read_openida_binary_from_xml(xmlXPathContextPtr xpathCtx, const char *base, unsigned int index) +{ +    openida_binary *result;                 /* Représentation à retourner  */ +    size_t expr_len;                        /* Taille d'une expression     */ +    char *expr;                             /* Chemin XPath reconstitué    */ +    xmlXPathObjectPtr xpathObj;             /* Cible d'une recherche       */ +    char *value;                            /* Type d'élément rencontré    */ +    size_t sub_expr_len;                    /* Taille d'une expression #2  */ +    char *sub_expr;                         /* Chemin XPath reconstitué #2 */ +    int i;                                  /* Boucle de parcours          */ + +    result = NULL; + +    /* S'occupe en premier lieu du niveau courant */ + +    expr_len = strlen(base) + strlen("/*[position()=") + strlen("4294967295") /* UINT_MAX */ + strlen("]") + 1; + +    expr = (char *)calloc(expr_len, sizeof(char)); +    snprintf(expr, expr_len, "%s/*[position()=%u]", base, index); + +    xpathObj = get_node_xpath_object(xpathCtx, expr); + +    value = qck_get_node_prop_value(NODE_FROM_PATH_OBJ(xpathObj, 0), "type"); + +    xmlXPathFreeObject(xpathObj); + +    if (value == NULL) goto robfx_err1; + +    /* Raffinement au second passage */ + +    sub_expr_len = expr_len + strlen("/*"); +    sub_expr = (char *)calloc(sub_expr_len, sizeof(char)); +    snprintf(sub_expr, sub_expr_len, "%s/*", expr); + +    xpathObj = get_node_xpath_object(xpathCtx, sub_expr); + +    if (strcmp(value, "file") == 0) result = load_binary_file_from_xml(xpathObj); + +    xmlXPathFreeObject(xpathObj); + +    free(sub_expr); + + robfx_err1: + +    free(expr); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = élément binaire à traiter.                          * +*                writer = rédacteur dédié à l'écriture.                       * +*                                                                             * +*  Description : Ecrit une sauvegarde du binaire dans un fichier XML.         * +*                                                                             * +*  Retour      : true si l'opération a bien tourné, false sinon.              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool write_openida_binary_to_xml(const openida_binary *binary, xmlTextWriterPtr writer) +{ +    bool result;                            /* Bilan à faire remonter      */ + +    result = open_xml_element(writer, "Binary"); + +    result &= write_xml_attribute(writer, "type", "file"); + +    result &= write_xml_element_with_content(writer, "Filename", "%s", binary->filename); + +    result &= close_xml_element(writer); + +    return result; + +} + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : filename = nom du fichier à charger.                         * +*                length   = taille des données mises en mémoire. [OUT]        * +*                                                                             * +*  Description : Charge en mémoire le contenu d'un fichier.                   * +*                                                                             * +*  Retour      : Adresse du contenu binaire ou NULL en cas d'échec.           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +uint8_t *map_binary_file(const char *filename, off_t *length) +{ +    uint8_t *result;                        /* Données à retourner         */ +    int fd;                                 /* Fichier ouvert en lecture   */ +    struct stat info;                       /* Informations sur le fichier */ +    int ret;                                /* Bilan d'un appel            */ + +    fd = open(filename, 0, O_RDONLY); +    if (fd == -1) +    { +        perror("open()"); +        return NULL; +    } + +    ret = fstat(fd, &info); +    if (ret == -1) +    { +        perror("fstat()"); +        close(fd); +        return NULL; +    } + +    *length = info.st_size; + +    result = (uint8_t *)mmap(NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0); +    if (result == MAP_FAILED) +    { +        perror("mmap()"); +        result = NULL; +    } + +    ret = close(fd); +    if (ret == -1) +        perror("close()"); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : filename = nom du fichier chargé.                            * +*                data     = données en mémoire pour l'empreinte.              * +*                length   = quantité de données à prendre en compte.          * +*                                                                             * +*  Description : Construit la description d'introduction du désassemblage.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data, off_t length) +{ +    GRenderingLine *result;                 /* Contenu à renvoyer          */ +    size_t len;                             /* Taille du texte             */ +    char *content;                          /* Contenu textuel d'une ligne */ +    GRenderingLine *line;                   /* Représentation à ajouter    */ +    GChecksum *checksum;                    /* Calcul de l'empreinte       */ +    const gchar *hex;                       /* Valeur hexadécimale du SHA  */ + +    result = NULL;/* FIXME DL_LIST_HEAD_INIT(  **/ + +    line = g_prologue_line_new("Disassembly generated by OpenIDA"); +    g_rendering_line_add_to_lines(&result, line); + +    line = g_prologue_line_new("OpenIDA is free software - © 2008-2009 Cyrille Bagard"); +    g_rendering_line_add_to_lines(&result, line); + +    line = g_prologue_line_new(""); +    g_rendering_line_add_to_lines(&result, line); + +    /* Fichier */ + +    len = strlen(_("File: ")) + strlen(filename); +    content = (char *)calloc(len + 1, sizeof(char)); + +    snprintf(content, len + 1, "%s%s", _("File: "), filename); + +    line = g_prologue_line_new(content); +    g_rendering_line_add_to_lines(&result, line); + +    free(content); + +    /* Checksum SHA256 */ + +    checksum = g_checksum_new(G_CHECKSUM_SHA256); + +    g_checksum_update(checksum, data, length); +    hex = g_checksum_get_string(checksum); + +    len = strlen(_("Sha256: ")) + strlen(hex); +    content = (char *)calloc(len + 1, sizeof(char)); + +    snprintf(content, len + 1, "%s%s", _("Sha256: "), hex); + +    g_checksum_free(checksum); + +    line = g_prologue_line_new(content); +    g_rendering_line_add_to_lines(&result, line); + +    free(content); + +    line = g_prologue_line_new(""); +    g_rendering_line_add_to_lines(&result, line); + +    line = g_prologue_line_new(""); +    g_rendering_line_add_to_lines(&result, line); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : binary = binaire dont le contenu est à analyser.             * +*                                                                             * +*  Description : Procède au désassemblage basique d'un contenu binaire.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void disassemble_openida_binary(openida_binary *binary) +{ +    asm_instr *instr; + +    bin_routine **routines;                 /* Liste des routines trouvées */ +    size_t routines_count;                  /* Nombre de ces routines      */ + +    bin_part **parts; +    size_t parts_count; + + + +    GRenderingLine *line; + + +    off_t start; +    off_t pos; +    off_t len; + +    uint64_t base = 0; +    uint64_t offset = 0; + +    size_t i; + +    size_t k; + +    uint64_t routine_offset;                /* Point de départ de routine  */ +    char *routine_desc;                     /* Prototype d'une routine     */ + + + + +    binary->lines = build_binary_prologue(binary->filename, binary->bin_data, binary->bin_length); + + +    routines = get_all_exe_routines(binary->format, &routines_count); + + +    parts = get_elf_default_code_parts(binary->format, &parts_count); +    qsort(parts, parts_count, sizeof(bin_part *), compare_bin_parts); + + + + +    for (i = 0; i < parts_count; i++) +    { +        get_bin_part_values(parts[i], &pos, &len, &base); + +        /* Décodage des instructions */ + +        start = pos; +        pos = 0; + +        while (pos < len) +        { +            offset = base + pos; + + +            instr = decode_instruction(binary->proc, &binary->bin_data[start], &pos, len, start, offset); + + +            line = g_code_line_new(offset, instr, &binary->options); +            g_rendering_line_add_to_lines(&binary->lines, line); + +        } + +        /* Ajout des prototypes de fonctions */ + +        for (k = 0; k < routines_count; k++) +        { +            routine_offset = get_binary_routine_offset(routines[k]); + +            if (!(base <= routine_offset && routine_offset < (base + len))) continue; + +            routine_desc = routine_to_string(routines[k]); + +            line = g_comment_line_new(routine_offset, routine_desc, &binary->options); +            g_rendering_line_insert_into_lines(&binary->lines, line, true); + +            free(routine_desc); + +        } + +    } + + + + + + +    line = g_rendering_line_find_by_offset(binary->lines, get_exe_entry_point(binary->format)); +    g_rendering_line_add_flag(line, RLF_ENTRY_POINT); + + + + +} diff --git a/src/analysis/binary.h b/src/analysis/binary.h new file mode 100644 index 0000000..69da2a7 --- /dev/null +++ b/src/analysis/binary.h @@ -0,0 +1,73 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * binary.h - prototypes pour le traitement des flots de code binaire + * + * Copyright (C) 2008 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 _BINARY_H +#define _BINARY_H + + +#include <stdbool.h> + + +#include "line.h" +#include "../xml.h" + + + +/* Description d'un fichier binaire */ +typedef struct _openida_binary openida_binary; + + +/* Charge en mémoire le contenu d'un fichier. */ +openida_binary *load_binary_file(const char *); + +/* Décharge de la mémoire le contenu d'un fichier. */ +void unload_binary_file(openida_binary *); + +/* Fournit une description humaine d'un élément binaire. */ +const char *openida_binary_to_string(const openida_binary *); + +/* Fournit le fichier correspondant à l'élément binaire. */ +const char *openida_binary_get_filename(const openida_binary *); + +/* Fournit les lignes de rendu issues du désassemblage. */ +GRenderingLine *get_openida_binary_lines(const openida_binary *); + + + +/* Lit un élément binaire depuis un fichier XML. */ +openida_binary *read_openida_binary_from_xml(xmlXPathContextPtr, const char *, unsigned int); + +/* Ecrit une sauvegarde du binaire dans un fichier. */ +bool write_openida_binary_to_xml(const openida_binary *, xmlTextWriterPtr); + + + + + + + + + + + +#endif  /* _BINARY_H */ diff --git a/src/analysis/line.c b/src/analysis/line.c index 4fc0ac5..bba601c 100644 --- a/src/analysis/line.c +++ b/src/analysis/line.c @@ -39,7 +39,7 @@  /* FIXME */ -extern GtkWidget *mywid; +//extern GtkWidget *mywid; @@ -96,9 +96,15 @@ static void g_rendering_line_class_init(GRenderingLineClass *klass)  static void g_rendering_line_init(GRenderingLine *line)  { +    GdkScreen *screen; +    PangoContext *context; +      DL_LIST_ITEM_INIT(&line->link); -    line->layout = gtk_widget_create_pango_layout(mywid, NULL); +    screen = gdk_screen_get_default(); +    context = gdk_pango_context_get_for_screen(screen); + +    line->layout = pango_layout_new(context);      line->get_bin_len = NULL;      line->refresh_markup = NULL; @@ -230,6 +236,7 @@ RenderingLineFlag g_rendering_line_get_flags(const GRenderingLine *line)  void g_rendering_line_draw(GRenderingLine *line, GdkDrawable *drawable, GdkGC *gc, gint x0, gint x1, gint y, gint h)  { +#if 0      GdkPixbuf *pixbuf;                      /* Données utiles au dessin    */      gdk_draw_layout(drawable, gc, x1, y, line->layout); @@ -268,7 +275,7 @@ void g_rendering_line_draw(GRenderingLine *line, GdkDrawable *drawable, GdkGC *g          g_object_unref(pixbuf);      } - +#endif  } | 
