begin process at 2012 02 08 08:50:29
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Système

 > HOOK D'API, INJECTION DE DLL, TABLE D'IMPORT

HOOK D'API, INJECTION DE DLL, TABLE D'IMPORT


 Information sur la source

Note :
9,67 / 10 - par 3 personnes
9,67 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Système Classé sous :hook, api, injection, import, dll Niveau :Initié Date de création :17/12/2007 Vu / téléchargé :8 315 / 828

Auteur : rt15

Ecrire un message privé
Commentaire sur cette source (12)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
#### Prérequis :

Lorsque l'on lance un exécutable, le loader de Windows mappe le fichier .exe (Ou plus précisément les sections qu'il contient) en RAM. Les lieurs sont généralement configurés pour produire des .exe qui ne peuvent fonctionner correctement qu'à une adresse fixe (Adresse de base de l'image dans les options de Delphi).

Comme le .exe est le premier à être chargé, le loader peut le mettre sans problème à cette adresse.

Puis le loader regarde la table d'importation du fichier .exe pour déterminer les dlls qu'il doit charger.

Cette fois, les dlls risquent de ne pas être chargées à leurs adresses de base préférées : elles peuvent être déjà prises par le .exe ou par un une autre dll. Heureusement, les dlls contiennent une table de relocation. Cette table est traitée par le loader de Windows qui va ainsi corriger des adresses de manière à ce que la dll fonctionne à l'adresse où elle est effectivement chargée.

La table d'importation du .exe contient aussi la liste des fonctions utilisées par le programme, pour chaque dll. Le loader de Windows va déterminer ces adresses et les mettre en place à des emplacements prévus à cet effet dans le mappage du .exe. Les adresses de ces futurs adresses sont donc connues au moment du linkage.

Les appels des fonctions importées ne sont donc pas implémentées sous forme de "exécute la fonction à cette adresse", adresse qui peut théoriquement être aléatoire, mais sous la forme "exécute la fonction dont l'adresse à été mise en place par le loader à cette adresse".

En assembleur on ne fait pas :
call XXXXXXX
car on ne connaît pas XXXXXXX au linkage, mais :
call dword ptr [YYYYYYYY]
où YYYYYYYY est connues au linkage, et le loader mettra "XXXXXXXX" à cette adresse car le .exe l'aura demandé via sa table d'importation.


#### Objectif :

Le hook d'API consiste à remplacer l'adresse mise en place par le loader par une autre. Ainsi, tout appel à la fonction hookée est redirigé vers la fonction de notre choix.

Cela permet deux choses :
1 Connaître les arguments passés à la fonction, pour par exemple connaître tous les fichiers ouverts par l'exécutable.
2 Modifier le comportement d'une application, pour par exemple forcer l'application à demander l'autorisation de l'utilisateur avant que l'application ne lance un exécutable avec CreateProcess ou ShellExecute.


#### Limitations :

Seules les fonctions importées par l'exe peuvent être hookées (Par cette technique...). Donc :

1 Tout emploi de LoadLibrary/GetProcAddress n'est pas filtré. Evidemment, rien n'empêche de hooker ces fonctions.
2 Les fonctions importées par les dlls utilisées par l'exe ne sont pas filtrées.

Le deuxième problème est sans doute peu courant dans les applications en Delphi qui s'appuient généralement uniquement sur des tables d'importations bien fournies avec des fonctions très classiques de l'API Win32.

Par contre, dans le cas d'une application C utilisant une runtime sous forme de dll, CreateFile peut tout à fait être absent de la table d'import par exemple, car le développeur peut n'avoir utilisé que fopen... Il suffit donc de hooker fopen aussi, mais il faut y penser.

Exemple encore plus flagrant : le VB6, où aucune fonction classique n'est importée. Les .exe de VB6 compilés en natif n'importent que depuis msvbvm60.dll, et encore, pas grand chose.


#### Préparation :

Il faut déduire le nom des fonctions hookées de l'objectif final que l'on souhaite atteindre. La doc du SDK Win32 peut nous aider à faire notre choix.

