lundi 11 février 2008

L'Export Table et GetProcAddress()

J'imagines que tout le monde connait le format PE, le format des executables Windows. Si ce n'est pas le cas je vous conseille d'aller lire ceci avant de commencer cet article : http://en.wikibooks.org/wiki/Reverse_Engineering/PE

Bon alors je vais aujourd'hui parlais d'un point peu soulever dans le format PE car tout le monde parle de l'Import Table dans les introductions au format PE mais j'ai trouvé très peu d'articles sur l'Export Table donc c'est parti pour l'avanture.


Donc on va d'abord voir comment accéder à l'export table et nous verrons ensuite comment récupérer les informations utiles de l'export table et enfin une petite implémentation de GetProcAddress() avec ce que nous viendrons de voir.


Je vous laisse regarder une petite représentation du format PE pour voir ce qui nous interessent : http://ivanlef0u.free.fr/repo/windoz/pe/_pe-tuts/GlobalPE.htm


Donc le format PE commence par une strutcture IMAGE_DOS_HEADER qui contient entre autre un champ e_magic qui représente la signature et le champ e_lflanew qui nous permet de savoir où se trouve la strucuture IMAGE_NT_HEADER.
Donc dans cette structure il y a toujours une signature et si on descend un peu dans l'OptionalHeader, on se retrouve avec des structures IMAGE_DATA_DIRECTORY dont la première est ... l'Export Table.

Bon alors voila je vais finir cette première partie en vous donnant toutes les structures du format PE pour que vous compreniez un peu mieux de quoi on parle.
http://ivanlef0u.free.fr/repo/windoz/pe/pe.txt


Bon après cette très courte introduction au format PE, on va approfondir un petit l'export table pour voir comment elle est composée.
Donc voici un petit résumer de l'organisation de l'export table en mémoire :

Flags ( Characteristics )TimestampMajor VersionMinor VersionNameBaseNombre de FonctionsNombre de NomAdresses des fonctionsAdresses des noms de fonctionsAdresses des noms ordinaux


Donc ici la seule chose que va nous interesser ce sont les 5 derniers champs, normalement Nombre de fonctions == Nombre de Noms donc on peut prendre soit l'un soit l'autre.

Ensuite il faut savoir que les champs d'adresses sont des pointeurs sur un tableau de pointeurs et que ce sont des tableaux en parallèles ce qui veut dire que le premier pointeur du tableau des adresses des fonctions et le premier pointeur du tableau des adresses des noms de fonctions correspondent aux même objet et donc à la même fonction.

En clair soit TabAdressFunc le tableau des adresses des fonctions et TabNameFunc le tableau des adresses des noms de fonctions, TabAdressFunc[0] et TabNameFunc[0] sont deux pointeurs qui font référence à la même fonction.
Et bien entendu la même chose pour le dernier tableau qui sert à déterminer l'adresse de l'adresse de l'API.

Pour récupérer le PE file d'une dll, il suffit juste d'appeler GetModuleHandle() avec comme param le nom de la dll.
Et donc voici un code qui dump l'export table d'une dll en d'occurrence kernel32 et puis vous verez qu'il y a vraiment beaucoup de fonctions exportés.
http://akhenathon2.free.fr/coding/DumpExportTable.c

Et donc voici ce que tout le monde attend, une implémentation de GetProcAddress() :
http://akhenathon2.free.fr/coding/MyGetProcAddress.c

Bon je vous accordes que les codes sont très moches mais en ce moment je n'ai pas trop le temps ( oué c'est les cours mais bon ça en vaut la peine 19.25 en math c'est la classe surtout en 1S ), je les retoucherais si j'ai un peu de temps.

En espérant que cet article vous auras permit d'en apprendre un peu plus sur l'Export Table et éventuellement découvert une alternative à GetProcAddress().

Doc : http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
Have fun :)

3 commentaires:

0vercl0k a dit…

Bonsoir à toi,
Merci pour tes articles régulier, continue comme cela quoi qu'il en soit.
Cependant, ta fonction personnelle n'est loin d'être aussi performante que GetProcAddress(), tu ne parles pas de l'export forwarding par exemple.

Akhenath0n a dit…

Oui c'est vrai je suis tout à fait d'accord mais c'était juste un moyen pour comprendre vite fait comment fonctionnait l'export table car c'est quelque chose que j'ignorais et pour essayer d'implementer une fonction avec une simple définition de l'export table

0vercl0k a dit…

Tout à fait, c'etait histoire de dire..:).
Tu fais du bon boulot continus, cya.h