Diffing e Memory Patching | ||
Data |
by "dlrm9m ([email protected])" |
|
15/Gen/2006 |
Published by Quequero | |
Non sempre tutto è come sembra |
Splendido lavoro, un tutorial del genere, aggiornato e con degli esempi ci mancava proprio! |
Non sempre tutto è come sembra |
.... |
|
.... |
Difficoltà |
(X)NewBies (X)Intermedio ( )Avanzato ( )Master |
Introduzione |
Tools usati |
URL o FTP del programma |
Prima parte :Il Diffing |
Cominciamo subito........Avviamo il nostro gioco [Naturalmente io seguo Tomb raider]
Diamo un'occhiata alle nostre risorse.Abbiamo 3 medikit piccoli...bene salviamo nel primo slot e rientriamo nel gioco.Usiamone uno e salviamo in un'altro slot...ora tomb raider possiamo anche chiuderlo tanto non ci servirà..più per un pò..Ora sappiamo che i due salvataggi sono stati salvati in 2 file diversi..savegame.0 e savegame.1Entriamo ora nella command del dos e usufruiamo di una funzione della cmd :La FC .Questa funzione pemette di fare un confronto tra due file...proprio quello che ci serve...:-))) Ora entriamo nella directory dove si trovano i file con la funzione cd [per i + newbies lo specifico non si sà mai..]...ora facciamo un confronto binario tra i due file scrivendo nella cmd cosi
|
Dovremmo ottenere un risultato simile a questo
|
A noi ora interessa ricordare il numero di medikit nel primo save e nel secondo.....e trasformare questi numeri in esadeciamle .In questo caso è abbastanza semplice in quanto i medikit passano da tre a due in esadeciamle sono 02 e 03 ...Sapendo questo cerchiamo ora l'offset il cui valore passa da 03 a 02 ...Trovato è lo 00000194: 03 02 ......Fissato questo nella mente [o in un blocco note]entriamo nel nostro editor esadecimale e carichiamo uno dei due file ..non importa quale è lo stesso.Per esempio carichiamo il primo e tramite l'opzione goto andiamo all'offset che ci interessa cioè 00000194 e ci apparirà in esadecimale il contenuto dell'offset.Naturalmente se carichiamo il primo troveremo 03 mentre nel secondo 02.......Fatto questo sostituiamo 02 con FF che è il numero massimo che si può ottenere con 2 cifre....Salviamo e rientriamo in tomb raider........Ora bbiamo 255 medikit.......Bene questo è il diffing applicato ai giochi ..
RIASSUMENDO:
Possiamo modificare tramite il diffing i valori esadecimali di un salvataggio ...Così facendo possiamo avere sempre armi ...munizioni ....ricariche quando e dove vogliamo.....Facile no?????....
Seconda Parte:Patch Memory e Trainers |
Ora invece parleremo di qualcosa di un pò più complesso..Il pacth memory...Bè penso che il nome spiga già abbastanza no????Come no?Vabbè per chi non lo sà...IL patch memory è una tecnica con la quale tramite un programma che richiama funzioni del win32 possiamo cambiare dei valori di un'altro programma direttamente in memoria..Creiamo ora la situazione analoga a quella di prima .Avviamo il gioco e stavolta torniamo in windows [naturalmente senza chiudere tomb raider..] e apriamo il Tsearch e apriamo il processo tramite l'open process .Ora clicchiamo sulla prima lente partendo da sinstra e cerchiamo il valore [ a 2 bit] 3.Verranno visualizzati un sacco di address ...ma per adesso niente paura ..poco importa..Rientriamo nel Game e usiamo un medikit così da scendere a 2...Torniamo nel Tsearch e clichiamo stavolta sulla seconda lente che serve a fare una ricerca tra i file gia cercati prima in modo da restringere il campo di ricerca.Cerchiamo ora 2...Ci spuntano altri risulati..ancora tanti però...[se a voi ne trova solo uno allora fermatevi io continuo perkè ne ho 8] ..Torniamo nel gioko e facciamo schalare di uno i medikit...Facciamo un'altra ricerca con la seconda lente e stavolta troviamo solo un risultato.....Bene...Leggiamo e vediamo che informazione ci dà lo scan memory......Supergiù dovremmo ottenere qualcosa del genere
E5BF9A | 1 | 2 bytes |
Il primo è il nostro address che sarà importantissimo per dopo.
Il secondo è il nostro valore in questo caso il numero di medikit
Il terzo è il tipo di numero che abbiamo cercato..[fate attenzione quando cercate quantià molto grandi ,non cercare a 2 bit ma a 4..]
Ora riprendiamo un pò lo scopo....Dobbiamo tramite un programma esterno al gioco interagire con esso così da modificarlo in memoria direttamente,in poche parole realizzare un mini trainers.... Starà a voi poi ampliarlo a vostro piacimento ;-) ............Possiamo scriverlo in qualunque linguaggio...Assembler ,C++,Delphi,...Anche in Visual mer*a Basic ....
Vediamolo in Assembler [Grazie que per avermi aiutato su questa parte!!!!! Grazie anche a SatUrN]
Per fare un PM abbiamo bisogno di utilizzare alcune funzioni del win32.ecco perkè vi ho detto che come tool ci doveva essere anche la W32.hlp.........
Facciamoci un'algoritmo facile facile e banale[questa parte è per i NewBies]
NOi DOBBIAMO
1)Trovare il processo e il suo identificatore
2)Potere quindi interagire con esso
3)Aprire un dialogo tra trainers e gioco
4)Leggere la parte di codice che ci interessa
5)Infine poterla modificare a nostro piacere
Vediamo ora le funzioni che ci interessano [tenete sott'occhio l'help w32]
La prima che useremo sarà la FindWindow ... che ha questa struttura
HWND FindWindow(
LPCTSTR
lpClassName, // puntatore alla classe
LPCTSTR lpWindowName // puntatore al
nome della finestra del programma
);
Per questa operazione ci servirà prima lo spy++ .....Apriamo il programma e cerchiamo il processo del gioco
Vediamo che nel nostro caso il nome della finestra è Tomb Raider Chronicles
e il nome della classe è MainGameWindow ..Si lo sò.....ho dimeticato di dirvi come riconoscerli......Cliccate 2 volte sul processo di tomb raider e si aprirà una finestra ....nel Tab General Trovate La Window Caption che è il nome della finestra mentre andando su class troviamo il Class Name ... FAtto questo buttiamo giù la prima parte del programma..
DIMENTICAVO La funzone FindWindow restituisce una valore HWND cioè un Handle .......Bè se non sapete cosa è un'handle cercate di vederlo in questo modo....L'identificatore di un processo...Capito?No? ......
Allora facciamo così....Window è una maratona atletica...i programmi sono i partecipanti a cui viene dato un numero di identificazione...quel numero è l'handle..........Cmq andiamo avanti....Dò per scontato che qualcosa di assembler la sappiate....[ringrazio nuovamente quequero]
_------------------------------__________Assembly________-------------_
.386p
LOCALS
JUMPS
.MODEL FLAT,STDCALL
UNICODE=0
INCLUDE W32.inc
[la libreria delle funzioni]
.data
class db "MainGameWindow",0 ---->
è il nome della classe
winame db "Tomb Raider Chronicles",0 -----> il
nome della finestra
handle dd 1 dup(0) ----> dove andremo a mettere l'handle della finestra
.code
call FindWindow,offset class,offset
winame-->richiamo della funzione
mov handle,eax------->muoviamo il risultato della funzione[ l'handle]
nella variabile
end start
Ora andiamo avanti e introduciamo le funzioni GetWindowThreadProcessId,OpenProcess,ReadProcessMemory e WriteProcessMemory
DWORD GetWindowThreadProcessId(
HWND hWnd,
// handle of window
LPDWORD lpdwProcessId // address of variable
for process identifier
);
La funzione è molto semplice e ci serve per trovare l'ID della process..E' composta da 2 agr..
1)L'handle della finestra trovato in precedenza con il FindWindow
2)Una variabile in ci mettere l'ID
ora passiamo alla OpenProcess ...
HANDLE OpenProcess(
DWORD
dwDesiredAccess, // access flag
BOOL bInheritHandle, // handle inheritance
flag
DWORD dwProcessId // process identifier
);
Questa funzione restituisce un'handle che sarà il risultato dell'apertura del dialogo tra i 2 programmi[trainers e gioco]
1)Questo è in flag di accesso..Identifica i privileggi che il trainers ha sul programma......nell'help ne troviamo parecchi no usiamo il flag PROCESS_ALL_ACCESS
2)Questo è un valore BOOL[vero o falso] che determina l'ereditarietà del processID
3)Variabile in cui c'è il processId
Fino a qui problemi ???spero di no!
Andiamo alle ultime 2 [sto cercando di seguire l'algoritmo fatto in precendenza]
BOOL ReadProcessMemory(
HANDLE
hProcess, // handle of the process whose memory is read
LPCVOID lpBaseAddress, // address to
start reading
LPVOID lpBuffer, // address of buffer
to place read data
DWORD nSize, // number of bytes to read
LPDWORD lpNumberOfBytesRead // address
of number of bytes read
);
Bè vista così può sembrare difficile...invece è la più facile........Restituisce infatti un valore BOOL ....1 o 0
1)Questo primo valore è il valore che abbiamo ottenuto dalla funzione di poco fà....
2)Questo è il nostro indirizzo[ricordate l'address che ci dava lo scan memory??lo dovremo inserire qui]
3)Questa è una variabile in cui inseriremo i nostri byte letti
4)Il numero di byte da leggere[2 bytes]
5)Lo impostiamo a NULL
Buttiamo giù un'altro programma in cui inseriamo anche queste Funzioni
.386p
LOCALS
JUMPS
.MODEL FLAT,STDCALL
UNICODE=0
INCLUDE W32.inc
extrn GetWindowThreadProcessId:Proc --->la dichiariamo esterna
.data
class db "MainGameWindow",0
winame db "Tomb Raider Chronicles",0
handle dd 1 dup(0)
PID dd 1 dup(0)----->Variabile in cui andremo a mettere
il ProcessID dopo la funzione GetWindowThreadProcessID
PHandle dd 1 dup(0)--->Variabile dove mettiamo l'handle
del processo dopo l'open process
ReadBuffer dd 1 dup(0)---> Byte letti
bytefree dw 00ffh --->byte da sostituire
.code
start:
call FindWindow,offset class,NULL
mov handle,eax
call GetWindowThreadProcessId, handle, offset PID
call OpenProcess, PROCESS_ALL_ACCESS, FALSE, dword ptr[PID]
mov PHandle, eax
mov eax,000E5BF9Ah----->L'address letto nello scanmemory
call ReadProcessMemory, [PHandle], eax, offset ReadBuffer, 2, NULL
end start
Infine vediamo l'ultima funzione La WriteProcessMemory è molto simile alla Read
BOOL WriteProcessMemory(
HANDLE
hProcess, // handle to process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // pointer to buffer to write data to
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
1)Il primo è uguale al ReadProcessMemory
2)Stessa cosa per il secondo
3)Il terzo deve contenere i Bytes che dobbiamo sostituire
4) e 5)Gli stessi del ReadProcessMemory
Ora implementiamo anche questo al programma
.386p
LOCALS
JUMPS
.MODEL FLAT,STDCALL
UNICODE=0
INCLUDE W32.inc
extrn GetWindowThreadProcessId:Proc --->la dichiariamo esterna
.data
class db "MainGameWindow",0
winame db "Tomb Raider Chronicles",0
handle dd 1 dup(0)
PID dd 1 dup(0)----->Variabile in cui andremo a mettere
il ProcessID dopo la funzione GetWindowThreadProcessID
PHandle dd 1 dup(0)--->Variabile dove mettiamo l'handle
del processo dopo l'open process
ReadBuffer dd 1 dup(0)---> Byte letti
bytefree dw 00ffh --->byte da sostituire
.code
start:
call FindWindow,offset class,NULL
mov handle,eax
call GetWindowThreadProcessId, handle, offset PID
call OpenProcess, PROCESS_ALL_ACCESS, FALSE, dword ptr[PID]
mov PHandle, eax
mov eax,000E5BF9Ah----->L'address letto nello scanmemory
call ReadProcessMemory, [PHandle], eax, offset ReadBuffer, 2, NULL
mov eax,000E5BF9Ah
call WriteProcessMemory,[ProcessHandle],eax,offset bytefree,2,NULL
end start
Compiliamo con il Tasm 5.0
E il programma è fatto........Possiamo anche farlo in Delphi per esempio possiamo scrivere qualcosa del genere
procedure
TForm1.Button1Click(Sender: TObject);
var
ByteRead :DWORD;
Hndle : HWND;
lpd : LPDWORD;
processid :DWORD;
Hfinestra :THandle;
Adressp :Pointer ;
VarRead :Pointer;
VerRe :pointer;
const
Classn='MainGameWindow';
Address=$E5BFA4;
begin
Hndle:=FindWindow(classn,nil);
processid:=GetWindowThreadProcessId(Hndle,lpd);
Hfinestra:= OpenProcess (PROCESS_ALL_ACCESS,FALSE,processid);
AdressP:=Pointer(Address);
ReadProcessMemory(Hfinestra ,AdressP ,VarRead ,2,ByteRead);
VerRe:= VarRead;
end;
Tocca ora decidere in che linguaggio di prog farlo.........
Spero di essere stato chiaro e scorrevole
SAaluti dlrM9M
Note finali |
Ringrazio tutta la UIC perchè è grazie aloro che ho deciso di imparare a far sempre di più e a non arrendermi..Ringrazio Quequero per aver rispostoa lle mie domande .Stessa cosa vale per SatUrN e per §-Death_Reaver-§ ..Grazie..
Disclaimer |
Ci tengo aprecisare che non c'è molto prio a giocare con i trainers...questo tut è a solo scopo informativo....
Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.