/* Chrysalide - Outil d'analyse de fichiers binaires * fetch.c - récupération d'instructions à partir de binaire brut * * Copyright (C) 2010-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 "fetch.h" #include "../../arch/artificial.h" #include "../../arch/raw.h" #include "../../arch/instruction-int.h" /****************************************************************************** * * * Paramètres : binary = représentation de binaire chargé. * * parts = parties binaires à désassembler. * * count = nombre de parties à traiter. * * statusbar = barre de statut avec progression à mettre à jour.* * id = identifiant du message affiché à l'utilisateur. * * * * Description : Procède au désassemblage basique d'un contenu binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id) { GArchInstruction *result; /* Liste d'instr. à renvoyer */ GBinFormat *format; /* Format du fichier binaire */ GArchProcessor *proc; /* Architecture du binaire */ off_t bin_length; /* Taille des données à lire */ bin_t *bin_data; /* Données binaires à lire */ vmpa2t pos; /* Boucle de parcours */ vmpa2t prev; /* Boucle de parcours */ off_t old_phy; /* Ancienne position physique */ GArchInstruction *instr; /* Instruction décodée */ off_t new_phy; /* Nouvelle position physique */ result = NULL; format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); bin_data = g_loaded_binary_get_data(binary, &bin_length); end = bin_length; copy_vmpa(&pos, base); copy_vmpa(&prev, base); old_phy = get_phy_addr(&prev); while (old_phy < end) { instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end, g_arch_processor_get_endianness(proc)); if (instr == NULL) printf(" Break !!!\n"); if (instr == NULL) break; new_phy = get_phy_addr(&pos); g_arch_instruction_set_location(instr, &prev, new_phy - old_phy); g_arch_instruction_add_to_list(&result, instr); copy_vmpa(&prev, &pos); old_phy = get_phy_addr(&prev); //done += (new_phy - old_phy); //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); } return result; } /****************************************************************************** * * * Paramètres : binary = représentation de binaire chargé. * * statusbar = barre de statut avec progression à mettre à jour.* * id = identifiant du message affiché à l'utilisateur. * * * * Description : Procède au désassemblage basique d'un contenu binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id) { GArchInstruction *result; /* Instruction désassemblées */ GBinFormat *format; /* Format du fichier binaire */ GBinSymbol **symbols; /* Symboles à représenter */ size_t sym_count; /* Qté de symboles présents */ size_t i; /* Boucle de parcours */ GArchInstruction *instr; /* Instruction à insérer */ vmpa2t *last; /* Dernière bordure rencontrée */ const vmpa2t *border; /* Nouvelle bordure rencontrée */ off_t length; /* Taille d'une partie traitée */ GArchInstruction *joint; /* Jointure entre deux lots */ off_t max_length; /* Taille des données à lire */ result = NULL; format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); last = make_vmpa(0, VMPA_NO_VIRTUAL); symbols = g_binary_format_get_symbols(format, &sym_count); //sym_count = 0; for (i = 0; i < sym_count; i++) { switch (g_binary_symbol_get_target_type(symbols[i])) { case STP_DATA: instr = g_binary_symbol_get_instruction(symbols[i]); g_object_ref(G_OBJECT(instr)); border = g_arch_instruction_get_location2(instr, &length); length = 4; break; } /* Traiter la diff */ if (cmp_vmpa_by_phy(last, border) < 0) { joint = load_raw_binary(binary, last, get_phy_addr(last) + compute_vmpa_diff(border, last), statusbar, id); ainstr_list_merge(&result, &joint); } /* Ajout des instructions déjà établies */ ainstr_list_merge(&result, &instr); /* Marquage de la nouvelle dernière bordure */ copy_vmpa(last, border); advance_vmpa(last, length); printf("length :: %d\n", length); } /* Raccord final ? */ g_loaded_binary_get_data(binary, &max_length); if (get_phy_addr(last) < max_length) { joint = load_raw_binary(binary, last, max_length, statusbar, id); ainstr_list_merge(&result, &joint); } printf("COUNT :: %zu\n", sym_count); //exit(0); return result; } #ifdef DEBUG # include "../../arch/artificial.h" #endif /****************************************************************************** * * * Paramètres : binary = représentation de binaire chargé. * * parts = parties binaires à désassembler. * * count = nombre de parties à traiter. * * statusbar = barre de statut avec progression à mettre à jour.* * id = identifiant du message affiché à l'utilisateur. * * * * Description : Procède au désassemblage basique d'un contenu binaire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *disassemble_binary_parts(const GLoadedBinary *binary, GBinPart **parts, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id) { GArchInstruction *result; /* Liste d'instr. à renvoyer */ GBinFormat *format; /* Format du fichier binaire */ GArchProcessor *proc; /* Architecture du binaire */ off_t bin_length; /* Taille des données à lire */ bin_t *bin_data; /* Données binaires à lire */ size_t i; /* Boucle de parcours #1 */ off_t sum; /* Somme de toutes les tailles */ off_t done; /* Quantité déjà traitée */ #ifdef DEBUG unsigned int valid; /* Instructions traduites */ unsigned int db; /* Instructions non décodées */ #endif off_t pos; /* Début d'une zone binaire */ off_t len; /* Taille de cette même zone */ vmpa_t base; /* Adresse de la zone binaire */ off_t start; /* Conservation du pt de départ*/ GProcContext *context; /* Contexte pour le décodage */ vmpa_t addr; /* Adresse d'une instruction */ GArchInstruction *instr; /* Instruction décodée */ result = NULL; format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); proc = get_arch_processor_from_format(G_EXE_FORMAT(format)); bin_data = g_loaded_binary_get_data(binary, &bin_length); /* Préparation du suivi de la progression */ sum = 0; for (i = 0; i < count; i++) { g_binary_part_get_values(parts[i], NULL, &len, NULL); if (len > bin_length) continue; sum += len; } done = 0; for (i = 0; i < count; i++) { g_binary_part_get_values(parts[i], &pos, &len, &base); if (len > bin_length) continue; context = g_arch_processor_get_context(proc); /* Décodage des instructions */ #ifdef DEBUG valid = 0; db = 0; #endif start = pos; len += start; while (pos < len) { addr = base + (pos - start); instr = g_arch_processor_decode_instruction(proc, context, bin_data, &pos, len, addr, format); g_arch_instruction_add_to_list(&result, instr); #ifdef DEBUG if (G_IS_DB_INSTRUCTION(instr) && !g_db_instruction_is_skipped(G_DB_INSTRUCTION(instr))) db++; else valid++; #endif if (pos < len) gtk_extended_status_bar_update_activity(statusbar, id, (done + pos - start) * 1.0 / sum); } if (context != NULL) g_object_unref(context); #ifdef DEBUG g_binary_part_set_checkup(parts[i], valid, db); #endif done += (len - start); gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); } return result; }