Lecture de la memoire d'un autre processus

0/5 (13 avis)

Vue 6 230 fois - Téléchargée 530 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 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.
Afficher les 13 commentaires

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.