cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010
-
22 janv. 2008 à 09:35
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010
-
25 janv. 2008 à 08:57
Bonjour à tous et à toutes,
Mon souci :
J'ai des adresses mémoire pour un logiciel donné et j'aurais besoin d'accèder directement à ces zones mémoire en lecture (pour en lire le contenu) et en écriture (pour y injecter de nouvelles données en lieu et place de celles existantes). Je sais, c'est pas simple.
Ce que je cherche donc à faire c'est dans un premier temps un petit programme de test avec un TEdit où rentrer l'adresse à lire/modifier, un Tlabel pour afficher le contenu en mémoire, un autre TEdit pour saisir les nouvelles valeurs à injecter, deux boutons, un pour lire et un pour écrire les valeurs.
Qui pourrait me donner un gros coup de main car je n'ai encore jamais utilisé de fonctions/API manipulant la mémoire d'un logiciel. Pour le reste ça devrait aller .
Merci d'avance.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 24 janv. 2008 à 15:42
Entraîne toi sur un processus fait par toi même pour bien comprendre le procédé.
C'est juste une histoire de pointeurs.
Voilà une tentative de traduction :
J'ai sûrement fait pas mal d'erreurs...
var
rbrWnd: HWND; // Handle de la fenêtre
dwProcessId: DWORD; // ID du processus à modifier
hProcess: HANDLE; // Handle du processus à modifier
OldProtect: DWORD; // Récupération de la protection précédente
damageBlockAddress: DWORD; // Calcul de l'adresse des dégats
value: DWORD; // Valeur que l'on écrira dans le processus distant
firstAddress: DWORD; // On va déterminer les autres adresses à partir de celle-ci
bytesWritten: DWORD; // Nombre d'octets écrits par WriteProcessMemory
leftDoorAddress: DWORD; // Adresse des dégats de la portière gauche
begin
// Recherche de la fenêtre
rbrWnd:= FindWindow('D3D Window', nil);
if rbrWnd = 0 then RaiseLastOSError;
// Récupération de l'ID du processus à partir du handle de fenêtre
GetWindowThreadProcessId(rbrWnd, dwProcessId);
// Récupération d'un handle sur le processus à partir de son ID
hProcess:= OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessId);
if hProcess = 0 then RaiseLastOSError;
// Lecture de 4 octets à l'adresse $008EF660
address:= $008EF660;
VirtualProtectEx(hProcess, Pointer(address), 4, PAGE_READWRITE, OldProtect);
ReadProcessMemory(hProcess, Pointer(address), @damageBlockAddress, 4, nil);
// L'adresse des dégats se trouve à l'offset $620 de l'adresse située à l'adresse $008EF660.
// On vient de récupérer l'adresse située à l'adresse $008EF660.
// Il faut lui ajouter $620.
damageBlockAddress:= damageBlockAddress + $620;
// On récupère l'adresse des dégats
VirtualProtectEx(hProcess, Pointer(damageBlockAddress), 4, PAGE_READWRITE, OldProtect);
ReadProcessMemory(hProcess, Pointer(damageBlockAddress), @damageBlockAddress, 4, nil);
// Pour ouvrir la porte, il faut écrire 0 à l'adresse des dégats + $36C
value:= 0;
leftDoorAddress:= damageBlockAddress + $36C;
Guillemouze
Messages postés991Date d'inscriptionsamedi 25 octobre 2003StatutMembreDernière intervention29 août 20136 22 janv. 2008 à 13:31
bah un simple cast devrait suffire, a partir du moment ou tu sais quel type y mettre (=quelle taille memoire)
par exemple
edit1.text vaut "12345"
var
addr: Pointer;
begin addr :Pointer(StrToInt(edit1.Text)); //addr vaut l'adresse memoire 12345 ( $3039 en hexa)
integer(addr^) := 5; //ecrira "5" sur 4 octets (taille d'un integer) a l'adresse $3039
end;
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010 22 janv. 2008 à 14:25
Hummm,
je pensais plutot avoir à utiliser des fonctions comme VirtualProtectEx(), ReadProcessMemory(), etc...
je dois lire et écrire dans des zones mémoire d'un processus déjà connu (cette partie fonctionne).
En fait j'ai déjà essayé ce qui suit mais j'ai une erreur.
Trouver le processus : HRBRWindow := FindWindow(Nil,'Richard Burns Rally - DirectX9');
Label3.Caption := IntToStr(HRBRWindow);
dwProcessId := 0;
GetWindowThreadProcessId(HRBRWindow, dwProcessId);
Label4.Caption := IntToStr(dwProcessId);
Lire :
function Tform1.LitDomages(adresse:dword): float;
var debBlock : dword;
begin
debBlock : = 0;
asm
push eax
mov eax, $008EF660
mov eax, [eax]
add eax, adresse //$620
mov eax, [eax]
mov debBlock, eax
pop eax
end;
LitDomages := debBlock;
end;
.......
.......
Ecrire (ça ça ne fonctionne pas) :
procedure TForm1.bButton1Click(Sender: TObject);
begin
OldProtect : = 0;
BlockAddressDomages := 0;
MA := $008EF660;
// change la protection de la zone mémoire Read/Write
NumberOfBytes := 4;
VirtualProtectEx(HRBRWindow, Ptr(MA),NumberOfBytes,PAGE_READWRITE,OldProtect);
ReadProcessMemory(HRBRWindow, Ptr(MA), Ptr(BlockAddressDomages), NumberOfBytes, Wrtpr);
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010 22 janv. 2008 à 17:56
Salut f0xi,
Ca sent surtout une mise en place de gestion des dommages entre deux courses pour des championnats. :-))
Et là... ben je galère... je ne m'était jamais penché sur des manip comme celle-ci.
Il faudrait que je puisse récupérer les dommages en fin de course pour pouvoir les ré-injecter juste avant le départ de la suivante.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 24 janv. 2008 à 12:46
Salut,
Ta LitDomages fonctionne ????
Ce n'est pas parce que c'est de l'assembleur que ça ira lire le processus voisin...
Il faut que ce code soit executé dans le processus cible pour qu'il ait
une chance de fonctionner : les processus ne partagent pas de mémoire.
Tu peux cependant sans problème traduire ce code avec du ReadProcessMemory.
Ton "Ecrire" ne fait que lire : il n'utilise pas WriteProcessMemory. Il
faut visiblement commencer par un Read mais le deuxième doit être un
Write.
Ptr(MA) -> Renvoie l'adresse de MA, alors que c'est l'adresse MA qui t'intéresse -> Pointer(MA).
Pour l'écriture, pareil, ta source doit être l'adresse d'un entier
contenant tes nouveaux dommages (Ptr()), mais l'adresse de destination
doit être la valeur de BlockAddressDomages (Pointer()).
damageBlockAddress += 0x620;
VirtualProtectEx(hProcess,(LPVOID)damageBlockAddress,4,PAGE_READWRITE,&OldProtect);
ReadProcessMemory(hProcess,(LPCVOID)damageBlockAddress, &damageBlockAddress, 4, NULL);
/*
the damage data starts at "damageBlockAddress"
you have to do some tests to determine which offsets means what
in example if you write zero at (damageBlockAddress + 0x36C) you will get the left door opened,
or if you write zero at (damageBlockAddress + 0x384) you open the bonet.
*/
DWORD value = 0;
DWORD bytesWritten = 0;
DWORD leftDoorOffset = damageBlockAddress + 0x36C;
VirtualProtectEx(hProcess,(LPVOID)leftDoorOffset,4,PAGE_READWRITE,&OldProtect);
WriteProcessMemory(hProcess, (LPVOID)leftDoorOffset, &value, 4, &bytesWritten);
DWORD bonetOffset = damageBlockAddress + 0x384;
VirtualProtectEx(hProcess,(LPVOID)bonetOffset,4,PAGE_READWRITE,&OldProtect);
WriteProcessMemory(hProcess, (LPVOID)bonetOffset, &value, 4, &bytesWritten);
CloseHandle(hProcess);
Tout ce que j'essaie me renvoie une erreur "violation de partage lecture adresse 008EF660 etc...".
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010 24 janv. 2008 à 16:17
Je te remercie pour cette traduction.
Ben justement les histoires pointeurs ce n'est pas mon fort....
J'obtiens l'erreur suivante "Les types des paramètres VAR originaux et formels doivent être identiques" avec les lignes
ReadProcessMemory(hProcess, Pointer(address), @damageBlockAddress, 4, nil);
et
ReadProcessMemory(hProcess, Pointer(damageBlockAddress), @damageBlockAddress, 4, nil);
lors de la compilation.
Je savais bien que ça allait être coton ce prog...
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010 24 janv. 2008 à 16:36
YES
ça marche, le logiciel arrive à ouvrir la portière, ce qui veux dire que la partie "écriture" fonctionne (heu ... celle pour la lecture aussi puisque après on peut écrire à cette adresse )
C'est vraiment génial.
Je te remercie encore pour le temps que tu as passé à m'aider c'était vraiment sympa car je ne pense pas que j'aurais réussi sans ton aide.
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 25 janv. 2008 à 08:30
Pour cela, il faut commencer par connaître la taille de ce qui se
trouve à cette adresse. On sait que la porte est en +$36C et le "bonet"
(?) en +$384. Donc ça fait de la place... On va essayer de copier $500
par exemple.
var
lpDamageBlocBuffer: array [0..$500] of Byte;
begin
...
VirtualLocEx
VirtualProtectEx(hProcess, Pointer(damageBlockAddress), $500, PAGE_READWRITE, OldProtect);
ReadProcessMemory(hProcess, Pointer(damageBlockAddress), @lpDamageBlocBuffer[0], $500, nil);
cs_PHIL63
Messages postés76Date d'inscriptiondimanche 9 février 2003StatutMembreDernière intervention10 août 2010 25 janv. 2008 à 08:57
Bonjour,
En fait pour la taille, je peux être un peu plus précis car je sais qu'en $36C j'ai "Porte G ouverte" et en $370 j'ai "Porte G dégondée" donc je peux réduire la taille à 4 au lieu de $500.
Il faut maintenant que je me fasse une petite fonction qui me renvoie le contenu du bloc mémoire avant que j'injecte le 0.
En fait, comme tu as du le comprendre, j'ai besoin dans un premier temps de trouver à quoi correspondent tout un tas d'adresses mémoire dans le processus du jeu pour établir une liste en injectant un 0 à chaque emplacement puis en vérifiant ce que ça fait merd** au niveau de la voiture.
Un fois que j'aurais fais au moins une liste sommaire, je pourrais réinjecter les dégats dans la partie suivante ce qui sera plus réaliste.
Grâce à toi j'ai énormément avancé et je t'en remerci encore.
@+