/* Chrysalide - Outil d'analyse de fichiers binaires * rich.c - calculs d'empreintes relatifs aux en-têtes PE enrichis * * Copyright (C) 2020 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 . */ #include "rich.h" #include #include /****************************************************************************** * * * Paramètres : format = format en place à consulter. * * csum = empreinte à déterminer. [OUT] * * * * Description : Calcule la valeur pour empreinte d'en-tête PE enrichi. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool compute_pe_rich_header_checksum(const GPeFormat *format, uint32_t *csum) { bool result; /* Bilan à retourner */ mrange_t area; /* Zone couverte par l'en-tête */ GBinContent *content; /* Contenu à parcourir */ vmpa2t start; /* Position de départ */ phys_t offset; /* Position du début d'en-tête */ const bin_t *data; /* Données brutes à analyser */ phys_t i; /* Boucle de parcours #0 */ comp_id_t *ids; /* Identifiants à traiter */ size_t count; /* Quantité de ces identifiants*/ size_t k; /* Boucle de parcours #1 */ result = g_pe_format_get_rich_header_area(format, &area); if (!result) *csum = 0; else { #define rol32(word, shift) \ ((uint32_t)word) << (shift & 31) | ((uint32_t)word) >> (32 - (shift & 31)) /* Première source de calculs */ content = g_known_format_get_content(G_KNOWN_FORMAT(format)); g_binary_content_compute_start_pos(content, &start); offset = get_phy_addr(get_mrange_addr(&area)) - get_phy_addr(&start); *csum = offset; data = g_binary_content_get_raw_access(content, &start, offset); if (data == NULL) { g_object_unref(G_OBJECT(content)); result = false; goto exit; } for (i = 0; i < offset; i++) { /* Saut du champ e_lfanew, non initialisé lors de la construction */ if (0x3c <= i && i < 0x40) continue; *csum += rol32(data[i], i); } g_object_unref(G_OBJECT(content)); /* Seconde source de calculs */ ids = g_pe_format_get_comp_ids(format, &count); for (k = 0; k < count; k++) *csum += rol32((ids[k].prod_id << 16) | ids[k].minor_cv, ids[k].count); if (ids != NULL) free(ids); } exit: return result; } /****************************************************************************** * * * Paramètres : format = format en place à consulter. * * pv = forme d'empreinte à construire. * * * * Description : Calcule l'empreinte des informations d'en-tête PE enrichi. * * * * Retour : Empreinte MD5 calculée ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ char *compute_pe_rich_header_hash(const GPeFormat *format, bool pv) { char *result; /* Empreinte à retourner */ comp_id_t *ids; /* Identifiants à traiter */ size_t count; /* Quantité de ces identifiants*/ GChecksum *checksum; /* Preneur d'empreinte */ size_t i; /* Boucle de parcours */ uint32_t value; /* Valeur à prendre en compte */ ids = g_pe_format_get_comp_ids(format, &count); if (ids == NULL) result = NULL; else { checksum = g_checksum_new(G_CHECKSUM_MD5); if (!pv) { g_checksum_update(checksum, "DanS", 4); g_checksum_update(checksum, "\x00\x00\x00\x00", 4); } for (i = 0; i < count; i++) { if (pv && i == 0) continue; value = (ids[i].prod_id << 16) | ids[i].minor_cv; g_checksum_update(checksum, (char *)&value, sizeof(value)); if (!pv) { value = ids[i].count; g_checksum_update(checksum, (char *)&value, sizeof(value)); } } result = strdup(g_checksum_get_string(checksum)); g_checksum_free(checksum); free(ids); } return result; }