summaryrefslogtreecommitdiff
path: root/plugins/pe/symbols.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pe/symbols.c')
-rw-r--r--plugins/pe/symbols.c335
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;