PE Les exportations de fichiers
Le contraire de l'importation d'une fonction exporte une fonction pour une utilisation par d'autres ou EXEs DLL. Un fichier PE stocke des informations sur ses fonctions exportées dans la section .edata. Généralement, les fichiers PE EXE générés par les liens Microsoft n'exportent rien, donc ils n'ont pas de section .edata. TLINK32 de Borland exporte toujours au moins un symbole à partir d'un fichier EXE. La plupart des DLL exportent des fonctions et ont une section .edata. Les composants principaux d'une section .edata (alias table d'exportation) sont des tables de noms de fonctions, d'adresses de points d'entrée et de valeurs ordinales d'exportation. Dans un fichier NE, les équivalents d'une table d'exportation sont la table d'entrée, la table des noms résidents et la table des noms non résidents. Ces tables sont stockées dans l'en-tête NE, plutôt que dans des segments ou des ressources distincts.
Au début d'une section .edata se trouve une structure IMAGE_EXPORT_DIRECTORY (voir Tableau 10). Cette structure est immédiatement suivie de données pointées par des champs dans la structure.
Tableau 10. IMAGE_EXPORT_DIRECTORY Format
DWORD Characteristics
Ce champ semble être utilisé et est toujours à 0.
DWORD TimeDateStamp
Le timbre heure/date indiquant le moment où ce fichier a été créé.
WORD MajorVersion
WORD MinorVersion
Ces champs semblent être inutilisés et sont mis à 0.
DWORD Name
La RVA d'une chaîne ASCIIZ avec le nom de cette DLL.
DWORD Base
Numéro d'ordre de départ pour les fonctions exportées. Par exemple, si le fichier exporte des fonctions avec des valeurs ordinales de 10, 11 et 12, ce champ contient 10. Pour obtenir l'ordinal exporté d'une fonction, vous devez ajouter cette valeur à l'élément approprié du tableau AddressOfNameOrdinals.
DWORD NumberOfFunctions
Le nombre d'éléments dans le tableau AddressOfFunctions. Cette valeur correspond également au nombre de fonctions exportées par ce module. Théoriquement, cette valeur peut être différente du champ NumberOfNames (suivant), mais en réalité, ils sont toujours les mêmes.
DWORD NumberOfNames
Le nombre d'éléments dans le tableau AddressOfNames. Cette valeur semble toujours être identique au champ NumberOfFunctions, tout comme le nombre de fonctions exportées.
PDWORD *AddressOfFunctions
Ce champ est un RVA et pointe vers un tableau d'adresses de fonctions. Les adresses de fonction sont les points d'entrée (RVA) pour chaque fonction exportée dans ce module.
PDWORD *AddressOfNames
Ce champ est un RVA et pointe vers un tableau de pointeurs de chaîne. Les chaînes sont les noms des fonctions exportées dans ce module.
PWORD *AddressOfNameOrdinals
Ce champ est un RVA et pointe vers un tableau de mots. Les WORD sont les ordinaux d'exportation de toutes les fonctions exportées dans ce module. Cependant, n'oubliez pas d'ajouter le nombre ordinal de départ spécifié dans le champ Base.
La disposition de la table d'exportation est quelque peu étrange (voir Figure 4 et Tableau 10). Comme je l'ai mentionné plus tôt, les exigences pour l'exportation d'une fonction sont un nom, une adresse et un ordinal d'exportation. On pourrait penser que les concepteurs du format PE auraient mis tous ces trois éléments dans une structure, et ensuite avoir un tableau de ces structures. Au lieu de cela, chaque composant d'une entrée exportée est un élément d'un tableau. Il y a trois de ces tableaux (AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals), et ils sont tous parallèles les uns aux autres. Pour trouver toutes les informations sur la quatrième fonction, vous devez rechercher le quatrième élément de chaque tableau.

Figure 4. disposition de la table d'exportation
Tableau 11. Tableau Exportations typiques d'un fichier EXE
Name: KERNEL32.dll
Characteristics: 00000000
TimeDateStamp: 2C4857D3
Version: 0.00
Ordinal base: 00000001
# of functions: 0000021F
# of Names: 0000021F
Entry Pt Ordn Name
00005090 1 AddAtomA
00005100 2 AddAtomW
00025540 3 AddConsoleAliasA
00025500 4 AddConsoleAliasW
00026AC0 5 AllocConsole
00001000 6 BackupRead
00001E90 7 BackupSeek
00002100 8 BackupWrite
0002520C 9 BaseAttachCompleteThunk
00024C50 10 BasepDebugDump
// Rest of table omitted...
Soit dit en passant, si vous videz les exportations de la DLL système Windows NT (par exemple, KERNEL32.DLL et USER32.DLL), vous remarquerez que dans de nombreux cas, il existe deux fonctions qui ne diffèrent que par un caractère à la fin du nom, par exemple CreateWindowExA et CreateWindowExW. C'est ainsi que le support UNICODE est implémenté de manière transparente. Les fonctions qui se terminent par A sont les fonctions compatibles ASCII (ou ANSI), tandis que celles qui se terminent par W sont la version UNICODE de la fonction. Dans votre code, vous ne spécifiez pas explicitement quelle fonction appeler. Au lieu de cela, la fonction appropriée est sélectionnée dans WINDOWS.H, via le préprocesseur #ifdefs. Cet extrait du Windows NT WINDOWS.H montre un exemple de la façon dont cela fonctionne: Copy
#ifdef UNICODE
#define DefWindowProc DefWindowProcW
#else
#define DefWindowProc DefWindowProcA
#endif // !UNICODE
//
// Export Format
//
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
EDIT: Dans le tableau des exportations de format PE n'est pas diffrent, adresse fonctions est une RVA d'adresse 64 bits uniquement.
Source:http://msdn.microsoft.com/en-us/library/ms809762.aspx
+1 pour la longueur de la réponse :) –
Merci beaucoup pour la réponse détaillée !! – Elad
Avez-vous un morceau de code en C# qui fait cela? – Elad