diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2021-04-05 22:59:31 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2021-04-05 23:11:48 (GMT) |
commit | b0347ca45a08ac63bc6dd6f244b046c6d19a6cdd (patch) | |
tree | 9af1ec9901ddcf696bd3297633faf9fb46712396 /plugins/pe/symbols.c | |
parent | cf0b5d5f07e8102f2c9a04012bf29cabda9d85e4 (diff) |
Build a partial working support for the PE format.
Diffstat (limited to 'plugins/pe/symbols.c')
-rw-r--r-- | plugins/pe/symbols.c | 335 |
1 files changed, 306 insertions, 29 deletions
diff --git a/plugins/pe/symbols.c b/plugins/pe/symbols.c index 30e43b5..9217466 100644 --- a/plugins/pe/symbols.c +++ b/plugins/pe/symbols.c @@ -24,20 +24,35 @@ #include "symbols.h" +#include <malloc.h> + + +#include <i18n.h> + + #include "pe-int.h" +#include "routine.h" +/* Charge en mémoire la liste humaine des symboles exportés. */ +static bool load_pe_exported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *); +/* Charge en mémoire la liste humaine des symboles importés. */ +static bool load_pe_imported_symbols(GPeFormat *, wgroup_id_t, GtkStatusStack *); +/* Assure l'inscription du point d'entrée d'un binaire PE. */ +static bool load_pe_entry_point(GPeFormat *, GtkStatusStack *); /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * +* Paramètres : format = format chargé dont l'analyse est lancée. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * * * -* Description : Charge en mémoire la liste humaine des symboles importés. * +* Description : Charge en mémoire la liste humaine des symboles exportés. * * * * Retour : Bilan de l'opération. * * * @@ -45,74 +60,331 @@ * * ******************************************************************************/ -bool load_pe_imported_symbols(GPeFormat *format) +static bool load_pe_exported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status) { bool result; /* Bilan à retourner */ - const image_data_directory *directory; /* Répertoire original */ - image_import_descriptor dll; /* DLL importée */ - off_t pos; /* Position de tête de lecture */ - off_t i; /* Boucle de parcours */ - image_import_by_name import; /* Fonction importée */ + image_export_directory *export; /* Répertoire de type 0 */ + const image_data_directory *dir; /* Localisation du répertoire */ + GBinFormat *base; /* Version basique du format */ + GExeFormat *exe; /* Autre vision du format */ + bool ret; /* Bilan d'un traitement */ + vmpa2t functions; /* Localisation des adresses */ + vmpa2t names; /* Localisation de RVA de noms */ + vmpa2t ordinals; /* Localisation des ordinaux */ + const GBinContent *content; /* Contenu binaire à lire */ + uint32_t i; /* Boucle de parcours */ + uint32_t rva; /* Adresse relative à traiter */ + vmpa2t pos; /* Position correspondante */ + const bin_t *name; /* Pointeur vers des données */ + uint16_t ordinal; /* Indice de l'exportation */ + bool forwarded; /* Le symbole est renvoyé ? */ + GPeExportedRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Equivalence en symbole */ + mrange_t range; /* Couverture mémoire associée */ + + result = false; + + export = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_EXPORT); + if (export == NULL) goto exit; + + dir = g_pe_format_get_directories(format, NULL); + dir += IMAGE_DIRECTORY_ENTRY_EXPORT; + + base = G_BIN_FORMAT(format); + exe = G_EXE_FORMAT(format); + + ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_functions, &functions); + if (!ret) goto exit_loading; + + ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_names, &names); + if (!ret) goto exit_loading; + + ret = g_exe_format_translate_address_into_vmpa(exe, export->address_of_name_ordinals, &ordinals); + if (!ret) goto exit_loading; + + content = G_KNOWN_FORMAT(format)->content; + + for (i = 0; i < export->number_of_names; i++) + { + /* Dénomination */ + + ret = g_binary_content_read_u32(content, &names, SRE_LITTLE, &rva); + if (!ret) goto exit_loading; + + ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos); + if (!ret) goto exit_loading; + + name = g_binary_content_get_raw_access(content, &pos, 1); + if (name == NULL) goto exit_loading; + + /* Ordinal */ + + ret = g_binary_content_read_u16(content, &ordinals, SRE_LITTLE, &ordinal); + if (!ret) goto exit_loading; + + ordinal += export->base; + + /* Adresse */ + + copy_vmpa(&pos, &functions); + advance_vmpa(&pos, ordinal * sizeof(uint32_t)); + + ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE, &rva); + if (!ret) goto exit_loading; + + /** + * Entrée de type "Forwarder RVA" ? + */ + forwarded = (dir->virtual_address <= rva && rva < (dir->virtual_address + dir->size)); + + ret = g_exe_format_translate_address_into_vmpa(exe, rva, &pos); + if (!ret) continue; + + /* Mise en place du symbole */ + + routine = g_pe_exported_routine_new((char *)name); + + g_pe_exported_routine_set_ordinal(routine, ordinal); + + symbol = G_BIN_SYMBOL(routine); + + if (forwarded) + g_binary_symbol_set_flag(symbol, PSF_FORWARDED); + + g_binary_symbol_set_status(symbol, SSS_EXPORTED); + + init_mrange(&range, &pos, 0); + + g_binary_symbol_set_range(symbol, &range); + + g_binary_format_add_symbol(base, symbol); + + } result = true; - directory = &format->nt_headers.optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + exit_loading: + + free(export); + + exit: + + return result; + +} + - /* TODO : msg si size !% sizeof(...) */ +/****************************************************************************** +* * +* Paramètres : format = format chargé dont l'analyse est lancée. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * +* * +* Description : Charge en mémoire la liste humaine des symboles importés. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - for (pos = directory->virtual_address; - result && pos < (directory->virtual_address + directory->size); ) +static bool load_pe_imported_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status) +{ + bool result; /* Bilan à retourner */ + bool is_32b; /* Exécutable 32 bits ? */ + image_import_descriptor *imports; /* Répertoire de type 1 */ + GBinFormat *base; /* Version basique du format */ + GExeFormat *exe; /* Autre vision du format */ + const GBinContent *content; /* Contenu binaire à lire */ + image_import_descriptor *iter; /* Boucle de parcours */ + vmpa2t dll; /* Nom de la DLL concernée */ + bool ret; /* Bilan d'un traitement */ + const bin_t *library; /* Pointeur vers des données */ + vmpa2t lookup; /* Informations d'importation */ + vmpa2t overwritten; /* Emplacement d'adresse finale*/ + uint32_t val32; /* Indications sur 32 bits */ + uint64_t val64; /* Indications sur 64 bits */ + uint32_t rva; /* Adresse relative à traiter */ + vmpa2t name; /* Désignation humaine */ + const bin_t *hint; /* Pointeur vers des données */ + GPeImportedRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Equivalence en symbole */ + mrange_t range; /* Couverture mémoire associée */ + + result = false; + + is_32b = g_pe_format_get_is_32b(format); + + imports = g_pe_format_get_directory(format, IMAGE_DIRECTORY_ENTRY_IMPORT); + if (imports == NULL) goto exit; + + base = G_BIN_FORMAT(format); + exe = G_EXE_FORMAT(format); + + content = G_KNOWN_FORMAT(format)->content; + + for (iter = imports; iter->original_first_thunk != 0; iter++) { - result = read_pe_image_import_descriptor(format, &pos, &dll); + /* Bibliothèque impactée */ - printf("mod orig thunk :: 0x%08x\n", dll.original_first_thunk); - printf("mod name :: 0x%08x\n", dll.module_name); - printf("mod first thunk :: 0x%08x\n", dll.first_thunk); + ret = g_exe_format_translate_address_into_vmpa(exe, iter->module_name, &dll); + if (!ret) goto exit_loading; - i = dll.original_first_thunk; + library = g_binary_content_get_raw_access(content, &dll, 1); + if (library == NULL) goto exit_loading; - /* TODO : i == 0 */ - if (i == 0) continue; + /* Liste des fonctions importées */ - while ((result = read_pe_image_import_by_name(format, &i, &import))) + ret = g_exe_format_translate_address_into_vmpa(exe, iter->original_first_thunk, &lookup); + if (!ret) goto exit_loading; + + ret = g_exe_format_translate_address_into_vmpa(exe, iter->first_thunk, &overwritten); + if (!ret) goto exit_loading; + + do { - if (import.hint == 0 && import.name == NULL) + if (is_32b) + { + ret = g_binary_content_read_u32(content, &lookup, SRE_LITTLE, &val32); + if (!ret) goto exit_loading; + + val64 = ((uint64_t)(val32 & 0x80000000)) << 32 | val32; + + } + else + { + ret = g_binary_content_read_u64(content, &lookup, SRE_LITTLE, &val64); + if (!ret) goto exit_loading; + } + + if (val64 == 0) break; + if (val64 & 0x8000000000000000) + { + routine = g_pe_imported_routine_new(NULL); + g_pe_exported_routine_set_ordinal(G_PE_EXPORTED_ROUTINE(routine), val64 & 0xffff); - printf(" >> import '%s'\n", import.name); + } + else + { + rva = (val64 & 0x7fffffff); + ret = g_exe_format_translate_address_into_vmpa(exe, rva, &name); + if (!ret) goto exit_loading; - } + hint = g_binary_content_get_raw_access(content, &name, 3); + if (hint == NULL) goto exit_loading; + + hint += 2; + + //routine = g_binary_format_decode_routine(base, hint); + routine = g_pe_imported_routine_new((char *)hint); + } + + g_pe_imported_routine_set_library(routine, (char *)library); + + symbol = G_BIN_SYMBOL(routine); + + g_binary_symbol_set_status(symbol, SSS_IMPORTED); + + init_mrange(&range, &overwritten, sizeof(uint32_t)); + advance_vmpa(&overwritten, sizeof(uint32_t)); + + g_binary_symbol_set_range(symbol, &range); + + g_binary_format_add_symbol(base, symbol); + + } + while (true); } - lpis_exit: + result = true; + + exit_loading: + + free(imports); + + exit: return result; } +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure l'inscription du point d'entrée d'un binaire PE. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_pe_entry_point(GPeFormat *format, GtkStatusStack *status) +{ + bool result; /* Bilan à renvoyer */ + activity_id_t msg; /* Message de progression */ + const image_nt_headers *headers; /* Informations d'entête */ + virt_t ep; /* Point d'entrée détecté */ + vmpa2t addr; /* Localisation d'une routine */ + GBinFormat *base; /* Autre version du format */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + GBinRoutine *routine; /* Routine à associer au point */ + mrange_t range; /* Couverture mémoire associée */ + + msg = gtk_status_stack_add_activity(status, _("Registering entry point..."), 0); + + headers = g_pe_format_get_nt_headers(format); + ep = headers->optional_header.header_32.address_of_entry_point; + result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), ep, &addr); + if (!result) goto exit; + base = G_BIN_FORMAT(format); + if (!g_binary_format_find_symbol_at(base, &addr, &symbol)) + { + routine = g_binary_format_decode_routine(base, "entry_point"); + symbol = G_BIN_SYMBOL(routine); + g_object_ref(G_OBJECT(symbol)); + init_mrange(&range, &addr, 0); + g_binary_symbol_set_range(symbol, &range); + g_binary_format_add_symbol(base, symbol); + } + g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT); + g_object_unref(G_OBJECT(symbol)); + /* Comptabilisation pour le désassemblage brut */ + g_binary_format_register_code_point(base, get_virt_addr(&addr), DPL_ENTRY_POINT); + exit: + gtk_status_stack_remove_activity(status, msg); + + return result; + +} /****************************************************************************** * * -* Paramètres : format = description de l'exécutable à compléter. * +* Paramètres : format = format chargé dont l'analyse est lancée. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * * * * Description : Charge en mémoire la liste humaine des symboles. * * * @@ -122,14 +394,19 @@ bool load_pe_imported_symbols(GPeFormat *format) * * ******************************************************************************/ -bool load_pe_symbols(GPeFormat *format) +bool load_pe_symbols(GPeFormat *format, wgroup_id_t gid, GtkStatusStack *status) { bool result; /* Bilan à retourner */ - /* Symboles externes */ - result = load_pe_imported_symbols(format); + result = load_pe_exported_symbols(format, gid, status); + + if (result) + result = load_pe_imported_symbols(format, gid, status); + + /* Symbole d'entrée, si encore besoin */ - /* Symboles internes */ + if (result) + result = load_pe_entry_point(format, status); return result; |