diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-08-02 22:25:15 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-08-02 22:25:15 (GMT) |
commit | 8c84aa2e41305fd388b7dac49f29ae17ee0554fb (patch) | |
tree | 52830a7d896e2d9272e7c71677c72ce9d62cf26c /src/format | |
parent | 30fc2ba22b469e38bc40e47f517988e418c178f3 (diff) |
Introduced symbols dedicated to strings.
Diffstat (limited to 'src/format')
-rw-r--r-- | src/format/Makefile.am | 1 | ||||
-rw-r--r-- | src/format/format.c | 91 | ||||
-rw-r--r-- | src/format/format.h | 3 | ||||
-rw-r--r-- | src/format/strsym.c | 474 | ||||
-rw-r--r-- | src/format/strsym.h | 80 | ||||
-rw-r--r-- | src/format/symbol.h | 5 |
6 files changed, 558 insertions, 96 deletions
diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 504055d..8a47b82 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -12,6 +12,7 @@ libformat_la_SOURCES = \ format.h format.c \ preload-int.h \ preload.h preload.c \ + strsym.h strsym.c \ symiter.h symiter.c \ symbol-int.h \ symbol.h symbol.c diff --git a/src/format/format.c b/src/format/format.c index 449f0f0..91cca37 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -25,7 +25,6 @@ #include <assert.h> -#include <ctype.h> #include <malloc.h> #include <string.h> @@ -957,96 +956,6 @@ static void g_binary_format_delete_duplicated_symbols(GBinFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* addr = adresse liée à la chaîne à traiter. * -* length = taille de la chaîne à représenter. * -* * -* Description : Construit une désignation pour chaîne de caractères. * -* * -* Retour : Chaîne de caractères à libérer de la mémoire. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char *create_string_label(GBinFormat *format, const vmpa2t *addr, size_t length) -{ - char *result; /* Nouvelle chaîne à retourner */ - vmpa2t pos; /* Tête de lecture modifiable */ - const bin_t *base; /* Contenu complet et original */ - unsigned int wc; /* Nombre de mots rencontrés */ - size_t iter; /* Tête d'écriture de recopie */ - size_t i; /* Boucle de parcours */ - bool empty; /* Base de l'étiquette vide ? */ - GBinSymbol *found; /* Symbole similaire trouvé */ - VMPA_BUFFER(last_sfx); /* Dernier suffixe à intégrer */ - - copy_vmpa(&pos, addr); - - base = g_binary_content_get_raw_access(format->content, &pos, length); - - if (base == NULL) - return NULL; - - result = (char *)calloc(length + 5 + VMPA_MAX_LEN + 1, sizeof(char)); - - wc = 0; - - iter = 0; - - for (i = 0; i < length; i++) - { - if (isalnum(base[i])) result[iter++] = tolower(base[i]); - - else if (iter > 0) - { - if (result[iter - 1] != '_') wc++; - - if (wc == 3) break; - - if (result[iter - 1] != '_') result[iter++] = '_'; - - } - - } - - /* Détermination du suffixe suffisant */ - - empty = (iter == 0); - - if (iter > 0 && result[iter - 1] != '_') result[iter++] = '_'; - - strcpy(&result[iter], "str"); - iter += 3; - - found = NULL; - - if (empty || g_binary_format_find_symbol_by_label(format, result, &found)) - { - if (found != NULL) - g_object_unref(G_OBJECT(found)); - - if (iter > 0 && result[iter - 1] != '_') result[iter++] = '_'; - - assert(has_phys_addr(addr) || has_virt_addr(addr)); - - /* TODO : use_phy_instead_of_virt */ - if (has_virt_addr(addr)) - vmpa2_virt_to_string(addr, MDS_UNDEFINED, last_sfx, NULL); - else - vmpa2_phys_to_string(addr, MDS_UNDEFINED, last_sfx, NULL); - - strcpy(&result[iter], last_sfx); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * * label = étiquette à retrouver lors des recherches. * * symbol = éventuel symbole trouvé à déréfenrencer. [OUT] * * * diff --git a/src/format/format.h b/src/format/format.h index 372b3b0..a9152ba 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -132,9 +132,6 @@ bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); /* Retire un symbole de la collection du format binaire. */ void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *); -/* Construit une désignation pour chaîne de caractères. */ -char *create_string_label(GBinFormat *, const vmpa2t *, size_t); - /* Recherche le symbole correspondant à une étiquette. */ bool g_binary_format_find_symbol_by_label(GBinFormat *, const char *, GBinSymbol **); diff --git a/src/format/strsym.c b/src/format/strsym.c new file mode 100644 index 0000000..b709b93 --- /dev/null +++ b/src/format/strsym.c @@ -0,0 +1,474 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strsym.c - gestion des chaînes dans un binaire + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "strsym.h" + + +#include <assert.h> +#include <ctype.h> +#include <malloc.h> +#include <string.h> + + +#include "symbol-int.h" +#include "../common/alloc.h" + + + +/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */ + + +/* Symbole pour chaîne de caractères (instance) */ +struct _GStrSymbol +{ + GBinSymbol parent; /* A laisser en premier */ + + StringEncodingType encoding; /* Encodage de la chaîne liée */ + + union + { + GBinContent *content; /* Conteneur d'origine */ + char *utf8; /* Données utilisables */ + + }; + + bool has_content; /* Choix dans l'union */ + +}; + +/* Symbole pour chaîne de caractères (classe) */ +struct _GStrSymbolClass +{ + GBinSymbolClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des chaînes de caractères. */ +static void g_string_symbol_class_init(GStrSymbolClass *); + +/* Initialise une instance de chaîne de caractères. */ +static void g_string_symbol_init(GStrSymbol *); + +/* Supprime toutes les références externes. */ +static void g_string_symbol_dispose(GStrSymbol *); + +/* Procède à la libération totale de la mémoire. */ +static void g_string_symbol_finalize(GStrSymbol *); + + + +/* ---------------------------------------------------------------------------------- */ +/* VITRINE POUR CHAINES DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un symbole d'exécutable. */ +/* +G_DEFINE_TYPE_WITH_CODE(GStrSymbol, g_string_symbol, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_string_symbol_interface_init)); +*/ +G_DEFINE_TYPE(GStrSymbol, g_string_symbol, G_TYPE_BIN_SYMBOL); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des chaînes de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_class_init(GStrSymbolClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_string_symbol_dispose; + object->finalize = (GObjectFinalizeFunc)g_string_symbol_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance à initialiser. * +* * +* Description : Initialise une instance de chaîne de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_init(GStrSymbol *symbol) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_dispose(GStrSymbol *symbol) +{ + if (symbol->has_content) + g_object_unref(G_OBJECT(symbol->content)); + + G_OBJECT_CLASS(g_string_symbol_parent_class)->dispose(G_OBJECT(symbol)); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_string_symbol_finalize(GStrSymbol *symbol) +{ + G_OBJECT_CLASS(g_string_symbol_parent_class)->finalize(G_OBJECT(symbol)); + +} + + +/****************************************************************************** +* * +* Paramètres : format = format binaire reconnu. * +* range = espace couvert par le nouveau symbole. * +* encoding = encodage de la chaîne de caractères à représenter.* +* * +* Description : Crée un nouveau symbole pour chaîne de caractères. * +* * +* Retour : Adresse de l'instance mise en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *g_string_symbol_new_read_only(GBinFormat *format, const mrange_t *range, StringEncodingType encoding) +{ + GStrSymbol *result; /* Nouveau symbole à renvoyer */ + GBinSymbol *parent; /* Type d'instance parent */ + vmpa2t pos; /* Tête de lecture modifiable */ + phys_t length; /* Taille de la chaîne */ + const char *base; /* Contenu complet et original */ + + result = g_object_new(G_TYPE_STR_SYMBOL, NULL); + + parent = G_BIN_SYMBOL(result); + + g_binary_symbol_set_range(parent, range); + g_binary_symbol_set_target_type(parent, STP_RO_STRING); + + result->encoding = encoding; + + result->content = g_binary_format_get_content(format); + result->has_content = true; + + switch (encoding) + { + case SET_ASCII: + break; + + case SET_UTF_8: + case SET_MUTF_8: + + copy_vmpa(&pos, get_mrange_addr(range)); + length = get_mrange_length(range); + + base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length); + + if (!g_utf8_validate(base, -1, NULL)) + result->encoding = SET_ASCII; + + break; + + case SET_GUESS: + + copy_vmpa(&pos, get_mrange_addr(range)); + length = get_mrange_length(range); + + base = (const char *)g_binary_content_get_raw_access(result->content, &pos, length); + + if (g_str_is_ascii(base)) + result->encoding = SET_ASCII; + + else if (g_utf8_validate(base, -1, NULL)) + result->encoding = SET_UTF_8; + + else + result->encoding = SET_ASCII; + + break; + + } + + return G_BIN_SYMBOL(result); + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = symbole à venir consulter. * +* * +* Description : Fournit l'encodage d'une chaîne de caractères. * +* * +* Retour : Type d'encodage utilisé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *symbol) +{ + StringEncodingType result; /* Type à retourner */ + + result = symbol->encoding; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : symbol = chaîne de caractères à consulter. * +* format = informations chargées à consulter. * +* * +* Description : Construit une désignation pour chaîne de caractères. * +* * +* Retour : Bilan de l'opération de mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_string_symbol_build_label(GStrSymbol *symbol, GBinFormat *format) +{ + const mrange_t *range; /* Couverture du symbole */ + vmpa2t pos; /* Tête de lecture modifiable */ + phys_t length; /* Taille de la chaîne */ + const char *base; /* Contenu complet et original */ + size_t allocated; /* Taille réservée */ + char *label; /* Etiquette à constituer */ + size_t cur; /* Point d'écriture courant */ + unsigned int wc; /* Nombre de mots rencontrés */ + size_t i; /* Boucle de parcours #1 */ + char *iter; /* Boucle de parcours #2 */ + gunichar c; /* Caractère unicode */ + gchar *converted; /* Caractère converti */ + glong size; /* Taille du caractère */ + bool empty; /* Base de l'étiquette vide ? */ + GBinSymbol *found; /* Symbole similaire trouvé */ + VMPA_BUFFER(last_sfx); /* Dernier suffixe à intégrer */ + + /* Base de décision */ + + range = g_binary_symbol_get_range(G_BIN_SYMBOL(symbol)); + + copy_vmpa(&pos, get_mrange_addr(range)); + + switch (g_binary_symbol_get_target_type(G_BIN_SYMBOL(symbol))) + { + case STP_RO_STRING: + length = get_mrange_length(range); + base = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, length); + break; + + case STP_DYN_STRING: + base = symbol->utf8; + length = strlen((char *)base); + break; + + default: + assert(false); + base = NULL; + break; + + } + + if (base == NULL) + return false; + + /* Phase de constitution */ + + allocated = length + 5 + VMPA_MAX_LEN + 1; + label = (char *)malloc(allocated * sizeof(char)); + + cur = 0; + + wc = 0; + + /** + * Version simple et rapide. + */ + if (symbol->encoding == SET_ASCII || g_str_is_ascii(base)) + { + for (i = 0; i < length; i++) + { + if (isalnum(base[i])) label[cur++] = tolower(base[i]); + + else if (cur > 0) + { + if (label[cur - 1] != '_') wc++; + + if (wc == 3) break; + + if (label[cur - 1] != '_') label[cur++] = '_'; + + } + + } + + } + + /** + * Version complète. + */ + else + { + for (iter = g_utf8_offset_to_pointer(base, 0); + iter != NULL; + iter = g_utf8_find_next_char(iter, NULL)) + { + c = g_utf8_get_char_validated(iter, -1); + + /** + * Si le caractère n'est pas valide (chaîne chiffrée ?)... + */ + if (c == (gunichar)-1 || c == (gunichar)-2) + break; + + if (c == '\0') + break; + + else if (g_unichar_isalnum(c)) + { + c = g_unichar_tolower(c); + + converted = g_ucs4_to_utf8(&c, 1, NULL, &size, NULL); + + label = ensure_allocation_size(label, &allocated, cur + size); + + memcpy(label + cur, converted, size); + + g_free(converted); + + cur += size; + + } + + else if (cur > 0) + { + if (label[cur - 1] != '_') wc++; + + if (wc == 3) break; + + if (label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + } + + } + + } + + empty = (cur == 0); + + if (!empty && label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + label = ensure_allocation_size(label, &allocated, cur + 4); + + strcpy(label + cur, "str"); + cur += 3; + + /* Détermination du suffixe suffisant */ + + found = NULL; + + if (empty || g_binary_format_find_symbol_by_label(format, label, &found)) + { + if (found != NULL) + g_object_unref(G_OBJECT(found)); + + if (label[cur - 1] != '_') + { + label = ensure_allocation_size(label, &allocated, cur + 1); + label[cur++] = '_'; + } + + copy_vmpa(&pos, get_mrange_addr(range)); + + assert(has_phys_addr(&pos) || has_virt_addr(&pos)); + + if (has_virt_addr(&pos)) + vmpa2_virt_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL); + else + vmpa2_phys_to_string(&pos, MDS_UNDEFINED, last_sfx, NULL); + + label = ensure_allocation_size(label, &allocated, cur + strlen(last_sfx) + 1); + + strcpy(label + cur, last_sfx); + + } + + /* Application */ + + g_binary_symbol_set_alt_label(G_BIN_SYMBOL(symbol), label); + + free(label); + + return true; + +} diff --git a/src/format/strsym.h b/src/format/strsym.h new file mode 100644 index 0000000..e827e6a --- /dev/null +++ b/src/format/strsym.h @@ -0,0 +1,80 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * strsym.h - prototypes pour la gestion des chaînes dans un binaire + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_STRSYM_H +#define _FORMAT_STRSYM_H + + +#include <glib-object.h> + + +#include "format.h" +#include "symbol.h" + + + +/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */ + + +/* Types de chaînes */ +typedef enum _StringEncodingType +{ + SET_ASCII, /* Format brut */ + SET_UTF_8, /* Format UTF-8 */ + SET_MUTF_8, /* Format UTF-8 modifié */ + + SET_GUESS, /* Détection automatique */ + +} StringEncodingType; + + +#define G_TYPE_STR_SYMBOL g_string_symbol_get_type() +#define G_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_string_symbol_get_type(), GStrSymbol)) +#define G_IS_STR_SYMBOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_string_symbol_get_type())) +#define G_STR_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_STR_SYMBOL, GStrSymbolClass)) +#define G_IS_STR_SYMBOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_STR_SYMBOL)) +#define G_STR_SYMBOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_STR_SYMBOL, GStrSymbolClass)) + + +/*/* Symbole pour chaîne de caractères (instance) */ +typedef struct _GStrSymbol GStrSymbol; + +/* Symbole pour chaîne de caractères (classe) */ +typedef struct _GStrSymbolClass GStrSymbolClass; + + +/* Indique le type défini pour un symbole d'exécutable. */ +GType g_string_symbol_get_type(void); + +/* Crée un nouveau symbole pour chaîne de caractères. */ +GBinSymbol *g_string_symbol_new_read_only(GBinFormat *, const mrange_t *, StringEncodingType); + +/* Fournit l'encodage d'une chaîne de caractères. */ +StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *); + +/* Construit une désignation pour chaîne de caractères. */ +bool g_string_symbol_build_label(GStrSymbol *, GBinFormat *); + + + +#endif /* _FORMAT_STRSYM_H */ diff --git a/src/format/symbol.h b/src/format/symbol.h index 13747d4..577a6a0 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -43,8 +43,8 @@ typedef enum _SymbolType STP_CODE_LABEL, /* Renvoi au sein de code */ STP_OBJECT, /* Objet quelconque */ STP_ENTRY_POINT, /* Morceau de code en entrée */ - STP_STRING, /* Chaîne de caractères */ - STP_RO_STRING, /* Chaîne de caractères */ + STP_RO_STRING, /* Chaîne d'origine */ + STP_DYN_STRING, /* Chaîne créée ex-nihilo */ STP_COUNT @@ -57,6 +57,7 @@ typedef enum _SymbolStatus SSS_INTERNAL, /* Visibilité nulle */ SSS_EXPORTED, /* Disponibilité extérieure */ SSS_IMPORTED, /* Besoin interne */ + SSS_DYNAMIC, /* Création durant l'analyse */ SSS_COUNT |