Bonsoir le forum,

Je me casse les dents sur un sujet depuis deux jours, je me décide donc à faire appel à votre aide !

J'ai un exécutable qui se charge de dialoguer avec un automate pour récupérer des données mais qui pour une raison inconnue se crache et il arrive que certaines données soient perdues ! J'ai donc créée un nouveau logiciel qui permet de détecter sa disparition des processus et de le relancer mais cela ne règle pas mon problème de perte de données.

J'ai donc décidé d'essayer de détecter lorsque le logiciel se fait tué afin de créée un fichier de log avec le nom du processus qui l'a tué avant qu'il soit tué. Bien évidemment comme TerminateProcess intervient à bas niveau il n'est pas possible d'intervenir directement. J'ai continué mes recherches et j'ai découvert qu'il fallait hooker le dit processus pour injecter une dll qui pourra réaliser le fichier de log.

J'ai donc trouvé une source en Delphi sur le site suivant intitulé "MagicApiHook" qui contient un exemple de Hook de TerminateProcess et plus exactement "zwTerminateProcess" de l'Api "ntdll.dll" mais le problème c'est que l'exemple permet d'mpêcher un processus de se terminer comme un antivirus par exemple alors que moi je veux juste écrire un fichier de log avant qu'il se termine et non pas l'empêcher de se terminer.

Le code exemple (loader.exe) se comporte de la façon suivante :

- Injection de la dll pour tous les processus actifs
- test via ctrl alt suppr pour terminer le processus loader.exe (ne fonctionne pas c'est le but du code)
- fermeture de façon normale via la croix de la fichie principale de loader.exe
- Libération de la dll pour tous les processus

Voici des extraits du code utile pour illustrer les propos ci-dessus :

Code du logiciel de chargement :
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
program Loader;
 
uses Windows, MagicApiHook;
 
var
 Dllname:string='ProtectProcess.dll';
 F: THandle;
 PID,Cnt: DWORD;
 
begin
 if not IsWinNt then begin
  MessageBox(0,'Sorry...just for WinNT...','Error...',MB_ICONERROR);
  Exit;
 end;
 if not IsFileExist(DllName) then begin
  MessageBox(0,Pchar('File not found : '+DllName),'Error...',MB_ICONERROR);
  Exit;
 end;
 PID:=GetCurrentProcessID;
 F:=CreateFileA(Pchar(GetPath(Paramstr(0))+'PID.dat'),GENERIC_READ or GENERIC_WRITE,
                FILE_SHARE_READ or FILE_SHARE_WRITE,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
 if F=INVALID_HANDLE_VALUE then begin
  MessageBox(0,'Can not Create ProcessID file...','Error...',MB_ICONERROR);
  Exit;
 end;
 WriteFile(F,PID,SizeOf(PID),Cnt,nil);
 CloseHandle(F);
 DebugPrivilege(True);
 InjectAllProc(GetPath(ParamStr(0))+DllName);
 MessageBox(0,'TerminateProcess Hook Installed...'#13#10+
              'Now Try to Terminate Me !'#13#10#13#10+
              'Press OK to UnInstall Hook...',
              'Success... Magic_h2001',MB_ICONINFORMATION);
 UnInjectAllProc(GetPath(ParamStr(0))+DllName);
end.
Extraits de code de la dll :
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
procedure DLLEntryPoint(dwReason:DWORD);
begin
 case dwReason of
   DLL_PROCESS_ATTACH: begin
     ApiHook('ntdll.dll','ZwTerminateProcess',nil,@HookZwTerminateProcess,@MainZwTerminateProcess);
     ApiHook('kernel32.dll','CreateProcessInternalW',nil,@HookCreateProcessInternalW,@MainCreateProcessInternalW);
     ApiHook('kernel32.dll','OpenProcess',nil,@HookOpenProcess,@MainOpenProcess);
     ApiHook('advapi32.dll','CreateProcessAsUserA',nil,@HookCreateProcessAsUserA,@MainCreateProcessAsUserA);
     ApiHook('advapi32.dll','CreateProcessAsUserW',nil,@HookCreateProcessAsUserW,@MainCreateProcessAsUserW);
     GetModuleFileName(GetModuleHandle(Pchar(DllName)),DllPath,SizeOf(DllPath));
     PID:=$FFFFFFFF;
     F:=CreateFileA(Pchar(GetPath(DllPath)+'PID.dat'),GENERIC_READ,FILE_SHARE_READ or
                    FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
     if F<>INVALID_HANDLE_VALUE then begin
      ReadFile(F,PID,SizeOf(PID),Cnt,nil);
      CloseHandle(F);
     end;
   end;
   DLL_PROCESS_DETACH: begin
     ApiUnHook('ntdll.dll','ZwTerminateProcess',nil,@HookZwTerminateProcess,@MainZwTerminateProcess);
     ApiUnHook('kernel32.dll','CreateProcessInternalW',nil,@HookCreateProcessInternalW,@MainCreateProcessInternalW);
     ApiUnHook('kernel32.dll','OpenProcess',nil,@HookOpenProcess,@MainOpenProcess);
     ApiUnHook('advapi32.dll','CreateProcessAsUserA',nil,@HookCreateProcessAsUserA,@MainCreateProcessAsUserA);
     ApiUnHook('advapi32.dll','CreateProcessAsUserW',nil,@HookCreateProcessAsUserW,@MainCreateProcessAsUserW);
   end;
 end;
end;
(******************************************************************************)
begin
 DllProc:=@DLLEntryPoint;
 DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
function HookZwTerminateProcess(hProcess: THandle; uExitCode: UINT): BOOL; stdcall;
begin
 if PHandleToPID(hProcess)=PID then begin
  Result:=False;
  SetLastError(ERROR_ACCESS_DENIED);
 end
 else Result:=MainZwTerminateProcess(hProcess,uExitCode);
end;
Dans la dernière fonciton "HookzwTerminateProcess" j'ai essayé de mettre le code pour générer le fichier de log avant result := False mais cela ne fonctionne pas ! J'ai effectué d'autres tests pas plus concluants qui m'ont valus quelques écrans bleu dûs à la non libération de dll !

Je me tourne donc vers vous pour savoir si quelqu'un aurait une piste pour m'aider.

Je vous remercie par avance de votre aide,

DelphiCode