Une fois que l'on a les noms, il faut s'assurer que ces fonctions sont bien importées par le .exe cible.

Pour cela, on peut utiliser l'utilitaire Import.exe inclus en source et en binaire (Renommer le .exec en .exe) dans le zip. C'est une appli console qui prend en argument un fichier image (.exe, .dll... Tant que le fichier est au format PE, c'est ok), et qui affiche toutes les fonctions de la table d'import.

Hooker une fonction ne nous servira pas à grand chose si on ne connaît pas son prototype, c'est à dire les arguments qu'elle attend et sa convention d'appel. On ne peut pas facilement connaître ces informations sans avoir accès à la documentation de la dll.


#### Injection de la procédure dans le processus :

On souhaite remplacer une fonction importée par notre propre fonction. On sait que l'on va remplacer une adresse par une autre dans la table d'import. Il faut donc que l'on commence par avoir l'adresse de notre fonction, et ce, dans le processus distant.

Certains seraient peut être tentés de mettre leur procédure dans le processus qui installe le hook, puis de mettre en place l'adresse de cette procédure dans le processus hooker. C'est absolument impossible : deux processus ne partagent pas de mémoire, les adresses valables dans un processus pointent sur n'importe quoi dans l'autre. L'adressage est tout à fait virtuel.

Il faut donc charger notre procédure dans le processus à hooker. Le plus logique est de faire une injection de dll.

On va donc commencer par réaliser une dll qui exporte une procédure avec le même prototype que la fonction que l'on souhaite hooker.

Un exemple est dans le répertoire InjectedDll.

Cette dll exporte ShellAboutW, la même procédure que celle exportée par la dll shell32.dll.
Cette fonction est utilisée par de nombreux programmes sous windows (calc, mspaint, notepad...) lorsque l'on demande leur "A propos de ..."

On va afficher une boîte de dialogue juste avant d'afficher la boîte standard.

La méthode d'injection de la dll utilisée est détaillée au chapitre 22 de "Programming Applications for Microsoft Windows", de Richter.


#### Remplacement de la fonction :

Le remplacement de la fonction peut par exemple se faire dans la fonction d'initialisation de la dll injectée. La table d'import est parcourue à la recherche de la fonction à remplacer et est modifiée quand elle est trouvée.

La structure de la table d'import est détaillée la spécification pe/coff de M$.


#### Application finale :

L'application finale lance une instance de la calculatrice de Windows et injecte la dll dedans.

La principale difficulté lors de la réalisation de cette appli a été de lancer l'injection suffisement tard. Par exemple, avec CREATE_SUSPENDED, le loader de Windows ne charge même pas kernel32, ce qui conduit à l'échec de l'injection.

L'emploi d'un Sleep, bien que possible, est vraiment pas propre (Tiens y a un jeu de mot là. Vivi je sors.).

La meilleur solution que j'ai trouvé a d'utiliser DEBUG_PROCESS. Bien pratique : on est informé des chargement de modules.

J'ai cependant dû rajouter un thread à cause d'un deadlock : le processus débogué attendais que le débogueur acquitte la création du thread, tandis que le débogueur attendais la fin du thread d'injection...



 Conclusion

pecoff :
http://www.google.fr/url?sa=t&ct=res&cd=1&url=ht tp%3A%2F%2Fdownload.microsoft.com%2Fdownload%2F9%2 Fc%2F5%2F9c5b2167-8017-4bae-9fde-d599bac8184a%2Fpe coff_v8.doc&ei=3TtmR72cBpuE-AL9gcHhDg&usg=AFQjCNFW FOT82_HIP-d2tbvX405t0FMMXQ&sig2=vGR7fJT3DiGgj6dEA7 NitQ

Richter :
http://brunews.free.fr/brunews/download/JR4.zip

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip Source avec une capture LIBÉRER LA TAILLE MAXIMALE D'UNE FENÊTRE PAR SUBCLASSING
Source avec Zip Source avec une capture [WIN32]ECHANGE INTER-PROCESSUS VIA SHAREDMEMORY, MUTEX ET EV...
Source avec Zip Source avec une capture FENÊTRE UN PEU CUSTOMISÉE
Source avec Zip Source avec une capture LE MINIMUM POUR UNE FENÊTRE WIN32
Source avec Zip Source avec une capture RÉDACTEUR D'UNITÉ DE CHARGEMENT DYNAMIQUE DE DLL

 Sources de la même categorie

Source avec Zip LECTURE DE LA MEMOIRE D'UN AUTRE PROCESSUS par Mokost
Source avec Zip Source avec une capture LIBÉRER LA TAILLE MAXIMALE D'UNE FENÊTRE PAR SUBCLASSING par rt15
Source avec Zip Source avec une capture OBSERVATEUR DE PROCESSUS ACTIFS; VPROCESS 1,0 par Neftali
UN SELECTDIRECTORY QUI SE PLACE AU BON ENDROIT par ThWilliam
Source avec une capture VOTRE PROGRAMME DE MAIL COMME CLIENT MAIL PAR DÉFAUT SOUS WI... par MAURICIO

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture KINECT TEST V1 par FFCAST
Source avec Zip Source avec une capture COMPOSANT TLOG UTILISANT UNE DLL par Bacterius
Source avec Zip CHARGEMENT D'UNE DLL SANS DLL par DelphiCool
Source avec Zip INJECTER DLL DANS UN PROCESSUS EN COURS par elguevel
Source avec Zip Source avec une capture REMPLACER UNE FONCTION D'UNE DLL PAR N'IMPORTE QUELLE AUTRE! par Forman

Commentaires et avis

Commentaire de Caribensila le 17/12/2007 11:18:51

Salut,

Eh bein!..
Ca nous change du SIMOBROWSER.
Tu pourrais peut-être pousser jusqu'au niveau «expert», non?  ;)

Commentaire de f0xi le 17/12/2007 17:21:23 administrateur CS 9/10

Houla! clair que c'est pas jo l'rigolo l'brunews :)

en tout cas ça m'a l'air bien costaud, bien programmé, même si j'ai pas tout tester.

le seul truc qui m'ennerve dans ce code c'est ça :

procedure ConsolePause();

sans arguments .... pas de parenthese! on est pas en C/C++  et t'es plus un debutant maintenant :)

par contre pour le niveau expert ... mmm ... je me demande si c'est vraiment utile. il est vrai que faut deja avoir un bon niveau pour bien comprendre la source.

Commentaire de rt15 le 17/12/2007 17:45:33 administrateur CS

f0xi -> Ca m'est venu très récemment le coup des parenthèses. Je me suis dit : pourquoi pas ?
Bah maintenant j'ai ma réponse...

Je mettrai mes sources dans "expert" quand j'emploierai des fonctions de M$ non documentées par M$. Niark niark.

Commentaire de WhiteHippo le 17/12/2007 19:32:12

Salut à tous,

Désolé foxi, mais je sens que je vais encore faire le rabat-joie doublé du pinailleur de service ... et surtout t'enerver encore plus ;)

"procedure ConsolePause();
sans arguments .... pas de parenthese! on est pas en C/C++  et t'es plus un debutant maintenant :)"

Ben justement, je pense que c'est parce que l'on est plus un débutant que l'on peut se permettre ces choses là. :P  Un code "initié" ou "expert" peut se le permettre, car il ne s'adresse pas aux mêmes personnes que le code "débutant".

Moi j'utilise régulièrement les parenthèses pour mes appels de fonctions ou de procédure, je pousse même le vice encore plus loin (N.B. je ne sais pas si la police de caractère employés pour les commentaires refletera correctement la disposition du code suivant) :

procedure MaProcedureSansParametres
  (
  )
;
begin
  // ...
end ;

N.B. Pour ceux qui voudraient me faire remarquer que la procédure sans paramètres occupe trois lignes alors qu'elle pourrait n'en utiliser qu'une, je sais et alors... Le compilateur comprends parfaitement le code donc il n'y a pas de problèmes ;D Juste une façon différente de voir les choses. Vive la différence !!

procedure MaProcedure
  ( var   MonParametre1 : MonType1  // Commentaire du MonParametre1
  ;       MonParametre2 : MonType2  // Commentaire du MonParametre2
  ; const MonParametre3 : MonType3  // Commentaire du MonParametre3
  )
; stdcall ;
begin
  // ...
end ;

Là encore, j'entends déjà les ronchons... Qu'est que fait un point virgule en début de ligne ? L'important là encore, et qu'il remplisse sa fonction de délimiteur. Et en plus, je trouve ça super esthétique ;P

function MaFonction
  ( const MonParametre1    : MonType1
  ; const MonParametre1bis : MonType1
  ; out   MonParametre3    : MonType3
  )      {Result}          : MonTypeResultat
;
begin
  // ...
end ;

Là, on fait apparaitre le result, défini par défaut dans chacune des fonctions. A quoi ça sert ? Ben je viens de le dire à le faire apparaitre :)

