diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2009-03-15 13:38:22 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2009-03-15 13:38:22 (GMT) | 
| commit | 4ad9e532a78401f787f0a8a6742095512b520488 (patch) | |
| tree | 2b71914a52fc930be78939362b16756efe9caa68 | |
| parent | a2b767b244e03f00c6a987bbd9872796ed385f47 (diff) | |
Avoided to crash when analysing crackmes such as grainne.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@55 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
| -rw-r--r-- | ChangeLog | 32 | ||||
| -rw-r--r-- | src/analysis/line.c | 107 | ||||
| -rw-r--r-- | src/analysis/line.h | 25 | ||||
| -rw-r--r-- | src/arch/processor.c | 4 | ||||
| -rw-r--r-- | src/binary.c | 3 | ||||
| -rw-r--r-- | src/format/elf/Makefile.am | 2 | ||||
| -rw-r--r-- | src/format/elf/e_elf.c | 131 | ||||
| -rw-r--r-- | src/format/elf/elf-int.h | 2 | ||||
| -rw-r--r-- | src/format/exe_format-int.h | 4 | ||||
| -rw-r--r-- | src/format/exe_format.c | 30 | ||||
| -rw-r--r-- | src/format/exe_format.h | 6 | ||||
| -rw-r--r-- | src/gtksnippet.c | 3 | 
12 files changed, 336 insertions, 13 deletions
| @@ -1,3 +1,35 @@ +2009-03-15  Cyrille Bagard <nocbos@gmail.com> + +	* src/analysis/line.c: +	* src/analysis/line.h: +	Add flags to lines and draw them in the margin if needed. Find lines by +	their offset. + +	* src/arch/processor.c: +	Typo. + +	* src/binary.c: +	Specify the entry point for rendering. + +	* src/format/elf/e_elf.c: +	Handle some corrupted fields in the ELF header (sizes and quantities of +	the section and program (!?) entries). Rely on program header to provide +	code to analyse if none is found. + +	* src/format/elf/elf-int.h: +	Fix the ELF_PHDR macro (. -> ()->). + +	* src/format/elf/Makefile.am: +	Add LIBGTK_CFLAGS to INCLUDES in order to be able to print log messages. + +	* src/format/exe_format.c: +	* src/format/exe_format.h: +	* src/format/exe_format-int.h: +	Give the entry point of a loaded program. + +	* src/gtksnippet.c: +	Update a call to draw_rendering_line(). +  2009-03-14  Cyrille Bagard <nocbos@gmail.com>  	* configure.ac: diff --git a/src/analysis/line.c b/src/analysis/line.c index f5f3d9c..62acb8e 100644 --- a/src/analysis/line.c +++ b/src/analysis/line.c @@ -58,6 +58,7 @@ struct _rendering_line      uint64_t offset;                        /* Position en mémoire/physique*/      RenderingLineType type;                 /* Type de représentation      */ +    RenderingLineFlag flags;                /* Extension d'informations    */      PangoLayout *layout;                    /* Moteur de rendu du code/txt */ @@ -169,6 +170,63 @@ void init_rendering_line(rendering_line *line)  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : line = ligne dont les informations sont à mettre à jour.     * +*                flag = extension d'information à ajouter.                    * +*                                                                             * +*  Description : Ajoute une information supplémentaire à une ligne.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void add_rendering_line_flag(rendering_line *line, RenderingLineFlag flag) +{ +    line->flags |= flag; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : line = ligne dont les informations sont à mettre à jour.     * +*                flag = extension d'information à retirer.                    * +*                                                                             * +*  Description : Retire une information supplémentaire sur d'une ligne.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void remove_rendering_line_flag(rendering_line *line, RenderingLineFlag flag) +{ +    line->flags &= ~flag; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : line = ligne dont les informations sont à mettre à jour.     * +*                                                                             * +*  Description : Fournit les informations supplémentaires d'une ligne.        * +*                                                                             * +*  Retour      : Extensions d'informations courantes.                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +RenderingLineFlag get_rendering_line_flags(const rendering_line *line) +{ +    return line->flags; + +} @@ -236,6 +294,30 @@ void insert_line_into_rendering_lines(rendering_line **lines, rendering_line *li  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : lines  = liste de lignes à parcourir.                        * +*                offset = position en mémoire ou physique à chercher.         * +*                                                                             * +*  Description : Recherche une ligne d'après sa position en mémoire/physique. * +*                                                                             * +*  Retour      : Ligne représentant l'adresse donnée, NULL si aucune trouvée. * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +rendering_line *find_offset_in_rendering_lines(const rendering_line **lines, uint64_t offset) +{ +    rendering_line *result; + +    dl_list_for_each(result, DLL_HCAST(lines), rendering_line *) +        if (result->offset == offset) break; + +    return result; + +} +  /****************************************************************************** @@ -313,8 +395,10 @@ void get_rendering_line_size(rendering_line *line, int *width, int *height)  *  Paramètres  : line     = adresse de la structure à représenter.            *  *                drawable = support de rendu pour le dessin.                  *  *                gc       = contexte graphique à utiliser.                    * -*                x        = abscisse de la zone de rendu.                     * +*                x0       = abscisse de la zone de rendu (marge).             * +*                x1       = abscisse de la zone de rendu (texte).             *  *                y        = ordonnée de la zone de rendu.                     * +*                h        = hauteur réservée pour la ligne.                   *  *                                                                             *  *  Description : Procède à l'initialisation des bases d'une représentation.   *  *                                                                             * @@ -324,9 +408,26 @@ void get_rendering_line_size(rendering_line *line, int *width, int *height)  *                                                                             *  ******************************************************************************/ -void draw_rendering_line(rendering_line *line, GdkDrawable *drawable, GdkGC *gc, gint x, gint y) +void draw_rendering_line(rendering_line *line, GdkDrawable *drawable, GdkGC *gc, gint x0, gint x1, gint y, gint h)  { -    gdk_draw_layout(drawable, gc, x, y, line->layout); +    GdkPixbuf *pixbuf;                      /* Données utiles au dessin    */ + +    gdk_draw_layout(drawable, gc, x1, y, line->layout); + +    if (line->flags & RLF_ENTRY_POINT) +        pixbuf = gtk_widget_render_icon(mywid, "gtk-go-forward", GTK_ICON_SIZE_MENU, NULL); + +    else pixbuf = NULL; + +    if (pixbuf != NULL) +    { +        gdk_draw_pixbuf(drawable, gc, pixbuf, 0, 0, x0, y, +                        gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), +                        GDK_RGB_DITHER_NORMAL, 0, 0); + +        g_object_unref(pixbuf); + +    }  } diff --git a/src/analysis/line.h b/src/analysis/line.h index b0635bf..bb628b6 100644 --- a/src/analysis/line.h +++ b/src/analysis/line.h @@ -43,6 +43,15 @@ typedef enum _RenderingLineType  } RenderingLineType; +/* Image à afficher en marge de ligne */ +typedef enum _RenderingLineFlag +{ +    RLF_NONE            = (0 << 0),         /* Ligne commune               */ +    RLF_ENTRY_POINT     = (1 << 0),         /* Point d'entrée du prgm.     */ +    RLF_BREAK_POINT     = (1 << 1)          /* Point d'arrêt               */ + +} RenderingLineFlag; +  /* Passage de paramètres compact */  typedef struct _disass_options  { @@ -60,6 +69,17 @@ typedef struct _disass_options  typedef struct _rendering_line rendering_line; +/* Ajoute une information supplémentaire à une ligne. */ +void add_rendering_line_flag(rendering_line *, RenderingLineFlag); + +/* Retire une information supplémentaire d'une ligne. */ +void remove_rendering_line_flag(rendering_line *, RenderingLineFlag); + +/* Fournit les informations supplémentaires d'une ligne. */ +RenderingLineFlag get_rendering_line_flags(const rendering_line *); + + +  /* Ajoute une ligne à un ensemble existant. */  void add_line_to_rendering_lines(rendering_line **, rendering_line *); @@ -67,6 +87,9 @@ void add_line_to_rendering_lines(rendering_line **, rendering_line *);  /* Insère une ligne dans un ensemble existant.  */  void insert_line_into_rendering_lines(rendering_line **, rendering_line *, bool); +/* Recherche une ligne d'après sa position en mémoire/physique. */ +rendering_line *find_offset_in_rendering_lines(const rendering_line **, uint64_t); +  /* Met à jour la nombre d'octets maximale par instruction. */ @@ -79,7 +102,7 @@ void set_rendering_line_max_binary_len(rendering_line *, off_t);  void get_rendering_line_size(rendering_line *, int *, int *);  /* Procède à l'initialisation des bases d'une représentation. */ -void draw_rendering_line(rendering_line *, GdkDrawable *, GdkGC *, gint, gint); +void draw_rendering_line(rendering_line *, GdkDrawable *, GdkGC *, gint, gint, gint, gint); diff --git a/src/arch/processor.c b/src/arch/processor.c index 71cdfba..d367949 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -65,14 +65,14 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of      result = proc->fetch_instr(proc, data, pos, len, offset); -#define NULL ((void *)0) +#define NULL ((void *)0)    /* FIXME */      if (result == NULL)      {          *pos = old_pos; -        printf("err while decoding opcode 0x%0hhx at 0x%08llx\n", data[*pos], offset); +        printf("err while decoding opcode 0x%02hhx at 0x%08llx\n", data[*pos], offset);          result = create_db_instruction(data, pos, len);      } diff --git a/src/binary.c b/src/binary.c index 5093335..e43d644 100644 --- a/src/binary.c +++ b/src/binary.c @@ -566,7 +566,8 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2) - +    line = find_offset_in_rendering_lines(lines, get_exe_entry_point(format)); +    add_rendering_line_flag(line, RLF_ENTRY_POINT);      gtk_snippet_set_rendering_lines(snippet, lines); diff --git a/src/format/elf/Makefile.am b/src/format/elf/Makefile.am index 03ebed2..663194e 100644 --- a/src/format/elf/Makefile.am +++ b/src/format/elf/Makefile.am @@ -11,7 +11,7 @@ libformatelf_a_SOURCES =				\  libformatelf_a_CFLAGS = $(AM_CFLAGS) -INCLUDES =  +INCLUDES = $(LIBGTK_CFLAGS)  AM_CPPFLAGS =  diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c index 91e0403..1a1fe8d 100644 --- a/src/format/elf/e_elf.c +++ b/src/format/elf/e_elf.c @@ -32,6 +32,18 @@  #include "section.h"  #include "strings.h"  #include "symbol.h" +#include "../../panel/log.h" + + + + +#define _(str) str + + + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +uint64_t get_elf_entry_point(const elf_format *); + @@ -101,6 +113,7 @@ elf_format *load_elf(const uint8_t *content, off_t length)      EXE_FORMAT(result)->content = content;      EXE_FORMAT(result)->length = length; +    EXE_FORMAT(result)->get_entry_point = (get_entry_point_fc)get_elf_entry_point;      EXE_FORMAT(result)->get_def_parts = (get_def_parts_fc)get_elf_default_code_parts;      EXE_FORMAT(result)->find_section = (find_section_fc)find_elf_section_content_by_name;      EXE_FORMAT(result)->get_symbols = (get_symbols_fc)get_elf_symbols; @@ -110,7 +123,66 @@ elf_format *load_elf(const uint8_t *content, off_t length)      memcpy(&result->header, content, sizeof(Elf32_Ehdr)); -    result->is_32b = true; + +    /* TODO : endian */ + + +    /* Vérification des tailles d'entrée de table */ +    switch (result->header.e_ident[EI_CLASS]) +    { +        case ELFCLASS32: + +            if (result->header.e_phentsize != sizeof(Elf32_Phdr)) +            { +                log_variadic_message(LMT_BAD_BINARY, _("Corrupted program header size (%hu); fixed !"), +                                     result->header.e_phentsize); +                result->header.e_phentsize = sizeof(Elf32_Phdr); +            } + +            if (result->header.e_shentsize != sizeof(Elf32_Shdr)) +            { +                log_variadic_message(LMT_BAD_BINARY, _("Corrupted section header size (%hu); fixed !"), +                                     result->header.e_shentsize); +                result->header.e_shentsize = sizeof(Elf32_Shdr); +            } + +            break; + +        case ELFCLASS64: + +            if (result->header.e_phentsize != sizeof(Elf64_Phdr)) +            { +                log_variadic_message(LMT_BAD_BINARY, _("Corrupted program header size (%hu); fixed !"), +                                     result->header.e_phentsize); +                result->header.e_phentsize = sizeof(Elf64_Phdr); +            } + +            if (result->header.e_shentsize != sizeof(Elf64_Shdr)) +            { +                log_variadic_message(LMT_BAD_BINARY, _("Corrupted section header size (%hu); fixed !"), +                                     result->header.e_shentsize); +                result->header.e_shentsize = sizeof(Elf64_Shdr); +            } + +            break; + +        default: +            log_variadic_message(LMT_BAD_BINARY, ("Invalid ELF class '%hhu'"), +                                 result->header.e_ident[EI_CLASS]); +            break; + +    } + + +    /* FIXME : à améliorer */ +    if ((result->header.e_shnum * result->header.e_shentsize) >= length) +    { +        log_variadic_message(LMT_BAD_BINARY, ("Suspicious section table (bigger than the binary !) ; reset !")); +        result->header.e_shnum = 0; +    } + + +    result->is_32b = (result->header.e_ident[EI_CLASS] == ELFCLASS32);      for (i = 0; i < result->header.e_phnum; i++) @@ -141,6 +213,12 @@ elf_format *load_elf(const uint8_t *content, off_t length)      return result; + lelf: + +    /* TODO */ + +    return NULL; +  } @@ -150,6 +228,25 @@ elf_format *load_elf(const uint8_t *content, off_t length)  /******************************************************************************  *                                                                             *  *  Paramètres  : format = informations chargées à consulter.                  * +*                                                                             * +*  Description : Fournit l'adresse mémoire du point d'entrée du programme.    * +*                                                                             * +*  Retour      : Adresse de mémoire.                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +uint64_t get_elf_entry_point(const elf_format *format) +{ +    return format->header.e_entry; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = informations chargées à consulter.                  *  *                count  = quantité de zones listées. [OUT]                    *  *                                                                             *  *  Description : Fournit les références aux zones de code à analyser.         * @@ -168,7 +265,8 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)      off_t size;                             /* Taille de la partie         */      uint64_t voffset;                       /* Adresse virtuelle éventuelle*/      int i;                                  /* Boucle de parcours          */ -    Elf_Shdr shdr;                          /* En-tête de programme ELF    */ +    Elf_Shdr shdr;                          /* En-tête de section ELF      */ +    Elf_Phdr phdr;                          /* En-tête de programme ELF    */      result = NULL;      *count = 0; @@ -231,7 +329,7 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)          for (i = 0; i < format->header.e_shnum; i++)          {              offset = format->header.e_shoff + format->header.e_shentsize * i; -            if ((offset + format->header.e_shentsize) >= EXE_FORMAT(format)->length) break; +            if ((offset + format->header.e_shentsize) >= EXE_FORMAT(format)->length) continue;              memcpy(&shdr, &EXE_FORMAT(format)->content[offset], format->header.e_shentsize); @@ -252,6 +350,33 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)          } +    /* En désespoir de cause, on se rabbat sur les parties de programme directement */ + +    if (*count == 0) +        for (i = 0; i < format->header.e_phnum; i++) +        { +            offset = format->header.e_phoff + format->header.e_phentsize * i; +            if ((offset + format->header.e_phentsize) >= EXE_FORMAT(format)->length) continue; + +            memcpy(&phdr, &EXE_FORMAT(format)->content[offset], format->header.e_phentsize); + +            if (ELF_PHDR(format, &phdr, p_flags) & PF_X) +            { +                part = create_bin_part(); + +                /* TODO : nom */ + +                set_bin_part_values(part, ELF_PHDR(format, &phdr, p_offset), +                                    ELF_PHDR(format, &phdr, p_filesz), +                                    ELF_PHDR(format, &phdr, p_vaddr)); + +                result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *)); +                result[*count - 1] = part; + +            } + +        } +      return result;  } diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h index 0931654..4ee3a08 100644 --- a/src/format/elf/elf-int.h +++ b/src/format/elf/elf-int.h @@ -83,7 +83,7 @@ typedef union _Elf_Phdr  } Elf_Phdr; -#define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? hdr.header32.fld : hdr.header64.fld) +#define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? (hdr)->header32.fld : (hdr)->header64.fld)  /* Entrée de la table de relocalisation */ diff --git a/src/format/exe_format-int.h b/src/format/exe_format-int.h index a882891..3bba821 100644 --- a/src/format/exe_format-int.h +++ b/src/format/exe_format-int.h @@ -48,6 +48,9 @@ struct _bin_part +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +typedef uint64_t (* get_entry_point_fc) (const exe_format *); +  /* Fournit les références aux zones de code à analyser. */  typedef bin_part ** (* get_def_parts_fc) (const exe_format *, size_t *); @@ -73,6 +76,7 @@ struct _exe_format      const uint8_t *content;                 /* Contenu binaire à étudier   */      off_t length;                           /* Taille de ce contenu        */ +    get_entry_point_fc get_entry_point;     /* Obtention du point d'entrée */      get_def_parts_fc get_def_parts;         /* Liste des parties de code   */      find_section_fc find_section;           /* Recherche d'une section     */      get_symbols_fc get_symbols;             /* Liste des symboles présents */ diff --git a/src/format/exe_format.c b/src/format/exe_format.c index be0e1f1..89b0b3b 100644 --- a/src/format/exe_format.c +++ b/src/format/exe_format.c @@ -316,6 +316,36 @@ const uint8_t *get_exe_content(const exe_format *format, off_t *length) + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = informations chargées à consulter.                  * +*                                                                             * +*  Description : Fournit l'adresse mémoire du point d'entrée du programme.    * +*                                                                             * +*  Retour      : Adresse de mémoire.                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +uint64_t get_exe_entry_point(const exe_format *format) +{ +    return format->get_entry_point(format); + +} + + + + + + + +  /******************************************************************************  *                                                                             *  *  Paramètres  : format  = description de l'exécutable à consulter.           * diff --git a/src/format/exe_format.h b/src/format/exe_format.h index 48cb989..efacfe2 100644 --- a/src/format/exe_format.h +++ b/src/format/exe_format.h @@ -111,6 +111,12 @@ typedef enum _ResolvedType  /* Fournit une référence vers le contenu binaire analysé. */  const uint8_t *get_exe_content(const exe_format *, off_t *); + +/* Fournit l'adresse mémoire du point d'entrée du programme. */ +uint64_t get_exe_entry_point(const exe_format *); + + +  /* Recherche une section donnée au sein de binaire. */  bool find_exe_section(const exe_format *, const char *, off_t *, off_t *, uint64_t *); diff --git a/src/gtksnippet.c b/src/gtksnippet.c index 989e22b..bd5b3df 100644 --- a/src/gtksnippet.c +++ b/src/gtksnippet.c @@ -413,7 +413,8 @@ gtk_snippet_paint(GtkSnippet *snippet)      dl_list_for_each(/**/liter, snippet->lines, rendering_line *)      {          draw_rendering_line(liter, GDK_DRAWABLE(widget->window), snippet->gc, -                            2 * MARGIN_SPACE + snippet->line_height, y0); +                            MARGIN_SPACE, 2 * MARGIN_SPACE + snippet->line_height, +                            y0, snippet->line_height);          y0 += snippet->line_height; | 
