IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

Comment surcharger (hook) n'importe quelle API windows ? [Sources]


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre averti
    Inscrit en
    Juin 2004
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 18
    Par défaut Comment surcharger (hook) n'importe quelle API windows ?
    Pour faciliter la recherche des utilisateurs du forum je copie colle une partie d'un post en rennomant le sujet.

    Le poste original était : Surveiller la base de registre.

    De fils en aiguille j'ai découvert un principe très interessant voià un résumé de cette recherche


    Voila je vais donc essayer de vous faire une petit topo sur cette méthode. Ce topo ne sera pas complet je compte sur vos compétences pour me reprendre sur quelque points ou pour apporter des précisions à mon propos.

    1) Point de départ :
    Je cherchais donc comment faire un hook sur la base de registre.

    a - première solution imcomplète : RegNotifyChangeKeyValue.
    Cette solution est expliquée ici : http://delphi.about.com/od/kbwinshell/l/aa052003a.htm

    Le gros défaut de cette solution est qu'elle ne renvoie pas la clé qui a subit une modification. Elle notifie seulement un changement.

    b - deuxième solution envisagée : le principe qu'utilise regmon. Là j'ai été un peu perturbé car le procédé utilise des fonctions non documentées de xp et que tout cela me paraissait un peu trop pointu. Pour info je vous donne différent liens dont j'ai cru comprendre qu'ils traitaient plus ou moins du sujet.

    http://www.eviloctal.com/forum/htm_d...603/20388.html

    et le site de regmon

    http://www.sysinternals.com/Utilities/Regmon.html (voir l'explication : "How Regmon Works")

    Peut-être aussi un référence bibliogrpahique :

    http://www.amazon.com/gp/product/020...lance&n=283155

    c - La solution utilisant le principe de Mathias Rauen (je décrirai plus bas cette méthode)

    En gros cette méthode permet de hooker n'importe quelle fonction API de windows. Pour le moment j'ai juste fait un hook sur RegOpenKey cela reste donc incomplet, mais le principe est vraiment très prometteur.

    2) Description du principe de Mathias Rauen

    Alors là je vais tenter une explication, mais je me reserve le droit d'être approximatif

    Les API windows sont donc chargées par le système et les programmes à partir des dll natives de windows. Par exemple on sait que TerminateProcess se trouve dans kernel32.dll. Quand un programme ou un utilisateur demande au systeme de terminer un process celui ci fait appel a cette fonction. Imaginons maintenant qu'il soit possible de surcharger cette fonction. C'est à dire d'executer un bout de code personnel au moment de son appel. On pourrait donc par exemple refuser qu'un processus donné soit terminé sans autorisation.

    Ceci est possible grâce au procédé développé par Mathias Rauen. Ce principe permet donc d'injecter la fonction surchargée d'une fonction originale (API) en lieu et place de celle-ci dans le système (system wide). D'ailleurs si quelqu'un veut bien m'expliquer ce que recouvre exactement ce terme (system wide) utilisé pas Mathias je suis preneur.

    L'ecriture de la fonction surchargée doit se faire dans une dl qui elle sera injecté dans le système.

    Pour développé un projet permettant cette injection il faut télécharger la collection de composants ici : http://madshi.net/madCollection.exe. Le composant qui nous interesse plus particulièrement est nommé madCodeHook.

    L'install registre une dcu "madCodeHook.dcu" et fournit une dll madCHook.dll nécessaire à l'injection.

    Pour résumé :

    on crée un dll contenant la fonction API surchargée. Cette dll est injectée dans le system à l'aide des fonctions contenues dans "madCodeHook.dcu" et de la dll "madCHook.dll". A mon avis c'est la dcu qui fait appel à "madCodeHook.dcu" .

    3) Passons à la pratique

    a - D'abord l'exemple de de l'auteur : http://help.madshi.net/HowToUseMadCodeHook.htm
    Cet exemple nous montre comment hooker l'API TerminanteProcess en autorisant ou non l'arrêt d'un processus donné.

    b - Maintenant mon exemple :
    Je vais en suivant Mathias hooker la fonction RegOpenKey qui est dans advapi32.dll.

    Ecriture de la dll surchargeant RegOpenKey :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    library HookRegOpenKey;
    uses dialogs,classes,Sysutils, Windows, madRemote, madCodeHook, madStrings;
     
    // variable représentant l'api originale "function RegOpenKey(hKey: HKEY; lpSubKey: PChar; var phkResult: HKEY): Longint; stdcall;"
     
    var RegOpenKeyNext : function (HandleKey: Dword; lpSubKey: PChar; var phkResult: Dword): Longint; stdcall;
     
    // Fonction surchargée
     
    function RegOpenKeyCallback(HandleKey: Dword; lpSubKey: PChar; var phkResult: Dword) : Longint; stdcall;
    Var
    Str : TStringList;
    RootKey : string;
    begin
        // On renvoie la fonction originale pour que la demande soit bien prise en compte
        result := RegOpenKeyNext(HandleKey, lpSubKey,phkResult);
        // surcharge par mon code perso j'ouvre un fichier log ou seront enregistrer les infos
        Str:=TStringList.Create;
        If fileExists('c:\regkey.txt') Then Str.LoadFromFile('c:\regkey.txt');
        Case HandleKey Of
          HKEY_CLASSES_ROOT : RootKey := 'HKEY_CLASSES_ROOT\';
          HKEY_CURRENT_USER : RootKey := 'HKEY_CURRENT_USER\';
          HKEY_LOCAL_MACHINE : RootKey := 'HKEY_LOCAL_MACHINE\';
          HKEY_USERS : RootKey := 'HKEY_USERS\';
          HKEY_CURRENT_CONFIG : RootKey := 'HKEY_CURRENT_CONFIG\';
        End;
        Str.Add('-----------------');
        Str.Add(DateTimeToStr(Now) + ' : RegOpenKey called');
        Str.Add(RootKey + lpSubKey);
        Str.Add('-----------------');
        Str.SaveToFile('c:\regkey.txt');
        Str.Free;
    end;
    begin
    // HookAPI provient de madCodeHook.dcu et permet de subsituer la fonction surchargée à l'API originale.  
    HookAPI('advapi32.dll', 'RegOpenKeyA', @RegOpenKeyCallback, @RegOpenKeyNext);
    end.
    Remarque importante : La fonction surchargée doit impérativement respecter les conventions d'écriture (paramètres et variables) de l'originale.

    Maintenant l'ecriture du projet permettant l'injection :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    unit InjectUnit;
    interface
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, madCodeHook,
      StdCtrls;
    type
      TForm1 = class(TForm)
        ButtonHook: TButton;
        ButtonUnHook: TButton;
        procedure ButtonHookClick(Sender: TObject);
        procedure ButtonUnHookClick(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
    var
      Form1: TForm1;
    implementation
    {$R *.DFM}
    procedure TForm1.ButtonHookClick(Sender: TObject);
    begin
      InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'HookRegOpenKey.dll');
    end;
    procedure TForm1.ButtonUnHookClick(Sender: TObject);
    begin
    UninjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'HookRegOpenKey.dll');
    end;
    end.
    Voila il suffit d'utiliser InjectLibrary pour Hooker et UninjectLibrary pour UnHooker.

    PS : scusez pour les fautes d'orthographe je fait des efforts mais c'est souvent en vain.

    Quand j'aurai monté le projet global je vous le ferai parvenir. Car il me reste un autre point a résoudre : connaitre le processus qui vient d'accéder à la base de registre. Il faut aussi que je surcharge les appels aux fonctions d'écriture dans la base.

    Raziel

  2. #2
    Membre éclairé

    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2003
    Messages
    286
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 286
    Par défaut
    mhhhh ... intéressant
    sympa de partager tes recherches, les librairies de Mathias Rauen m'ont l'air assez impressionnantes ...

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 477
    Par défaut
    salut


    le principe est assez simple microsoft met a notre disposition une api permettant d'injecter du code

    -pour info les virus utilise souvent cettte posibilite
    faite une recherche su et et voila une utilisation possible
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
     
    uses tlhelp32;
     
    procedure GetMyProcessID(const AFilename: string; const PathMatch: Boolean; var ProcessID: DWORD);
    var
      lppe: TProcessEntry32;
      SsHandle: Thandle;
      FoundAProc, FoundOK: boolean;
    begin
      ProcessID :=0;
      SsHandle := CreateToolHelp32SnapShot(TH32CS_SnapProcess, 0);
     
      lppe.dwSize := sizeof(TProcessEntry32);
      FoundAProc := Process32First(Sshandle, lppe);
      while FoundAProc do
      begin
        if PathMatch then
          FoundOK := AnsiStricomp(lppe.szExefile, PChar(AFilename)) = 0
        else
          FoundOK := AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)), PChar(ExtractFilename(AFilename))) = 0;
        if FoundOK then
        begin
          ProcessID := lppe.th32ProcessID;
          break;
        end;
        FoundAProc := Process32Next(SsHandle, lppe);
      end;
      CloseHandle(SsHandle);
    end;
     
     
    function EnabledDebugPrivilege(const Enabled : Boolean) : Boolean;
    var
      hTk : THandle;
      rtnTemp : Dword;
      TokenPri : TOKEN_PRIVILEGES;
    const
      SE_DEBUG = 'SeDebugPrivilege';
    begin
      Result := False;
      if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hTk)) then
      begin
        TokenPri.PrivilegeCount := 1;
        LookupPrivilegeValue(nil,SE_DEBUG,TokenPri.Privileges[0].Luid);
     
        if Enabled then
          TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
        else
          TokenPri.Privileges[0].Attributes := 0;
     
        rtnTemp := 0;
        AdjustTokenPrivileges(hTk,False,TokenPri,sizeof(TokenPri),nil,rtnTemp);
     
        Result := GetLastError = ERROR_SUCCESS;
        CloseHandle(hTk);
     
      end;
    end;
     
    function InjectTo(const Host, Guest: string; const PID: DWORD = 0): DWORD;
    var
      hRemoteProcess: THandle;
      dwRemoteProcessId: DWORD;
     
      memSize: DWORD;
     
      pszLibFileRemote: Pointer;
     
      iReturnCode: Boolean;
      TempVar: DWORD;
     
      pfnStartAddr: TFNThreadStartRoutine;
     
      pszLibAFilename: PwideChar;
    begin
      Result := 0;
      EnabledDebugPrivilege(True);
     
      Getmem(pszLibAFilename, Length(Guest) * 2 + 1);
      StringToWideChar(Guest, pszLibAFilename, Length(Guest) * 2 + 1);
     
      if PID > 0 then
         dwRemoteProcessID := PID
      else
         GetMyProcessID(Host, False, dwRemoteProcessID);
     
      hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + 
          PROCESS_VM_OPERATION + 
          PROCESS_VM_WRITE, 
          FALSE, dwRemoteProcessId);
     
      memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
      pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE));
      TempVar := 0;
      iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, TempVar);
     
      if iReturnCode then
      begin
        pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
        TempVar := 0;
        Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
      end;
      Freemem(pszLibAFilename);
    end;
    @+ Phil

  4. #4
    Membre éclairé

    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2003
    Messages
    286
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2003
    Messages : 286
    Par défaut
    Encore un plus gros merci pour ce code qui est bien sympathique (et assez technique ....)

  5. #5
    Membre Expert
    Avatar de NoisetteProd
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    1 905
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 905
    Par défaut
    N'hésitez pas à proposer vos sources : http://www.developpez.net/forums/showthread.php?t=11501 ou bien contactez moi par MP.


  6. #6
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 477
    Par défaut
    salut

    le code n'est malheureusement pas de moi je l'ai recupere sur un site chinois

    sinon plus explicite voila du code russe

    http://www.sources.ru/magazine/0505/st.html

    @+ Phil

  7. #7
    Membre Expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 54
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Par défaut
    Pour info, j'ai trouvé un tuto sur le problême qui intéresse ce fil.
    ça a peut être été déjà posté, mais bon, voilà :
    http://perso.orange.fr/bardou/michel/hook/hooks.htm

  8. #8
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Tiens ca me fait penser a un autre post ya pas si longtemps ....
    Il ne serait pas possible de remplacer la DLL hooké par une de ton cru, exportant les memes focntions, et qui appelle les fonctions de la vraie dll renommée, avec en plus pour certaines d'entre elles ton code supplementaire ?

  9. #9
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 477
    Par défaut
    salut

    euh comment le dire sans que vous vous fachiez ... ce fils est resolue depuis plus d'un an

    @+ Phil

  10. #10
    Membre confirmé
    Profil pro
    Directeur
    Inscrit en
    Juin 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Directeur

    Informations forums :
    Inscription : Juin 2005
    Messages : 113
    Par défaut
    Dsl de remonter un vieux topic, c'est just pour répondre a une question:
    The primary role of windows hooks is to monitor the message traffic of some thread. In general there are:

    1. Local hooks, where you monitor the message traffic of any thread belonging to your process.
    2. Remote hooks, which can be:
    1. thread-specific, to monitor the message traffic of a thread belonging to another process;
    2. system-wide, to monitor the message traffic for all threads currently running on the system.

  11. #11
    Invité de passage
    Homme Profil pro
    Développeur en delphi
    Inscrit en
    Mai 2020
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur en delphi
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2020
    Messages : 1
    Par défaut madCodeHook
    Stp est ce que c'est possible d'avoir le composant madCodeHook ???

  12. #12
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 910
    Billets dans le blog
    6
    Par défaut
    Oui, ici. Mais c'est payant et d'accès restreint pour éviter les dérives d'utilisations malhonnêtes.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    404
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 404
    Par défaut
    tu peux toujours essayer DDetours

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 03/12/2010, 15h13
  2. Réponses: 2
    Dernier message: 03/10/2009, 07h51
  3. Comment reconnaitre le type de clavier (API windows)
    Par moulydi dans le forum Débuter
    Réponses: 8
    Dernier message: 08/07/2009, 15h58
  4. Réponses: 10
    Dernier message: 26/03/2008, 17h23
  5. Réponses: 69
    Dernier message: 15/06/2006, 11h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo