LECTURE DE LA MEMOIRE D'UN AUTRE PROCESSUS

fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 - 5 juil. 2011 à 13:50
cs_Jean_Jean Messages postés 615 Date d'inscription dimanche 13 août 2006 Statut Membre Dernière intervention 13 décembre 2018 - 5 juil. 2012 à 14:40
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/53350-lecture-de-la-memoire-d-un-autre-processus

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
5 juil. 2012 à 14:40
Bonjour Mokost,

J'ai été intéressé par ton code que j'ai inclu dans un projet test sous XE2.
Mais le compilateur me génère 29 erreurs du genre:
E2033 : les types des parametres VAR originaux et formels doivent être identiques.

Lorsque je regarde les fonctions en question, par exemple :

function TProcessDataModifier.ReadBytes(size:integer):TByteDynArray;
var readed :cardinal;
begin
setlength(result,size);
ReadProcessMemory(FAccessHandle,pointer(FAdresse),@result[0],size,readed);
inc(FAdresse,size);
end;

le compilateur s'arrête sur la 2ème ligne: ReadProcessMemory(...) que je n'ai pas modifié!

Je fais appel à la fonction dans la fiche principale:

procedure TForm1.FormActivate(Sender: TObject);
begin
// test1.exe qui est un code de D7
ProcessReader := TProcessDataModifier.Create('test1',0);
// Lire une chaîne de 256 octets
With ProcessDataModifier DO
Begin
Showmessage(ReadString(256)); //nombre d'octet à lire
End;
end;

Que se passe-t-il?
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
26 juil. 2011 à 09:12
J'ai introduit cette modification dans la procedure ReadString en remplaçant le "Raise Exception" par "result:=", ce qui donne:

if (not ReadProcessMemory (FAccessHandle, pointer (FAdresse), @result[1], size, readed)) then
result:=('Impossible de lire les données')
Else
begin (* reprise du programme original *)
ReadProcessMemory (FAccessHandle, Pointer (FAdresse) , @result[1] , Size,Readed);
setlength(str,readed);
result := String(str);
end;

Effectivement, au lieu d'obtenir "Lire_mem.exe", j'obtiens maintenant "Impossible de lire les données".

J'ai essayé de changer l'adresse de lecture. Après l'exemple que tu donnes (ProcessReader.Adresse := $047Fc87), j'ai essayé d'autres adresses.
Si je passe au dessous de 0460000, j'obtiens "Impossible de lire les données". Si je prends une valeur supérieure, j'obtiens un Showmessage vide. Je suppose que ça représente une longue suite de Chr(0) avec aucun autre caractère. C'est quand même un peu surprenant.

J'avoue que je ne sais pas grand-chose sur la gestion de la mémoire. Est-ce que tu vois une adresse où je pourrais lire quelque chose d'intéressant ?
Mokost Messages postés 48 Date d'inscription jeudi 18 décembre 2003 Statut Membre Dernière intervention 29 mars 2010
25 juil. 2011 à 22:53
L'argument qui suit ReadString réprésente bien le nombre d'octet à lire. Il impossible de lire à l'adresse 0, c'est pour cela que tu obtient "Lire_mem.exe", on se sait pas ou il lit vraiment les données. En fait il aurait été plus judicieux si j'avais mit un test ex:
if(not ReadProcessMemory(FAccessHandle,pointer(FAdresse),@result[1],size,readed))
then raise Exception.Create('Impossible de lire les données');
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
22 juil. 2011 à 18:23
Je pense que c'est la mémoire de la calculatrice que j'ai lue puisque j'ai écrit au début du programme:

begin
// Faire de la calculatrice le processus étudié
ProcessReader := TProcessDataModifier.Create('Calc',0);

Mais j'ai essayé de modifier un peu ce Readstring(256). A la place, j'ai mis ReadString(500) et cette fois j'obtiens "Lire_mem.exe", le nom sous lequel j'ai sauvegardé ton programme. Bizarre, ça ne peut pas être contenu dans la mémoire de la calculatrice.