Pourquoi, ecrire et disposer le code ainsi ?
Plusieurs raisons à cela :
  - Le décalage entre deux paramètres en est grandement facilité.
  - L'insertion d'un nouveau paramètre (d'une ligne) se fait aisément.
  - La clarté du code est, pour moi, meilleure ainsi.
  - La sélection et/ou la suppression ("par colonne") est alors pleinement exploitable.

Bref, si c'est juste histoire de mettre des parenthèses, pas d'intérêts. Par contre si c'est en prévision de modifications futures, alors je suis plus que pour rt15. Et pour tous ceux, qui comme foxi sont enervés à la simple vue d'un code quelques peu différent, il reste toujours des outils de formattage de code tel DelForExp.

P.S. Entre commenter ton code rt15, et taquiner foxi, le choix à été vite fait... Patience, je regarde ça bientôt.

Cordialement.

Commentaire de WhiteHippo le 17/12/2007 19:36:24

Comme je le pensais, la police ne convient pas pour le code. Une copie sous Delphi ou bien dans un editeur de texte avec du Courier Nex par exemple, permettra de le faire apparaitre tel qu'il aurait du apparaitre.

Cordialement.

Commentaire de Oniria le 19/12/2007 10:33:43

Bonjour,

Je voulais juste savoir si c'est cette méthode qu'il faut utiliser pour créer un sniffer de port RS232 ?

En tout cas bravo.

Oniria

Commentaire de rt15 le 19/12/2007 12:32:45 administrateur CS

Les sniffeurs de réseaux sont généralement implantés plus bas au niveau des drivers, mais certains utilisent en effet des hooks pour espionner la socket d'un processus en particulier.

Pour le rs232, je sais pas, mais si tu veux juste espionner une application en particulier cette méthode marcherait peut être, le tout est de trouver les fonctions qu'elle utilise.

Par exemple, elle peut utiliser RSCOM.DLL :
http://delphipage.free.fr/portserie.html

ou encore WriteFile :
http://www.delphifr.com/codes/EAGLE-ENSEMBLE-FONCTIONS-UTILES-FICHIERS-SYSTEME-STRINGS-RS232_30232.aspx

Commentaire de jeanr le 19/12/2007 18:36:52 10/10

Belle source, super bien documentée et expliquée, merci :-)

