REMPLACER UNE FONCTION D'UNE DLL PAR N'IMPORTE QUELLE AUTRE!

John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009 - 8 juil. 2006 à 10:09
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 - 20 oct. 2008 à 20:56
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/38484-remplacer-une-fonction-d-une-dll-par-n-importe-quelle-autre

cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 20:56
Il y a la réponse ici:
http://www.dependencywalker.com/help/html/interpreting_errors.htm
(voir le paragraphe qui commence par "Delay-load dependencies")

Donc apparemment c'est un import retardé, avec un système que ma fonction ne peut pas patcher tel quel. Finalement, peut-être que ça pourrait marcher en patchant GetProcAdress sur toutes les DLL chargées, et en recommençant à intervalles réguliers (au cas où une nouvelle DLL apparait), voire même en patchant LoadLibrary pour détecter toutes nouvelle DLL qui est chargée... bon courage!
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 20:33
Je viens d'essayer avec la fonction ReplaceAllImportedAPI mais malheureusement wtsapi32.dll n'est pas énuméré. N'ayant jamais utilisé Dependency Walker auparavant, je me posais une question: Devant WTSAPI32.dll il y a un sablier, qu'est-ce que ca signifie exactement?
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 20:16
Oui ça devrait marcher, si la méthode que j'ai utilisée plus haut (avec CreateToolhelp32Snapshot) énumère bien toutes les DLL chargées. Eventuellement, tu peux faire un ShowMessage avec toutes les DLL trouvées dans la boucle, pour vérifier que Wtsapi32.dll est dans la liste.
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 20:08
Oui, pour commencer j'Avais juste mit un ShowMessage dans la procédure et je renvoyais rien (histoire de voir si ca l'Avais réellement un impact) et effectivement il y en avait un. Je viens d'installer Dependency Walker et je voit que Wtsapi32.dll ne semble pas être chargé par l'appli mais bien par: Winscard.dll qui est chargé par rasdlg.dll qui est chargé par wininet.dll qui est chargé par shell32.dll qui est chargé par mon EXE (si j'ai bien compris le tree qui a sorti). Donc j'imagine que si j'utilise ta fonction mentionné plus haut dans les commentaires il y aurait moyen de faire fonctionner le tout?

Merci encore, l'aide est vraiment apprécié!!
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 20:02
Sinon le code que tu as mis plus haut a l'air parfaitement valide. Quand tu as fait des essais avec GetSystemMetrics, est-ce aue tu as effectivement observé des changements dans le comportement de l'exe?
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 20:01
Peut-être qu'il faut utiliser 'GetProcAddressA' ou 'GetProcAddressW'? (il faudrait relire la MSDN en détails à ce sujet).

Tu peux aussi essayer d'utiliser un soft du genre Dependency Walker pour voir quelles sont les API qui sont effectivement chargées statiquement par ton exécutable. Il est possible que GetProcAddress ou WTS... soient utilisées non pas directement par l'exécutable, mais par une DLL que l'exécutable utilise... auquel cas il faudrait modifier mon code pour qu'il cherche dans la table d'import de la DLL en question et non pas dans celle de l'exe.
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 19:45
En réalité, je ne fait pas vraiment de méthode d'injection et j'expliquer pourquoi: Le logiciel que je veux modifier s'occupe de loader ma DLL. Donc, si je me trompe pas, c'est lui qui se charge de "l'injection". Présentement je suis en mesure de hooker les message windows de mon EXE (avec SetWindowLong) sans problème. En fesant quelques test, j'ai réussi à hook l'API GetSystemMetrics sans problème. Mais cela ne fonctionne pas avec WTS... et GetProcAddress. Voici le code que j'utilise pour GetProcAddress, peut-être qu'il est là le problème:

Quand ma DLL est loadé par le EXE:

h:=LoadLibrary(kernel32);
@GOldGetSysColor:=GetProcAddress(h,'GetProcAddress');
Assert(Assigned(@GOldGetSysColor));
if ReplaceAPI(kernel32,'GetProcAddress',@Test1) then begin
ShowMessage('True')
end else
begin
ShowMessage('False');
end;

Et voici le reste:

var
GOldGetSysColor:function(hModule : HMODULE; lpProcName: LPCSTR): Pointer; stdcall;

function Test1(hModule : HMODULE; lpProcName: LPCSTR): Pointer; stdcall;
begin
Result := GOldGetSysColor(hModule, lpProcName);
end;



Est-ce que je mit prend d'une mauvaise manière?

Merci
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 19:38
Ca m'étonnerait beaucoup que GetProcAdress soit dynamique! (sinon comment serait-elle chargée?)

Peut-être que le problème vient tout simplement de ta méthode d'injection. Est-ce que tu fais par exemple CreateRemoteThread sur l'adresse de LoadLibrary (avec ta DLL en paramètre) depuis un processus extérieur? Et dans ce cas, est-ce que tu fais le patch dans la procédure "main" de la DLL? Si c'est le cas essaie de lancer un thread depuis le "main" de la DLL qui va s'occuper de patcher les API désirées, car il se peut que le thread "temporaire" qui est créé pour le "main" de la DLL ne dispose pas de toutes les informations utilisées (image base, etc...).
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 19:31
Salut, quand j'essai d'utiliser ReplaceAPI avec GetProcAddress, j'ai le même problème qu'au début (ReplaceAPI retourne False). Est-ce possible que GetProcAddress soit lui aussi dynamique? Je n'ai pas essayé encore de faire un programme de lancement car je voulais commencer par modifier le GetProcAddress, mais ca ne fonctionne pas. Pense-tu qu'avec le programme de lancement ca pourrais changer quelquechose? (Si pour l'instant on met de côté le WTSQuerySessionInformationA).

Merci!
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 19:17
De rien.

En ce qui concerne le délai de 4 ou 5 secondes, il se peut quand même que l'API soit chargée avec GetProcAdress bien avant, auquel cas il faut quand même que tu la remplaces très vite!

Peut-être que ça peut être une bonne idée de faire un programme de lancement (qui utilise CreateProcess sur l'exe) avec le flag CREATE_SUSPENDED, patcher GetProcAdress à ce moment-là, puis faire un ResumeThread sur le thread principal du process une fois que c'est patché.
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 18:53
Salut, l'Exe est déjà compilé. Je crois qu'il n'y aurait pas de problème pour patcher GetProcAdress avant que WTSQuerySessionInformationA soit exécuté car cette fonction est utilisé apres 4 ou 5 secondes que l'appli est starté. Donc si je comprend bien, j'utilise ReplaceAPI pour GetProcAdress, et quand je recoit une requête pour charger WTSQuerySessionInformationA, je renvoit un pointeur vers ma nouvelle fonction. Ca serais très logique. Je vais essayer ca et je t'en redonne de nouvelles

Merci beaucoup encore une fois!
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 18:40
Re-

Ma fonction ne marche qu'avec les importations statiques (qui modifient effectivement la table d'import) et pas avec les importations dynamiques (pour lesquelles la table d'import n'est pas modifiée, l'adresse de la fonction importée pouvant se retrouver n'importe où dans la mémoire de l'exécutable). Dans le cas d'une importation dynamique on pourrait bien sûr faire une recherche toutes les secondes pour déterminer dans la mémoire virtuelle de l'exécutable si l'adresse de l'API apparait quelque part, et la remplacer par une autre adresse, mais ça ne parait pas souhaitable pour deux raisons:
-d'abord ça prend potentiellement beaucoup de temps d'explorer tout l'espace mémoire d'un processus (virtuellement plusieurs gigabytes de mémoire)
-si on est malchanceux on peut tomber sur une valeur égale à celle recherchée, mais qui n'a rien à voir (par exemple un int qui prendrait la même valeur et servirait à autre chose de vital!)

Par contre, rien ne t'empêche de patcher l'API GetProcAdress au moment du lancement de l'exécutable, pour la remplacer par une autre fonction qui, lorsqu'on l'appelle avec le nom 'WTSQuerySessionInformationA', renvoie l'adresse que tu veux (et qui a le même comportement que celle d'origine dans les autres cas). Toutes les API de User32.dll et Kernel32.dll sont chargées de manière statique normalement, donc dans ce cas là ça devrait fonctionner.

Ceci dit après c'est une course contre la vitesse de l'exécutable, car il faut que tu arrives à patcher GetProcAdress avant que celle-ci ne soit utilisée pour charger WTSQuerySessionInformationA. Est-ce que l'exe en question est déjà compilé ou tu en as les sources?
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 17:05
Salut, le code est présentement dans une DLL, mais c'est le EXE qui call l'API. Donc à ce niveau tout semble correct. J'ai utiliser le logiciel 'WinAPIOverride32' pour vérifier que le EXE exécute bien la fonction WTSQuerySessionInformationA. Je crois avoir une piste vers le problème. Je me demandais si la DLL n'était pas chargé dynamiquement. Si tel est le cas, de quel manière pourrais-je le déterminer? Y'a t'il un moyen d'utiliser ReplaceAPI si la DLL est chargé dynamiquement? (Genre avec un Timer qui vérifierais la table d'import à tous les 100 ms ou quelquechose du genre?)

Merci beaucoup pour l'aide!
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 05:16
Re,

Est-ce que tu es sûr que le programme dans lequel tu lances ma fonction utilise effectivement l'API WTSQuerySessionInformationA? Il ne suffit pas que tu fasses un import sur la fonction dans l'interface d'une unité (ça doit vraisemblablement être le cas dans ton code qui doit utiliser une unité du type wtsapi32.pas), il faut qu'en plus à un moment donné ton code l'utilise quelque part explicitement (je crois que le linker de Delphi repère les liens vers des procédures qui ne sont pas utilisées et les élimine de la table d'import pour optimiser l'exécutable). Pour être sûr, essaie de rajouter une fonction bidon à un endroit qui utilise l'API avec des paramètres bidons (par exemple dans un événement quelconque qui ne sera jamais déclenché). Vérifie aussi que ce n'est pas de la version WTSQuerySessionInformationW dont il s'agit. Il faut noter aussi que la fonction ne modifie que la table d'import de l'exécutable principal, si tu le fais depuis une DLL qui elle-même utilise WTSQuerySessionInformationA ça modifiera le comportement de l'API pour l'exécutable, pas pour la DLL (je ne sais pas si je suis très clair).

Si ça ne fonctionne toujours pas, je ne vois aucune explication possible, à moins que cette API ait des conventions d'import inhabituelles, mais ça me parait bizarre. Ca voudrait dire que le loader d'exécutable intégré à Windows serait programmé pour reconnaitre ce nom de fonction en particulier, et à appliquer des conventions différentes dans ce cas.

Autre piste: peut-être que la DLL wtsapi32.dll utilise un comportement similaire à celui de ma fonction pour modifier la table d'import des exécutables qui la chargent, par exemple un correctif de sécurité? Mais ça parait quand même improbable, en théorie ça peut causer des ennuis de stabilité de modifier la table d'import si l'exécutable n'a pas été réalisé en connaissance de cause (par exemple s'il inclut une protection antipiratage ou autre qui se base dessus).
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 03:12
Salut, merci pour la réponse. J'avais malheureusement déjà essayé en ajoutant .dll et j'ai le même problème. L'erreur qui est retourné est quand ReplaceAPI = False. Quand je fait un peu de debug, je voit qu'à la ligne 163 du code (celui que tu as posté sur cette page) la condition n'est jamais True, donc c'Est pour ca que ReplaceAPI retourne False. Par contre, je ne comprend pas pourquoi la ligne 163 je retourne jamais True.

Merci encore pour l'aide!
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
20 oct. 2008 à 00:53
Bonsoir,

essaie en mettant
ReplaceAPI('wtsapi32.dll','WTSQuerySessionInformationA',@Test1)

Sinon, je ne vois pas pourquoi ça ne marcherait pas... si mes souvenirs sont bons la fonction ReplaceAPI commence par faire un GetProcAddress sur l'API à remplacer, et c'est à ce moment-là que l'erreur que tu mentionnes peut se produire.
softkey Messages postés 110 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 20 octobre 2008
20 oct. 2008 à 00:42
Bonjour, tous dabord, je trouve cette source vraiment merveilleuse! J'ai un petit soucis par contre. J'essai d'utiliser cette fonction avec l'API 'WTSQuerySessionInformationA' dans la DLL 'Wtsapi32.dll'. Par contre, je n'arrive pas à le faire fonctionner (J'ai toujours l'erreur "Erreur: impossible de localiser l''API à remplacer".

Je mit prend de la manière suivante: ReplaceAPI('wtsapi32','WTSQuerySessionInformationA',@Test1) then begin

Merci !
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
12 mai 2008 à 20:29
Ben en fait j'ai trouvé ça sur MSDN:

CreateToolhelp32Snapshot
http://msdn.microsoft.com/en-us/library/ms682489(VS.85).aspx

Module32First
http://msdn.microsoft.com/en-us/library/ms684218(VS.85).aspx

et MODULEENTRY32 (renommé en TModuleEntry32 dans Delphi)
http://msdn.microsoft.com/en-us/library/ms684225(VS.85).aspx

Effectivement, à ce stade je ne vois hélas pas d'autre solution qu'un skinnage à l'ancienne... et c'est toujours un peu pénible à écrire.

Bonne prog
Forman
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
12 mai 2008 à 19:58
mdr et ouf!
merci de m'avoir prévenu. C'est donc un autre mécanisme qui entre en jeu. je crois que le mieux est de skinner l'ensemble afin de personnaliser en formes et couleurs. Moi qui croyais qu'il y avait une solution API simple et rapide.

Je commençais à me dire qu'il me fallait écrire en assembleur pour récupérer l'adresse mémoire des Dll utilisées par le programme. Mais je vois que tu as résolu la chose avec cette fonction digne de grand Forman!

Au fait, C'est quoi TModuleEntry32? un type que tu as déclaré, je ne le vois pas dans l'aide;

Bien à toi.
Jean_Jean
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
12 mai 2008 à 19:14
Ah oui au fait dans le code que j'ai mis plus haut il faut enlever le WriteLn(t)
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
12 mai 2008 à 19:13
Donc conclusion ça ne fonctionne pas pour changer les couleurs. J'ai aussi essayé de patcher GetSysColorBrush qui fait un peu la même chose mais en renvoyant un HBRUSH pour peindre, mais là encore ça ne donne rien.

Il semblerait donc qu'il faille utiliser une autre méthode...
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
12 mai 2008 à 19:11
Aïe avant que tu te lances: je viens de faire un essai en patchant GetSysColor pour toutes les DLL utilisées dans le programme de démo de ce source, et apparemment aucune des DLL windows utilisées ne l'utilise...

Voici la liste de celles qui sont utilisées, l'adresse de chargement et un booléen indiquant si elles importent ou non GetSysColor:
Project1.exe : 00400000 TRUE
ntdll.dll : 7C910000 FALSE
kernel32.dll : 7C800000 FALSE
user32.dll : 7E390000 FALSE
GDI32.dll : 77EF0000 FALSE
advapi32.dll : 77DA0000 FALSE
RPCRT4.dll : 77E50000 FALSE
oleaut32.dll : 770E0000 FALSE
msvcrt.dll : 77BE0000 FALSE
ole32.dll : 774A0000 FALSE
version.dll : 77BD0000 FALSE
comctl32.dll : 58B50000 FALSE
IMM32.DLL : 76320000 FALSE
uxtheme.dll : 5B090000 FALSE
msctfime.ime : 75140000 FALSE
comctl32.dll : 77390000 FALSE
SHLWAPI.dll : 77F40000 FALSE

J'ai utilisé cette fonction en remplacement de ma fonction ReplaceAPI originale:

function ReplaceAllImportedAPI(DllName:string;ProcName:string;NewProc:Pointer):Boolean;
var
ImageBase,OldProc,RedirectMem,LauncherCode:Pointer;
ImageDosHeader:TImageDosHeader;
ImageNTHeader:TImageNtHeaders;
n,LauncherSize:Cardinal;
Module:HModule;
h:THandle;
ME32:TModuleEntry32;
t:Boolean;
begin
Result:=False;
Module:=LoadLibrary(PChar(DllName));
OldProc:=GetProcAddress(Module,PChar(ProcName)); // Get the real API address
if not Assigned(OldProc) then
Assert(False,'Wrong library or procedure name'); // TODO: use Result:=False;Exit;
GetLauncherCode(LauncherCode,LauncherSize,NewProc);
try
RedirectMem:=VirtualAllocEx(GetCurrentProcess,nil,LauncherSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE); // Let's add some new code to the module ;-)
if not WriteProcessMemory(GetCurrentProcess,RedirectMem,LauncherCode,LauncherSize,n) then // Write the launcher code
RaiseLastOSError;
h:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId);
if h=0 then
RaiseLastOSError;
ZeroMemory(@ME32,SizeOf(ME32));
ME32.dwSize:=SizeOf(ME32);
if Module32First(h,ME32) then
repeat
ImageBase:=ME32.modBaseAddr;
if not ReadProcessMemory(GetCurrentProcess,ImageBase,@ImageDosHeader,SizeOf(ImageDosHeader),n) then // The DOS header is located at offset 0...
RaiseLastOSError;
if not ReadProcessMemory(GetCurrentProcess,Ptr(Integer(ImageBase)+ImageDosHeader._lfanew),@ImageNTHeader,SizeOf(ImageNTHeader),n) then
RaiseLastOSError; // The NT is located at offset _lfanew...
t:=RedirectAPI(DllName,Cardinal(OldProc),Cardinal(RedirectMem),Cardinal(ImageBase),@ImageDosHeader,@ImageNTHeader); // OK, here we go, let's modify the headers
writeln(t);
Result:=Result or t;
until not Module32Next(h,ME32);
CloseHandle(h);
finally
FreeMem(LauncherCode);
end;
end;
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 3
12 mai 2008 à 15:27
Merci beaucoup Forman pour toutes ces précisions!

Génial, tu m'a donné du boulot pour des mois au rythme où je programme en ce moment. Je crois que je vais publier mon code en l'état pour la semaine prochaine et réfléchir qu'elle piste je vais approfondir. Je pense que trouver l'adresse d'une DLL chargée ne doit pas être très compliqué bien que je ne l'ai jamais fait. J'ai été surpris de ne pas avoir accès aux sources windows. Si mes souvenirs sont bons, du temps où je programmais en BP7 et BPW, on avait accès aux fenêtres ou aux bitmap de boutons utilisés... Il faudrait demander à Mauricio!

Si tu n'y vois pas d'inconvénient, j'incluerai certains passages de tes explications (je l'ai déjà fait pour ton source) dans mon aide qui va devenir un tuto si ça continue! Il y vraiment des pistes intéresantes dans tout ce que tu écris...

Salutations delphistes!
Jean_Jean
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
12 mai 2008 à 13:45
Salut Jean_Jean

Mon code permet de changer la table d'import du processus, comme tu as dû le remarquer. Pour les speedbuttons, la partie "windows" de l'affichage est gérée par une DLL (je ne sais pas exactement laquelle). Cette DLL possède sa propre table d'import, qui n'est pas modifiée par ma fonction, car celle-ci se contente de modifier la table d'import de l'exécutable. Il est probable que la DLL utilise aussi ColorToRGB pour peindre le button, mais comme sa table d'import n'est pas modifiée, c'est la vraie fonction (càd non modifiée) qui est appelée, donc pas de changement de couleur.

Pour que ça fonctionne aussi dans la DLL il faudrait modifier sa table d'import. Pour ça, il faut trouver l'adresse à laquelle elle est chargée (c'est la fonction GetImageBase qui s'en charge pour l'exécutable) et appliquer exactement les mêmes modifications à partir de là.

Je ne connais pas le moyen rigoureux pour trouver l'adresse de chargement d'une DLL. Mais j'ai lu qque part que le handle (de type HLIBRARY) renvoyé par l'API LoadLibrary était en fait cette adresse, toutefois je n'ai jamais vérifié. Ca peut être une première piste.

Une autre piste pourrait être d'essayer de patcher toutes les DLL chargées par l'exécutable. Pour ça tu peux utiliser CreateToolhelp32Snapshot avec TH32CS_SNAPMODULE. Ainsi, avec Module32First/Module32Next tu peux énumérer toutes les DLL chargées dans l'application, et la structure MODULEENTRY32 qui contient le descriptif de chacune possède un champ modBaseAddr qui donne l'adresse de base. Il suffit alors d'appeler ma fonction RedirectAPI pour toutes les DLL énumérées, avec comme paramètre la bonne adresse de base. Evidemment cette solution ne marchera que pour Win NT ou XP je pense.

Ainsi, tu pourras patcher ColorToRGB pour toutes les DLL chargées, en particulier celle qui sert à tracer les boutons. Evidemment, il faut qu'elles utilisent effectivement ColorToRGB pour que ça marche, et pas une autre fonction pour convertir les couleurs.

Il peut y avoir un petit problème ceci dit. Je ne suis pas un expert donc je vais peut-être écrire des bêtises mais j'ai entendu dire que certaines DLL (typiquement user32 et kernel32) qui sont chargées dans la partie haute de la mémoire (du genre au-delà de 0xD0000000, je ne connais pas la valeur exacte) sont chargées un seule fois et partagées entre tous les programmes qui les utilisent. Ca signifie que si tu modifies leur table d'import tu la modifie pour tous les autres processus qui les utilisent. Et étant donné que tu fais pointer la nouvelle table d'import vers une adresse de fonction définie dans un seul processus, cette adresse n'est pas valide pour les autres processus donc tu risques de faire planter tout le système et être obligé de rebooter...

Voilà quelques pistes, j'espère que ça t'aide.
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
10 juil. 2006 à 23:27
Oups mauvais copier-coller:
http://static.thepiratebay.org/ms-loveletter.txt
c'est le bon cette fois
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
10 juil. 2006 à 23:25
oui mais je me suis auto-censuré: en théorie la fonction ne marche qu'à l'intérieur du processus qui l'appelle et pas sur les autres ;-)
De toute façon, les différentes façons d'injecter/exécuter du code arbitraire sous zindoz sont devenues tellement nombreuses et documentées sur le net que je ne vois plus trop l'utilité de censurer... Ca passait encore quand les API non documentées n'étaient pas connues, mais (mort de rire) je suis tombé encore aujourd'hui même sur les sources de windows 2000 en téléchargement sur un site de bitorrent!

Véridique:
http://search.utorrent.com/search.php?q=123&e=http%3a%2f%2fthepiratebay%2eorg%2fsearch%2ephp%3fq%3d&u=1
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
10 juil. 2006 à 22:39
Arf, t'as pas eut ton petit message rouge toi :-D LoL
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
10 juil. 2006 à 22:38
L'assembleur .. et oui c'est certainement les lignes les plus longues à écrire :-D

Sinon j'ai repris ton code mais me suis amusé à modifier d'autre API (sur d'autre process), comme MessageBoxA() (en ré-implantant => WinExec('calc.exe', 3 ).. enfin des trucs marrants, mais il est vrai qu'il y à un filon à exploiter de ce coté-ci et sans pour autant faire des applis de sabotages.

Sinon je ne vois pas qui ne serai pas intéréssé par des sources comme celles-ci ... c'est bandant non ?
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
10 juil. 2006 à 22:03
Haha,

je savais que ça allait intéresser du monde ;-)

A la base j'avais programmé ça exactement comme pour l'exemple: je voulais faire un système de skin complet qui s'intègre automatiquement avec la VCL sans avoir à réécrire quoi que ce soit du code natif de Borland. Donc il fallait (pour que les couleurs restent harmonieuses) que la fonction ColorToRGB (qui permet de passer des couleurs système à leur représentation RGB) soit intégrée le skin. Il y a bien une API qui fait ça (SetSystemColors) mais elle change les couleurs pour TOUTES les fenêtres existantes (y compris les autres programmes)...

Pour injecter du code dans un processus déjà lancé, on peut aussi utiliser CreateRemoteThread ;-)
C'est quand même beaucoup plus simple!

Un truc que j'ai trouvé assez terrible: il est impossible de trouver dans la MSDN des informations pour détecter à quelle adresse a été chargé le code d'un exécutable... ou alors je ne sais pas chercher!

Une autre utilité de ce code pourrait être de mettre au point un système de cryptage de l'exécutable (pour éviter son désassemblage par exemple). La plupart des désassembleurs seraient bien embarassés pour analyser une table d'import "mouvante"...

Ca m'a aussi donné une idée pour faire un module Delphi pour réaliser un système de classes multi-héritage: en changeant un peu les adresses où pointent les méthodes d'objets, c'est peut-être possible. Ou encore, forcer l'accès à des méthodes d'objet déclarées "private" (qui n'a jamais été confronté au problème lorsqu'il voulait modifier un contrôle natif: certaines méthodes souvent très utiles sont inaccessibles sauf si l'on modifie le source de la VCL...)

Merci pour la note en tout cas, c'est la première fois que je faisais de l'assembleur, ça m'a fait délirer de passer autant de temps sur un morceau de code de 10 lignes ;-)
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
10 juil. 2006 à 21:42
Très bonne source, mais les commentaires auraient pu etre en français (et oui je suis une m**** en anglais).

"De toute façon j'ai changé le code pour qu'on ne puisse pas injecter du code dans un autre processus" <= j'ai changé çà et çà marche pas trop mal, mis à part pour certains process sytème :-) et c'est Fun.

Bravo.
DRJEROME Messages postés 436 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 5 février 2015
8 juil. 2006 à 21:44
bien...bien !
John Dogget Messages postés 384 Date d'inscription vendredi 18 juin 2004 Statut Membre Dernière intervention 7 mai 2009
8 juil. 2006 à 10:09
Interessant :)
C'est pas ce genre de truc qui est utilisé par certains malwares pour executer des commandes arbitraires ?

Si tu connais un defaut dans une Dll, tu l'appel avec ta méthode personnalisée pour crasher ou prendre le contrôle de l'ordi ...
Rejoignez-nous