diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-09-11 20:40:24 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-09-11 20:40:24 (GMT) |
commit | 18648e4e8763a3bc005d6fae51eae3d1528d7d29 (patch) | |
tree | 05feca5b6c5575b2a048b60130e3207b9f2c355a /src/analysis/contents | |
parent | 9f8c79e3b272960b48bfd85a24f4b5cb5651df2d (diff) |
Created an interface from the original GBinContent object.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@576 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/contents')
-rwxr-xr-x | src/analysis/contents/Makefile.am | 16 | ||||
-rw-r--r-- | src/analysis/contents/file.c | 603 | ||||
-rw-r--r-- | src/analysis/contents/file.h | 58 |
3 files changed, 677 insertions, 0 deletions
diff --git a/src/analysis/contents/Makefile.am b/src/analysis/contents/Makefile.am new file mode 100755 index 0000000..e2eec74 --- /dev/null +++ b/src/analysis/contents/Makefile.am @@ -0,0 +1,16 @@ + +noinst_LTLIBRARIES = libanalysiscontents.la + +libanalysiscontents_la_SOURCES = \ + file.h file.c + +libanalysiscontents_la_LIBADD = + +libanalysiscontents_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/analysis/contents/file.c b/src/analysis/contents/file.c new file mode 100644 index 0000000..eb0d488 --- /dev/null +++ b/src/analysis/contents/file.c @@ -0,0 +1,603 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * file.c - chargement de données binaires à partir d'un fichier + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 "file.h" + + +#include <assert.h> +#include <fcntl.h> +#include <malloc.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> + + +#include "../content-int.h" + + + +/* Contenu de données binaires issues d'un fichier (instance) */ +struct _GFileContent +{ + GObject parent; /* A laisser en premier */ + + bin_t *data; /* Contenu binaire représenté */ + mrange_t range; /* Couverture du binaire */ + + GChecksum *checksum; /* Calcul de l'empreinte */ + bool cs_computed; /* Calcul effectué ? */ + +}; + +/* Contenu de données binaires issues d'un fichier (classe) */ +struct _GFileContentClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des contenus de données binaires. */ +static void g_file_content_class_init(GFileContentClass *); + +/* Initialise une instance de contenu de données binaires. */ +static void g_file_content_init(GFileContent *); + +/* Procède à l'initialisation de l'interface de lecture. */ +static void g_file_content_interface_init(GBinContentInterface *); + +/* Supprime toutes les références externes. */ +static void g_file_content_dispose(GFileContent *); + +/* Procède à la libération totale de la mémoire. */ +static void g_file_content_finalize(GFileContent *); + +/* Fournit une empreinte unique (SHA256) pour les données. */ +static const gchar *g_file_content_get_checksum(GFileContent *); + +/* Détermine le nombre d'octets lisibles. */ +static phys_t g_file_content_compute_size(const GFileContent *); + +/* Donne accès à une portion des données représentées. */ +static const bin_t *g_file_content_get_raw_access(const GFileContent *, vmpa2t *, phys_t); + +/* Fournit une portion des données représentées. */ +static bool g_file_content_read_raw(const GFileContent *, vmpa2t *, phys_t, bin_t *); + +/* Lit un nombre non signé sur quatre bits. */ +static bool g_file_content_read_u4(const GFileContent *, vmpa2t *, bool *, uint8_t *); + +/* Lit un nombre non signé sur un octet. */ +static bool g_file_content_read_u8(const GFileContent *, vmpa2t *, uint8_t *); + +/* Lit un nombre non signé sur deux octets. */ +static bool g_file_content_read_u16(const GFileContent *, vmpa2t *, SourceEndian, uint16_t *); + +/* Lit un nombre non signé sur quatre octets. */ +static bool g_file_content_read_u32(const GFileContent *, vmpa2t *, SourceEndian, uint32_t *); + +/* Lit un nombre non signé sur huit octets. */ +static bool g_file_content_read_u64(const GFileContent *, vmpa2t *, SourceEndian, uint64_t *); + + + +/* Indique le type défini par la GLib pour les contenus de données. */ +G_DEFINE_TYPE_WITH_CODE(GFileContent, g_file_content, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_BIN_CONTENT, g_file_content_interface_init)) + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contenus de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_class_init(GFileContentClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_file_content_dispose; + object->finalize = (GObjectFinalizeFunc)g_file_content_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : content = instance à initialiser. * +* * +* Description : Initialise une instance de contenu de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_init(GFileContent *content) +{ + content->checksum = g_checksum_new(G_CHECKSUM_SHA256); + assert(content->checksum != NULL); + + content->cs_computed = false; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de lecture. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_interface_init(GBinContentInterface *iface) +{ + iface->get_checksum = (get_checksum_fc)g_file_content_get_checksum; + + iface->compute_size = (compute_size_fc)g_file_content_compute_size; + + iface->get_raw_access = (get_raw_access_fc)g_file_content_get_raw_access; + + iface->read_raw = (read_raw_fc)g_file_content_read_raw; + iface->read_u4 = (read_u4_fc)g_file_content_read_u4; + iface->read_u8 = (read_u8_fc)g_file_content_read_u8; + iface->read_u16 = (read_u16_fc)g_file_content_read_u16; + iface->read_u32 = (read_u32_fc)g_file_content_read_u32; + iface->read_u64 = (read_u64_fc)g_file_content_read_u64; + +} + + +/****************************************************************************** +* * +* Paramètres : content = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_dispose(GFileContent *content) +{ + g_checksum_free(content->checksum); + + G_OBJECT_CLASS(g_file_content_parent_class)->dispose(G_OBJECT(content)); + +} + + +/****************************************************************************** +* * +* Paramètres : content = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_file_content_finalize(GFileContent *content) +{ + if (content->data != NULL) + free(content->data); + + G_OBJECT_CLASS(g_file_content_parent_class)->finalize(G_OBJECT(content)); + +} + + +/****************************************************************************** +* * +* Paramètres : filename = chemin d'accès au fichier à charger. * +* * +* Description : Charge en mémoire le contenu d'un fichier donné. * +* * +* Retour : Représentation de contenu à manipuler ou NULL en cas d'échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinContent *g_file_content_new(const char *filename) +{ + GFileContent *result; /* Structure à retourner */ + int fd; /* Descripteur du fichier */ + struct stat info; /* Informations sur le fichier */ + int ret; /* Bilan d'un appel */ + void *content; /* Contenu brut du fichier */ + vmpa2t base; /* Localisation des données */ + + /* Récupération des données */ + + fd = open(filename, O_RDONLY); + if (fd == -1) + { + perror("open"); + goto gbcnff_error; + } + + ret = fstat(fd, &info); + if (ret == -1) + { + close(fd); + perror("fstat"); + goto gbcnff_error; + } + + content = mmap(NULL, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (content == MAP_FAILED) + { + close(fd); + perror("mmap"); + goto gbcnff_error; + } + + /* Constitution du contenu officiel */ + + result = g_object_new(G_TYPE_FILE_CONTENT, NULL); + + result->data = (bin_t *)malloc(info.st_size); + memcpy(result->data, content, info.st_size); + + munmap(content, info.st_size); + close(fd); + + init_vmpa(&base, 0, VMPA_NO_VIRTUAL); + init_mrange(&result->range, &base, info.st_size); + + return G_BIN_CONTENT(result); + + gbcnff_error: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* * +* Description : Fournit une empreinte unique (SHA256) pour les données. * +* * +* Retour : Chaîne représentant l'empreinte du contenu binaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const gchar *g_file_content_get_checksum(GFileContent *content) +{ + if (!content->cs_computed) + { + g_checksum_reset(content->checksum); + + g_checksum_update(content->checksum, content->data, get_mrange_length(&content->range)); + + content->cs_computed = true; + + } + + return g_checksum_get_string(content->checksum); + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* * +* Description : Détermine le nombre d'octets lisibles. * +* * +* Retour : Quantité représentée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static phys_t g_file_content_compute_size(const GFileContent *content) +{ + phys_t result; /* Quantité trouvée à retourner*/ + + result = get_mrange_length(&content->range); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* length = quantité d'octets à lire. * +* * +* Description : Donne accès à une portion des données représentées. * +* * +* Retour : Pointeur vers les données à lire ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const bin_t *g_file_content_get_raw_access(const GFileContent *content, vmpa2t *addr, phys_t length) +{ + phys_t offset; /* Emplacement de départ */ + + offset = get_phy_addr(addr); + + if (offset == VMPA_NO_PHYSICAL) + return NULL; + + if ((offset + length) >= get_mrange_length(&content->range)) + return NULL; + + advance_vmpa(addr, length); + + return &content->data[offset]; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* length = quantité d'octets à lire. * +* out = réceptacle disponible pour ces données. [OUT] * +* * +* Description : Fournit une portion des données représentées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_raw(const GFileContent *content, vmpa2t *addr, phys_t length, bin_t *out) +{ + bool result; /* Bilan à remonter */ + const bin_t *data; /* Pointeur vers données utiles*/ + + data = g_file_content_get_raw_access(content, addr, length); + + if (data != NULL) + { + result = true; + memcpy(out, data, length); + } + else + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* low = position éventuelle des 4 bits visés. [OUT] * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur quatre bits. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_u4(const GFileContent *content, vmpa2t *addr, bool *low, uint8_t *val) +{ + bool result; /* Bilan de lecture à renvoyer */ + phys_t pos; /* Tête de lecture courante */ + phys_t length; /* Taille de la surface dispo. */ + + pos = get_phy_addr(addr); + + if (pos == VMPA_NO_PHYSICAL) + return false; + + length = get_mrange_length(&content->range); + + result = read_u4(val, content->data, &pos, length, low); + + if (result) + advance_vmpa(addr, pos - get_phy_addr(addr)); + + return result; + +} + + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur un octet. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_u8(const GFileContent *content, vmpa2t *addr, uint8_t *val) +{ + bool result; /* Bilan de lecture à renvoyer */ + phys_t pos; /* Tête de lecture courante */ + phys_t length; /* Taille de la surface dispo. */ + + pos = get_phy_addr(addr); + + if (pos == VMPA_NO_PHYSICAL) + return false; + + length = get_mrange_length(&content->range); + + result = read_u8(val, content->data, &pos, length); + + if (result) + advance_vmpa(addr, pos - get_phy_addr(addr)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur deux octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_u16(const GFileContent *content, vmpa2t *addr, SourceEndian endian, uint16_t *val) +{ + bool result; /* Bilan de lecture à renvoyer */ + phys_t pos; /* Tête de lecture courante */ + phys_t length; /* Taille de la surface dispo. */ + + pos = get_phy_addr(addr); + + if (pos == VMPA_NO_PHYSICAL) + return false; + + length = get_mrange_length(&content->range); + + result = read_u16(val, content->data, &pos, length, endian); + + if (result) + advance_vmpa(addr, pos - get_phy_addr(addr)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur quatre octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_u32(const GFileContent *content, vmpa2t *addr, SourceEndian endian, uint32_t *val) +{ + bool result; /* Bilan de lecture à renvoyer */ + phys_t pos; /* Tête de lecture courante */ + phys_t length; /* Taille de la surface dispo. */ + + pos = get_phy_addr(addr); + + if (pos == VMPA_NO_PHYSICAL) + return false; + + length = get_mrange_length(&content->range); + + result = read_u32(val, content->data, &pos, length, endian); + + if (result) + advance_vmpa(addr, pos - get_phy_addr(addr)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu binaire à venir lire. * +* addr = position de la tête de lecture. * +* endian = ordre des bits dans la source. * +* val = lieu d'enregistrement de la lecture. [OUT] * +* * +* Description : Lit un nombre non signé sur huit octets. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_file_content_read_u64(const GFileContent *content, vmpa2t *addr, SourceEndian endian, uint64_t *val) +{ + bool result; /* Bilan de lecture à renvoyer */ + phys_t pos; /* Tête de lecture courante */ + phys_t length; /* Taille de la surface dispo. */ + + pos = get_phy_addr(addr); + + if (pos == VMPA_NO_PHYSICAL) + return false; + + length = get_mrange_length(&content->range); + + result = read_u64(val, content->data, &pos, length, endian); + + if (result) + advance_vmpa(addr, pos - get_phy_addr(addr)); + + return result; + +} diff --git a/src/analysis/contents/file.h b/src/analysis/contents/file.h new file mode 100644 index 0000000..2e3cfef --- /dev/null +++ b/src/analysis/contents/file.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * file.h - prototypes pour le chargement de données binaires à partir d'un fichier + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * 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 _ANALYSIS_CONTENTS_FILE_H +#define _ANALYSIS_CONTENTS_FILE_H + + +#include <glib-object.h> + + +#include "../content.h" + + + +#define G_TYPE_FILE_CONTENT (g_file_content_get_type()) +#define G_FILE_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_FILE_CONTENT, GFileContent)) +#define G_IS_FILE_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_FILE_CONTENT)) +#define G_FILE_CONTENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FILE_CONTENT, GFileContentClass)) +#define G_IS_FILE_CONTENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FILE_CONTENT)) +#define G_FILE_CONTENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FILE_CONTENT, GFileContentClass)) + + +/* Contenu de données binaires issues d'un fichier (instance) */ +typedef struct _GFileContent GFileContent; + +/* Contenu de données binaires issues d'un fichier (classe) */ +typedef struct _GFileContentClass GFileContentClass; + + +/* Indique le type défini par la GLib pour les contenus de données. */ +GType g_file_content_get_type(void); + +/* Charge en mémoire le contenu d'un fichier donné. */ +GBinContent *g_file_content_new(const char *); + + + +#endif /* _ANALYSIS_CONTENTS_FILE_H */ |