Diffing e Memory Patching
(Voglio essere immortale!)

Data

by "dlrm9m ([email protected])"

 

15/Gen/2006

UIC's Home Page

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

Cercherò di farvi capire un pò come funzionano le tecniche di Diffing e di Patch Memory sui giochi così da facilitarvi la vita in alcune situazioni veramente strazianti.....:-) Il tutorial si dividerà infatti in due parti Diffing e PM ....Vi aiuterò più possibile con i colori..

Tools usati

I tools per il diffing sono:
- Un semplice editor esadecimale che potrete trovare nella sezione tools del sito della UIC (www.quequero.org)
- Un gioco che vi piace, tanto il discorso non cambia...io per il mio esempio userò Tomb raider Chronicles ma tanto non cambia...state tranquilli
 
I tools per il PM sono:
-TSearch 1.6 un fantastico scan memory .
-Tasm 5.0 (per compilare il PM)
-Ollydbg 1.10 (per capire un pò se il prog và..)
-W32.hlp indispensabile !!!!!!
Spy++ ... (incluso nel visual c++)
 

URL o FTP del programma

......Può essere anche un gioco che avete nello scaffale della vostra stanza

Prima parte :Il Diffing

Cosa è il Diffing?Il diffing è una tecnica con la quale si può ,tramite un confronto, identificare degli offset di un documento, i quali contengono informazioni importanti richiamate poi da programmi secondi ,quindi andarli così a modificare per ottenere dei risultati da noi voluti.....Detto così può sembrare chissa cosa .ma vi farò vedere che è davero semplice...........

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



fc /b primofile secondofile quindi
fc /b savegame.0 savegame.1

Dovremmo ottenere un risultato simile a questo

00000053: 00 01
00000055: 22 10
00000057: 66 45
...
00000100: 00 01
00000101: 00 FC
00000194: 03 02
..
...

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.