L'argument qui suit Readstring représente-t-il un nombre maximum d'octets à lire ou une adresse de départ ?
Mokost Messages postés 48 Date d'inscription jeudi 18 décembre 2003 Statut Membre Dernière intervention 29 mars 2010
8 juil. 2011 à 12:19
Je pense que tu as tenté de lire la mémoire d'un processus système et à mon avis Windows ne te permettra ni de lire ni de modifier la mémoire de ce processus.
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
6 juil. 2011 à 13:12
En effet, il y avait une erreur de ma part. Au lieu de

WITH ProcessDataModifier DO

j'aurais dÙ écrire:

WITH ProcessReader DO

et supprimer ce FAdresse:=10000

car FAdresse est une variable de type "private".

Après correction, ça marche et le Showmessage me dit :
[System Process]

Eh bien bravo mais j'aimerais bien comprendre à quoi correspond ce que j'ai lu.
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
6 juil. 2011 à 11:52
mais je n'obtiens rien, même pas le showmessage!

????

ça doit planter nécessairement sur une de ces lignes :

ProcessReader := TProcessDataModifier.Create('Calc',0);

With ProcessDataModifier DO
Begin
FAdresse:=10000:

---
End;

end;
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
6 juil. 2011 à 10:56
Merci pour ces infos. Effectivement AnsiContainsText est accepté par mon vieux Delphi7 et la compilation ne pose plus de problème.

Dans mon Unit 1, je crée la procédure FormActivate suivante:

procedure TForm1.FormActivate(Sender: TObject);
begin
// Faire de la calculatrice le processus étudié
ProcessReader := TProcessDataModifier.Create('Calc',0);

// Lire une chaîne de 256 octets à l'adresse 10000
With ProcessDataModifier DO
Begin
FAdresse:=10000:
Showmessage(ReadString(256));
End;
end;

Je lance la calculatrice puis je lance mon application mais je n'obtiens rien, même pas le showmessage! Je demande encore un peu d'aide.

(J'ai vu sur Intenet que CheatEngine, c'est une application et non pas comme je le pensais un mot de Delphi. Moi qui aime bien Démineur, je vais m'intéresser à ce CheatEngine mais pour l'instant, je cherche plutôt à progresser dans l'utilisation de ton logiciel).
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
6 juil. 2011 à 01:10
@Freedelem:

si tu as D7 ou +
tu remplaces ContainsText par AnsiContainsText et ça devrait fonctionner
Mokost Messages postés 48 Date d'inscription jeudi 18 décembre 2003 Statut Membre Dernière intervention 29 mars 2010
5 juil. 2011 à 20:32
Pour ContainsText utilise strpos : l'idée c'est de savoir si le nom de fichier contient la chaine rechercher exemple on cherche 'calc' dans 'calc.exe'.
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
5 juil. 2011 à 18:17
OK, j'ai remplacé RawByteString par String mais que puis-je faire pour la fonction ContainsText ? La remplacer par le mot "True" ou essayer de la réécrire à partir de l'idée suivante: si on trouve 10 caractères alphanumériques de suite dans le morceau à analyser, renvoyer true, sinon renvoyer false ?
Je voudrais bien utiliser CheatEngine mais Delphi7 ne connaît pas ce mot-là non plus.
Mokost Messages postés 48 Date d'inscription jeudi 18 décembre 2003 Statut Membre Dernière intervention 29 mars 2010
5 juil. 2011 à 16:48
Salut Fredelem, Comme je l'ai dit le type RawByteString et la fonction ContainsText existe bien dans Delphi Xe. Je m'en suis servit pour coder cette classe. Ensuite pour chercher l'adresse du résultat de la calculette je te conseille CheatEngine.
fredelem Messages postés 136 Date d'inscription dimanche 29 octobre 2006 Statut Membre Dernière intervention 1 décembre 2022 2
5 juil. 2011 à 13:50
Je voudrais utiliser ton unité pour faire la chose suivante: lancer la calculatrice dans un processus et lire le résultat qu'elle affiche dans un autre et peut-être aussi voir quel est le contenu de la mémoire à l'adresse CS:IP. Peux-tu m'aider un peu à le faire ?

A la compilation, j'ai eu deux problèmes: le type RawByteString n'est pas défini et la fonction ContainsText non plus. Il faudrait que tu corriges ces deux oublis.