/* Chrysalide - Outil d'analyse de fichiers binaires
* pe.c - support du format Portable Executable
*
* Copyright (C) 2009-2012 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 Foobar. If not, see .
*/
#include "pe.h"
#include
#include "pe-int.h"
#include "section.h"
#include "symbols.h"
/* Initialise la classe des formats d'exécutables PE. */
static void g_pe_format_class_init(GPeFormatClass *);
/* Initialise une instance de format d'exécutable PE. */
static void g_pe_format_init(GPeFormat *);
/* Indique le type d'architecture visée par le format. */
static const char *g_pe_format_get_target_machine(const GPeFormat *);
/* Fournit les références aux zones binaires à analyser. */
//static GBinPart **g_pe_format_get_parts(const GPeFormat *, size_t *);
/******************************************************************************
* *
* Paramètres : content = contenu binaire à parcourir. *
* *
* Description : Indique si le format peut être pris en charge ici. *
* *
* Retour : true si la réponse est positive, false sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
bool pe_is_matching(GBinContent *content)
{
bool result; /* Bilan à faire connaître */
image_dos_header dos_header; /* En-tête DOS */
result = false;
#if 0
if (length >= 2)
{
result = (strncmp((const char *)content, "\x4d\x5a" /* MZ */, 2) == 0);
result &= length >= sizeof(image_dos_header);
}
if (result)
{
memcpy(&dos_header, content, sizeof(image_dos_header));
result = length >= (dos_header.e_lfanew + 4);
result &= (strncmp((const char *)&content[dos_header.e_lfanew],
"\x50\x45\x00\x00" /* PE00 */, 4) == 0);
}
#endif
return result;
}
/* Indique le type défini pour un format d'exécutable PE. */
G_DEFINE_TYPE(GPeFormat, g_pe_format, G_TYPE_EXE_FORMAT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des formats d'exécutables PE. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_pe_format_class_init(GPeFormatClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : format = instance à initialiser. *
* *
* Description : Initialise une instance de format d'exécutable PE. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_pe_format_init(GPeFormat *format)
{
}
/******************************************************************************
* *
* Paramètres : content = contenu binaire à parcourir. *
* length = taille du contenu en question. *
* *
* Description : Prend en charge un nouveau format PE. *
* *
* Retour : Adresse de la structure mise en place ou NULL en cas d'échec.*
* *
* Remarques : - *
* *
******************************************************************************/
GBinFormat *g_pe_format_new(const bin_t *content, off_t length)
{
GPeFormat *result; /* Structure à retourner */
off_t offset; /* Tête de lecture */
int i;
result = g_object_new(G_TYPE_PE_FORMAT, NULL);
//g_binary_format_set_content(G_BIN_FORMAT(result), content, length);
offset = 0;
if (!read_dos_image_header(result, &offset, &result->dos_header))
{
/* TODO */
return NULL;
}
offset = result->dos_header.e_lfanew;
if (!read_pe_nt_header(result, &offset, &result->nt_headers))
{
/* TODO */
return NULL;
}
result->section_offset = offset;
printf("offset :: 0x%08x\n", offset);
printf("Format :: 0x%08x\n", result->nt_headers.signature);
printf("directories :: %d\n", result->nt_headers.optional_header.number_of_rva_and_sizes);
for (i = 0; i < result->nt_headers.optional_header.number_of_rva_and_sizes; i++)
printf(" [%d] addr=0x%08x size=%d\n", i,
result->nt_headers.optional_header.data_directory[i].virtual_address,
result->nt_headers.optional_header.data_directory[i].size);
load_pe_symbols(result);
return G_BIN_FORMAT(result);
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* *
* Description : Indique le type d'architecture visée par le format. *
* *
* Retour : Identifiant de l'architecture ciblée par le format. *
* *
* Remarques : - *
* *
******************************************************************************/
static const char *g_pe_format_get_target_machine(const GPeFormat *format)
{
return "i386";
}
/******************************************************************************
* *
* Paramètres : format = informations chargées à consulter. *
* count = quantité de zones listées. [OUT] *
* *
* Description : Fournit les références aux zones binaires à analyser. *
* *
* Retour : Zones binaires à analyser. *
* *
* Remarques : - *
* *
******************************************************************************/
#if 0
static GBinPart **g_pe_format_get_parts(const GPeFormat *format, size_t *count)
{
GBinPart **result; /* Tableau à retourner */
uint16_t i; /* Boucle de parcours */
image_section_header section; /* En-tête de section PE */
GBinPart *part; /* Partie à intégrer à la liste*/
char name[IMAGE_SIZEOF_SHORT_NAME + 1]; /* Nom de section utilisable */
result = NULL;
*count = 0;
for (i = 0; i < format->nt_headers.file_header.number_of_sections; i++)
{
if (!find_pe_section_by_index(format, i, §ion))
continue;
if (section.characteristics & IMAGE_SCN_MEM_EXECUTE)
{
part = g_binary_part_new();
memset(name, 0, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
memcpy(name, section.name, (IMAGE_SIZEOF_SHORT_NAME + 1) * sizeof(char));
g_binary_part_set_name(part, name);
printf("section '%s'\n", name);
g_binary_part_set_values(part,
section.pointer_to_raw_data,
section.size_of_raw_data,
section.virtual_address);
printf("section[%d] start=0x%08x size=%d addr=0x%08x\n", i,
section.pointer_to_raw_data,
section.size_of_raw_data,
section.virtual_address);
result = (GBinPart **)realloc(result, ++(*count) * sizeof(GBinPart *));
result[*count - 1] = part;
}
}
return result;
}
#endif