Commentaire de Yooda le 15/07/2008 01:44:45

Superbe source... Et merci pour la blague sur le "string" ;) Ca détend....

juste une question:
Comment faire pour "Hooker" une fonction exporté dans l'exe et non importé à partir de la DLL ?

ansi dans mon code j'ai :
-----------------
implementation

{$R *.dfm}
function SommeINCLUDE(A, B: Integer): Integer;
begin
result:=A+B;
end;


exports SommeINCLUDE;
end.
-----------------
SommeINCLUDE est donc Exporté... Et non importé certes. Mais les mécanismes sont les mêmes. Ne peut on pas ce basé sur ce code pour "Hooké" sommeINCLUDE ?

Commentaire de rt15 le 15/07/2008 11:45:45 administrateur CS

Cela marcherait si le code de l'exe passait par sa propre table d'export pour appeler cette fonction. Mais il serait stupide de passer par celle-ci pour récupérer une adresse que l'on connait déjà. Donc il y a peu de chance que des compilos le fasse.

Par contre...

Ton exe exporte la fonction, donc tu peux facilement récupérer son adresse dans le processus distant (Pour cela, on peut exploiter la technique d'injection de ce source). Une fois que l'on a l'adresse de cette fonction, rien n'empèche de modifier le début du code de cette fonction pour appeler une fonction à nous, injectée elle aussi.

1. Injection d'une dll dans le processus distant, via la technique de ce source ou autre.

2. Dans le code de la dll, récupérer un handle du .exe avec GetModuleHandle.

3. Récupérer l'adresse de la fonction exportée avec GetProcAdresse, en lui passant le handle du .exe.

4. Modifier le début de la fonction exporté (Ecriture à l'adresse ci-dessus). La fonction commence très certainement par un :
push ebp
mov ebp, esp

(Les compilos Microsoft mettent généralement un mov edi,edi en début de fonction, idéal pour un hook)

Remplacer ce début par un jmp vers une fonction de la dll que l'on a injecté.

5. La fonction de la dll qui va récupérer les appel doit faire le début qui a été remplacé, et doit faire un saut vers la fonction originale à la fin.

Bien qu'un peu technique, c'est très faisable.
Par contre, je ne vois pas dans quel cas ce serait utile...

Commentaire de Yooda le 15/07/2008 11:52:42

Certains exe, exporte des fonctions. Je suppose pour inter-opérabilité avec d'autres softs.  C'est justement ce que je cherche a faire... ;)

Je teste cette piste, merci :)


