From 4ad9e532a78401f787f0a8a6742095512b520488 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 15 Mar 2009 13:38:22 +0000 Subject: 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 --- ChangeLog | 32 +++++++++++ src/analysis/line.c | 107 +++++++++++++++++++++++++++++++++++- src/analysis/line.h | 25 ++++++++- src/arch/processor.c | 4 +- src/binary.c | 3 +- src/format/elf/Makefile.am | 2 +- src/format/elf/e_elf.c | 131 +++++++++++++++++++++++++++++++++++++++++++- src/format/elf/elf-int.h | 2 +- src/format/exe_format-int.h | 4 ++ src/format/exe_format.c | 30 ++++++++++ src/format/exe_format.h | 6 ++ src/gtksnippet.c | 3 +- 12 files changed, 336 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 30e3904..b94f587 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2009-03-15 Cyrille Bagard + + * 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 * 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; -- cgit v0.11.2-87-g4458