/* Chrysalide - Outil d'analyse de fichiers binaires
* file.h - prototypes pour la prise en charge des binaires sous forme de fichier
*
* Copyright (C) 2012-2013 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 .
*/
#include "file.h"
#include
#include
#include
#include
#include
#include "../binary-int.h"
#include "../../common/extstr.h"
#include "../../core/processors.h"
#include "../../gui/panels/log.h"
/* Description de fichier binaire (instance) */
struct _GFileBinary
{
GLoadedBinary parent; /* A laisser en premier */
char *filename; /* Fichier chargé en mémoire */
};
/* Description de fichier binaire (classe) */
struct _GFileBinaryClass
{
GLoadedBinaryClass parent; /* A laisser en premier */
};
/* Initialise la classe des descriptions de fichier binaire. */
static void g_file_binary_class_init(GFileBinaryClass *);
/* Initialise une description de fichier binaire. */
static void g_file_binary_init(GFileBinary *);
/* Procède à la libération totale de la mémoire. */
static void g_file_binary_finalize(GFileBinary *);
/* Ecrit une sauvegarde du binaire dans un fichier XML. */
static bool g_file_binary_save(const GFileBinary *, xmlDocPtr, xmlXPathContextPtr, const char *);
/* Fournit le nom associé à l'élément binaire. */
static const char *g_file_binary_get_name(const GFileBinary *, bool);
/* Indique le type défini pour une description de fichier binaire. */
G_DEFINE_TYPE(GFileBinary, g_file_binary, G_TYPE_LOADED_BINARY);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des descriptions de fichier binaire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_file_binary_class_init(GFileBinaryClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
object = G_OBJECT_CLASS(klass);
object->finalize = (GObjectFinalizeFunc)g_file_binary_finalize;
}
/******************************************************************************
* *
* Paramètres : binary = instance à initialiser. *
* *
* Description : Initialise une description de fichier binaire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_file_binary_init(GFileBinary *binary)
{
GLoadedBinary *loaded; /* Version parente */
loaded = G_LOADED_BINARY(binary);
loaded->save = (save_binary_fc)g_file_binary_save;
loaded->get_name = (get_binary_name_fc)g_file_binary_get_name;
}
/******************************************************************************
* *
* Paramètres : binary = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_file_binary_finalize(GFileBinary *binary)
{
free(binary->filename);
G_OBJECT_CLASS(g_file_binary_parent_class)->finalize(G_OBJECT(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 : - *
* *
******************************************************************************/
GLoadedBinary *g_file_binary_new_from_file(const char *filename)
{
GFileBinary *result; /* Adresse à retourner */
GLoadedBinary *loaded; /* Version parente */
int fd; /* Descripteur du fichier */
struct stat info; /* Informations sur le fichier */
int ret; /* Bilan d'un appel */
void *content; /* Contenu brut du fichier */
const char *target; /* Architecture requise */
const char *desc; /* Description humaine associée*/
result = g_object_new(G_TYPE_FILE_BINARY, NULL);
loaded = G_LOADED_BINARY(result);
log_variadic_message(LMT_PROCESS, _("Opening '%s' file..."), filename);
result->filename = strdup(filename);
/* Récupération des données */
fd = open(filename, O_RDONLY);
if (fd == -1)
{
perror("open");
goto lbf_error;
}
ret = fstat(fd, &info);
if (ret == -1)
{
close(fd);
perror("fstat");
goto lbf_error;
}
content = mmap(NULL, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (content == MAP_FAILED)
{
close(fd);
perror("mmap");
goto lbf_error;
}
loaded->bin_length = info.st_size;
loaded->bin_data = (bin_t *)malloc(info.st_size);
memcpy(loaded->bin_data, content, info.st_size);
munmap(content, info.st_size);
close(fd);
/* Chargement du binaire */
loaded->format = G_EXE_FORMAT(load_new_format(FMT_EXEC, filename,
&loaded->bin_data, &loaded->bin_length));
if (loaded->format == NULL)
{
log_simple_message(LMT_INFO, _("Unknown binary format"));
goto lbf_error;
}
target = g_exe_format_get_target_machine(loaded->format);
desc = get_arch_processor_name(target);
if (desc == NULL)
{
log_simple_message(LMT_INFO, _("Unknown architecture"));
goto lbf_error;
}
else
log_variadic_message(LMT_INFO, _("Detected architecture: %s"), desc);
loaded->proc = get_arch_processor_for_type(target);
if (loaded->proc == NULL)
{
log_simple_message(LMT_ERROR, _("Unable to load the required processor"));
goto lbf_error;
}
return G_LOADED_BINARY(result);
lbf_error:
g_object_unref(G_OBJECT(result));
return NULL;
}
/******************************************************************************
* *
* Paramètres : context = contexte pour les recherches XPath. *
* path = chemin d'accès au noeud XML à lire. *
* *
* 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 : - *
* *
******************************************************************************/
GLoadedBinary *g_file_binary_new_from_xml(xmlXPathContextPtr context, const char *path)
{
GLoadedBinary *result; /* Adresse à retourner */
char *access; /* Chemin pour une sous-config.*/
char *filename; /* Chemin du binaire à charger */
result = NULL;
/* Chemin du fichier à retrouver */
access = strdup(path);
access = stradd(access, "/Filename");
filename = get_node_text_value(context, access);
free(access);
/* Chargement */
if (filename != NULL)
{
result = g_file_binary_new_from_file(filename);
free(filename);
}
return result;
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à traiter. *
* xdoc = structure XML en cours d'édition. *
* context = contexte à utiliser pour les recherches. *
* path = chemin d'accès réservé au binaire. *
* *
* Description : Ecrit une sauvegarde du binaire dans un fichier XML. *
* *
* Retour : true si l'opération a bien tourné, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_file_binary_save(const GFileBinary *binary, xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path)
{
bool result; /* Bilan à faire remonter */
char *access; /* Chemin d'accès à un élément */
result = true;
/* Type */
result &= add_string_attribute_to_node(xdoc, context, path, "type", "file");
/* Nom du fichier associé */
access = strdup(path);
access = stradd(access, "/Filename");
result &= add_content_to_node(xdoc, context, access, binary->filename);
free(access);
return result;
}
/******************************************************************************
* *
* Paramètres : binary = élément binaire à consulter. *
* full = précise s'il s'agit d'une version longue ou non. *
* *
* Description : Fournit le nom associé à l'élément binaire. *
* *
* Retour : Nom de fichier avec chemin absolu. *
* *
* Remarques : - *
* *
******************************************************************************/
static const char *g_file_binary_get_name(const GFileBinary *binary, bool full)
{
const char *result; /* Description à retourner */
if (full)
result = binary->filename;
else
result = strrchr(binary->filename, G_DIR_SEPARATOR) + 1;
return result;
}
/******************************************************************************
* *
* 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 *g_file_binary_get_filename(const GFileBinary *binary)
{
return binary->filename;
}