/* Chrysalide - Outil d'analyse de fichiers binaires * pe.c - support du format Portable Executable * * Copyright (C) 2010-2017 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