Commentaire de strobinateur le 19/07/2011 17:01:02 10/10

Merci, c'est une très bonne source !

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Hook dll : comment ca marche ? [ par Millenius ] Bonjour, je voudrais hooker un dll.Le clavier et la souris, ca je sais faire.Ce que je voudrais, c pouvoir connaitre les flux de données entrant et so Dll injection dans iexplore [ par achraf1986 ] Salut a tous !!! j'ai chercher dans tous le net mais j'ai pas trouver un source qui montre comment ajouter un boutton dans Internet explorer alors aid Hook sans dll, c'est possible , mais comment ? [ par jace1975 ] salut à tous je travaille actuellement sur une application, pour me permettre notamment de  killer immédiatement le processus en c Dll injection [WindowsExplorer Toolbar] [ par AgentAmine ] salut tous, Je veux créer un programme pour changer les icônes de ImageList de toolbar de WindowsExplorer, en utilisant l'api ImageList_ReplaceIcon; Delphi 2009 DLL Dotnet [ par CARAB1 ] Bonjour, Je n'arrive pas à utiliser une DLL d'un fournisseur (de CAO) sous Delphi 2009. Cette DLL est écrite en VB .Net (PowerSolutionDOTNetOLE.DLL + import data from excell to oracle 10g [ par sharifcrd ] sharif bon jour qlq sait comment importer les donnes de excell vers oracle 10g impossible de charger l evaluateur comp32p.dll [ par devdel ] bonjour , comment est ce qu'on peut trouver une solution à ce message merci d'avance Comment utiliser une DLL depuis un composant ? [ par drexl ] Bonjour a tous et bonne année, J'ai fait une DLL (paramétrage d'un appareil) que j'utilise depuis mon programme. Pour "simplifier l'utilisation" de l Ouvrir un fichier .exe ou .dll sous forme hexa [ par delphi ] Comment faire pour ouvrir un fichier .exe ou .dll sous son format Hexadecimal et modifier un octet ou mot donné. Inserer une DLL... [ par Delphi ] Salut, je voudrai savoir comment je dois inserer une dll avec delphi pour pouvoir utiliser cette dll svp ?


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,574 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales