Lecture de la memoire d'un autre processus

Soyez le premier à donner votre avis sur cette source.

Vue 5 212 fois - Téléchargée 468 fois

Description

Une classe qui permet de lire et modifier la mémoire d'un autre processus à une adresse donnée.

ProcessReader := TProcessDataModifier.Create('calc',0);
Va créer une nouvelle instance de TProcessDataModifier et accéder à la mémoire du premier processus dont le nom de fichier contient 'calc' à l'évidence ce sera la calculatrice de windows : 'calc.exe'. Sous réserve que celle-ci soit lancé au préalable.

ProcessReader := TProcessDataModifier.CreateFromFile('c:\un\chemin\fichier.exe',0);
Va créer une nouvelle instance de TProcessDataModifier et lancer fichier.exe puis accéder à sa mémoire.

A chaque lecture l'adresse est incrémenter automatique de la taille des données lues. A tout moment pour venir à l'adresse de base il suffit d’exécuter ProcessReader.ResetPos; Pour positionner directement à l'adresse des données à lire : ProcessReader.Adresse := $047Fc87;

Source / Exemple :


//Codé sous delphi Xe, pour une compatibilité descendante (delphi 7 par exemple) il suffira de
//remplacer rawbytestring par string et verifier la taille en memoire des types de donnée 
TProcessDataModifier = Class
    constructor Create(aProcess: string; BaseAdresse:Cardinal);overload;
    constructor CreateFromFile(aFullPath: string; BaseAdresse:Cardinal);
    destructor Free;
  private
    FProcessName:string;
    FAccessHandle : HWND;
    FProcessId : HWND;
    FAdresse : cardinal;
    FBaseAdresse : cardinal;
  public
    property Adresse:cardinal read FAdresse write FAdresse;
    //Déplace l'adresse de offset
    procedure Move(offset:integer);
    //Réinitialise l'adresse de lecture à l'origine
    procedure ResetPos;

    //Lecture de donnée
    function ReadSmallInt:SmallInt;
    function ReadShortInt:ShortInt;
    function ReadLongInt:LongInt;
    function ReadChar:Char;
    function ReadByte:Byte;
    function ReadWord:Word;
    function ReadLongWord:LongWord;
    function ReadSingle:Single;
    function ReadReal:Real;
    function ReadReal48:Real48;
    function ReadExtended:Extended;
    function ReadBytes(size:integer):TByteDynArray;
    function ReadString(size:integer):RawByteString;

    //Ecriture de donnée
    procedure Write(value:SmallInt);overload;
    procedure Write(value:ShortInt);overload;
    procedure Write(value:LongInt);overload;
    procedure Write(value:Char);overload;
    procedure Write(value:Byte);overload;
    procedure Write(value:Word);overload;
    procedure Write(value:LongWord);overload;
    procedure Write(value:Single);overload;
    procedure Write(value:Real);overload;
    procedure Write(value:Real48);overload;
    procedure Write(value:Extended);overload;
    procedure Write(value:TByteDynArray);overload;
    procedure Write(value:RawByteString);overload;
    procedure Write(value:RawByteString;size:cardinal);overload;
End;

Conclusion :


Pour obtenir des adresses de lecture vous pouvez utiliser cheat engine par exemple.

Tout tourne principalement autour de ReadProcessMemory et de WriteProcessMemory de l'api Windows.

En conclusion j'espère que cette classe vous sera utile et j'attends vos conseils et avis.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_Jean_Jean
Messages postés
637
Date d'inscription
dimanche 13 août 2006
Statut
Membre
Dernière intervention
13 décembre 2018
2
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
131
Date d'inscription
dimanche 29 octobre 2006
Statut
Membre
Dernière intervention
30 novembre 2018
1
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

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
131
Date d'inscription
dimanche 29 octobre 2006
Statut
Membre
Dernière intervention
30 novembre 2018
1
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

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.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.