Warfans
Benvenuti!!!!! Warfans è il forum più completo che riguarda computer e giochi di qualsiasi tipo!!!! ! Che aspettate? Iscrivetevi ed entrerete nella nostra community

1- L'utente continuando la navigazione nel sito dichiara di aver letto attentamente il Regolamento.
2- Tutti i nuovi Utenti sono pregati di presentarsi nella sezione Presentazioni.
3- Lo Staff cerca: Moderatori, Coder, Graphic. Se vi interessa scrivete il Curriculum nella sezione Zona Reclutamento.
Warfans
Benvenuti!!!!! Warfans è il forum più completo che riguarda computer e giochi di qualsiasi tipo!!!! ! Che aspettate? Iscrivetevi ed entrerete nella nostra community

1- L'utente continuando la navigazione nel sito dichiara di aver letto attentamente il Regolamento.
2- Tutti i nuovi Utenti sono pregati di presentarsi nella sezione Presentazioni.
3- Lo Staff cerca: Moderatori, Coder, Graphic. Se vi interessa scrivete il Curriculum nella sezione Zona Reclutamento.
Warfans
Vuoi reagire a questo messaggio? Crea un account in pochi click o accedi per continuare.

Warfans

La nuova frontiera dei videogiochi
 
IndiceHomeUltime immaginiRegistratiAccedi
E' obbligatorio presentarsi nella sezione "presentazioni" prima di formulare una richiesta!!!!

 

 Cheat Engine

Andare in basso 
AutoreMessaggio
Lambert7

Lambert7


Numero di messaggi : 44
Età : 36
Località : Torino

Cheat Engine Empty
MessaggioTitolo: Cheat Engine   Cheat Engine Icon_minitimeLun 12 Apr 2010, 16:03

Al mio parere il miglior tut per il famoso memory scanner. Non mio.


Cos'è un trainer

Non mi piace la teoria ma qui ci vuole per forza dato che non tutti sanno cos'è un trainer e ancora meno sanno cos'è il DMA.
Un trainer è, detto in parole povere, un programma capace di alterare un secondo programma (spesso un videogioco) mentre è in esecuzione, per permettergli di fare cose che solitamente non farebbe, o non consentirebbe di fare.

In termini più tecnici è la modifica (memory patching) di un programma fintanto che questo è caricato in memoria. Chiuso il programma si perdono le modifiche apportate dato che il programma viene scaricato dalla memoria del pc.

Un bell'esempio pratico: stiamo giocando con uno sparatutto e abbiamo 8 vite. Non riusciamo a superare un livello dove crepiamo sempre, e forse lo supereremmo se avessimo una ventina di vite. Prima di avviare il gioco dunque avviamo un programma trainer per il nostro videogame, e mentre stiamo giocando attiviamo (tramite una sequenza di tasti predefinita) una funzionalità del trainer che ci consente di aumentare di 2 vite l'ammontare delle nostre vite nel gioco. In questo modo riusciamo a superare il livello senza difficoltà.


Come si crea un trainer

Le fasi da seguire per creare un trainer per un videogioco sono essenzialmente 3:

Trovare l'indirizzo di memoria da patchare (modificare)
Modificare i dati a quell'indirizzo di memoria per realizzare il nostro obiettivo
Scrivere un programma che renda queste operazioni automatiche (la fase più facile e rilassante una volta finiti i punti 1 e 2)

Un primo semplice memory patching

Vediamo di realizzare un piccolo memory patching (una modifica di memoria) riguardo a un celebre programma: Prato Fiorito per Windows!

Per realizzare questo patching avremo bisogno di un memory scanner, un programma capace di cercare all'interno della memoria del programma che vogliamo modificare (prato fiorito in questo caso) alla ricerca dei dati che vogliamo modificare.

Se giustamente non ci avete capito nulla passiamo all'esempio pratico.

Scarichiamoci il successore del buon vecchio Tsearch: Cheat Engine (al momento in cui scrivo è appena uscita la versione 5.3) dal sito Cheat Engine: [Devi essere iscritto e connesso per vedere questo link]

La prima volta che eseguiamo Cheat Engine (che chiamerò CE per abbreviare..) ci viene presentato un interessante tutorial in lingua inglese che ci illustra come va utilizzato CE per alcune patch basilari, sarebbe opportuno seguirlo tutto se non abbiamo fretta.

Dunque passiamo al memory patching di prato fiorito mediante CE.

Eseguiamo prato fiorito e iniziamo a giocare, noteremo che il timer del tempo inizia a scorrere..


Io sono bravino a prato fiorito ma devo pensarci mezz'ora per capire dove sta una mina. E ciò pregiudica il mio dominio nella lista dei record dove primeggia quel gay di mio cugino.

Questa purtroppo è una brutta cosa e dobbiamo porvi rimedio.

Allora avviamo CE e accediamo al processo di prato fiorito con il tasto "Let's you select the program you want to cheat with" (lampante come suggerimento..) in alto a sx


Aperto il processo con nome WINMINE.EXE, effettuiamo con CE una ricerca dei secondi che sono passati nel gioco scegliendo Exact Value e un valore di 4 bytes (un valore a 4 bytes può essere minore o uguale a 4294967295, di solito la maggior parte dei valori dei videogame sono a 4 bytes) e inserendo (siate veloci ) il valore dei secondi nel campo del valore da ricercare. Siccome intanto che CE analizza la memoria di prato fiorito (e per giochi di grandi dimensioni ci mette tanto) il gioco va avanti e ci scala secondi, corriamo il rischio di un risultato errato, dunque scegliamo anche l'opzione "Pause the game while scanning" e avviamo la ricerca nella memoria di WINMINE.EXE con il tasto First Scan


Ci viene presentata a lato una lista di taaanti indirizzi dove è memorizzato un valore come quello che abbiamo cercato.


Uno di questi è quello che ci interessa. Come facciamo a sapere quale?

Siccome questo gioco è una vergogna vediamo che uno dei valori cercati si incrementa al passare dei secondi, ma nel caso non l'avessimo visto (o facciamo finta di non averlo visto), ecco come assicurarci che sia quello il valore buono.

Torniamo in prato fiorito e controlliamo di nuovo i secondi.

Ora torniamo in CE e inseriamo il nuovo valore dei secondi (veloci anche qua) e facciamo Next Scan


Ecco che ci viene presentato un solo valore!

Cosa abbiamo fatto? Abbiamo ricercato un indirizzo di memoria con valore xx fra quelli della prima ricerca. Cioè un indirizzo il cui valore prima era quello ricercato nella prima ricerca e ora è cambiato a xx, e un solo valore rientra tra i nostri criteri ed è quello che ci interessa. Se avessimo avuto più valori avremmo continuato a ricercare valori con Next Search (che a differenza di First Search si può fare quante volte vogliamo sui valori che abbiamo trovato con la prima scansione).

Aggiungiamo il valore che ci interessa nella lista di indirizzi in basso selezionandolo e cliccando sulla freccetta rossa


Da qui possiamo cambiare il campo Value e aggiungere un valore che vogliamo noi, e daremo a questo indirizzo valore 1, cioè che dall'inizio del gioco è trascorso un solo secondo.


Premiamo ok e torniamo in prato fiorito. Wow è trascorso un solo secondo da quando ho iniziato a giocare invece dei 289 secondi che ci ho messo a trovare la mina!

Mio cugino è esterrefatto guardando la classifica dei record. Obiettivo raggiunto. La prossima volta lo sorprenderò ancora di più con il trucco del xyzzy (un easter egg, usate google


Iniziano le complicazioni

A questo punto non ci resterebbe che creare un bel programma in qualche linguaggio (asm se siete cazzuti, c++ se volete fare le cose per bene e aggiungere una bella interfaccia grafica o delphi o quello che vi pare evitando possibilmente il visual basic ! ) per fare in modo che premendo un tasto si cambi automaticamente il valore dell'indirizzo che abbiamo trovato (nel mio caso è 0100579C, ovvero l'indirizzo base del processo winmine.exe + 579C che è chiamato offset, notare che tutti i numeri di cui si parla qui sono in formato esadecimale, in base 16) nel valore 1 così da giocare con calma e arrivati all'ultima casellina non dovremmo fare altro che premere il tastone e risulterà che abbiamo completato il quadro in un secondo

Più in fondo vedremo anche come scrivere un tale programma in C++, ma ora non divaghiamo perchè questo è il memory patching per dilettanti, il più facile. Nulla a che vedere con i giochi commerciali di alta lega come GTA San Andreas e simili.

Perchè si da il caso che questi giochi abbiano spesso e volentieri delle complicazioni date dal loro meccanismo di funzionamento..


Cos'è il DMA

DMA, totalmente sconosciuto alla maggior parte di coloro che non si sono mai interessati su come funziona un trainer, è la sigla di Dynamic Memory Allocation e per qualcuno questa sigla già avrà fatto capire perchè è così odiato da tutti coloro che creano/cercano di creare trainer per videogames.

Senza giri di parole, un gioco protetto da DMA è un gioco in cui valgono tutte le regole per il memory training che abbiamo visto finora con una semplice differenza che ci smonta palle e lavoro fatto finora: l'indirizzo che troviamo da patchare (nel caso qui sopra avevo trovato l'indirizzo 0100579C in cui venivano memorizzati i secondi trascorsi dall'inizio della partita) non è più statico ma può variare.

Ovvero se prato fiorito fosse protetto da DMA, ogni volta che il gioco verrebbe avviato, l'indirizzo in cui vengono memorizzati i secondi trascorsi dall'inizio della partita sarebbe diverso.

Se nella sessione di memory patching di prima avevo individuato l'indirizzo 0100579C e mi stavo preparando a creare un bel programma trainer in C++ per distribuirlo agli amici, se riavvio ora il gioco (chiudo il programma e lo riavvio) e vado a controllare con CE l'indirizzo 0100579C vedrò che a quell'indirizzo probabilmente non c'è più una ceppa. Il gioco ha scelto dinamicamente un altro indirizzo di memoria (diverso dunque da 0100579C) e ha memorizzato lì i secondi trascorsi dall'inizio della partita.

Ecco perchè creare un trainer è una cosa difficoltosa con alcuni giochi, è necessario realizzare un memory patching che tenga conto che l'indirizzo nel quale viene memorizzato il valore che ci interessa cambiare, può cambiare anch'esso!

Ancora.. se prato fiorito fosse protetto da DMA, non potrei scrivere un programma che imposti a zero il valore da 4 bytes contenuto in 0100579C, perchè al successivo riavvio di prato fiorito non succederebbe nulla dato che il programma ha memorizzato i secondi trascorsi dall'inizio della partita in qualche altra locazione, in un altro indirizzo.

Ora penso che abbiate capito.

Infine c'è da far notare che nei giochi protetti da DMA non significa nulla aver individuato l'indirizzo in cui vengono memorizzati ad esempio i crediti di gioco, dato che spesso questi indirizzi oltre a cambiare ogni volta che si avvia il gioco sono spesso affiancati da un ciclo di controllo che ne evita la manipolazione, ovvero una volta trovati potremmo non essere in grado di cambiarli (il gioco se ne frega se li cambiamo con i valori che vogliamo noi e continua ad usare i valori precedenti).

Tutte queste situazioni sono racchiuse dalla sigla DMA e questa è anche la differenza che intercorre tra un memory patching basilare e un memory patching di classe.


Come fregare il DMA

Qualche buona notizia al riguardo del DMA.

Ogni gioco protetto da DMA può dunque variare gli indirizzi di memoria in cui vengono memorizzati i dati di gioco negandoci la possibilità di creare un trainer decente.

Ma ogni gioco (e non solo quelli protetti da DMA) ha una caratteristica: un cosiddetto 'game code', delle istruzioni di gioco fisse e non spostabili da un indirizzo all'altro.

Cosa ce ne frega a noi?

Ce ne frega parecchio dato che questo 'game code' sceglie e determina a che indirizzo vengono memorizzati i dati che ci interessano e che cambiano in continuazione.

Ancora: per fare un trainer per un gioco non protetto da DMA semplicemente scriviamo un programma che cambi l'indirizzo XXXXXXXX nel valore che ci interessa. Per fare un trainer per un gioco con DMA non dobbiamo cambiare il valore agli indirizzi che ci interessano in quanto sarebbe inutile (al successivo avvio del gioco sarebbero diversi) ma dobbiamo trovare il 'game code', quella serie di istruzioni in assembler che allocano la memoria (allocare = mettere a disposizione scegliendo un indirizzo ben preciso) dove verranno salvati i dati che ci interessano.

Se non è chiaro non c'è da preoccuparsi, con gli esempi si capisce sempre meglio.


La conoscenza dell'ASM

Non servirebbe nemmeno dirlo in questo eccezionale sito di reversing qual'è la UIC, ma per fare un trainer ai livelli l4m3ri che intendo io non c'è bisogno di una buona conoscenza di linguaggio Assembler, ma conoscere questo linguaggio aiuta estremamente a districarsi in un qualsiasi contesto in cui dobbiamo patchare o cambiare qualcosa in un programma di cui non abbiamo i sorgenti.

Chiunque volesse realizzare game training a livello professionale è invitato caldamente a studiarsi prima come viene utilizzata la memoria dai sistemi operativi e un corso di linguaggio assembler: Corsi di Assembly.


Creiamo un trainer per Command & Conquer 3: Tiberium Wars

Dunque prendiamo un gioco serio che utilizzi la protezione fornita dal DMA, in questo tutorial scelgo Command & Conquer 3: Tiberium Wars dato che è il gioco più recente che gira su questo scassone di pc che ho a disposizione. In più mi è sempre piaciuta la saga di C&C con il mitico Kane.

Dunque, dato che "il tiberium è la via", potremmo provare immediatamente a verificare ciò che ho appena spiegato. Ovvero potremmo subito attivare il nostro CE, aprire il processo "cnc3game.dat", ricercare l'indirizzo ad esempio dei crediti di gioco (solitamente si parte con 20.000 o 25.000 fondi) per poi tornare al gioco, costruire una costruzione qualsiasi per far decrementare i fondi, tornare in CE e cercare il nuovo valore fra quelli che avevamo già trovato. In questo modo ci comporteremmo se il gioco non fosse protetto da DMA.

Nota che è buona abitudine scansionare il processo di gioco con l'opzione "pause the game while scanning", altrimenti corriamo il rischio che il valore che stiamo cercando in quell'istante cambi prima che CE l'abbia individuato.


In ogni caso trovare il valore (solitamente per i crediti di gioco se ne trovano due, dunque non è detto che ci sia un unico indirizzo) e cambiarlo è poco utile in quanto anche se il patching riuscisse (se cambio il valore che ho appena trovato col metodo classico il gioco viene effettivamente mafiato) al successivo riavvio del gioco dovrei rifare tutta la procedura per trovare un altro indirizzo dove il gioco ha memorizzato i soldini. E dunque non si può fare un trainer che cambi questi valori automaticamente.

Way back al game code

Il tutorial prenderà la piega di un training specifico per C&C3: Tiberium Wars ma le nozioni presentate qui possono essere adattate a quasi tutti i giochi.

E ricordate che tutto questo è a scopo informativo, ciò implica che se venite a rompere dicendo che questo metodo non funziona sul gioco xxx io me ne frego e vi mando al diavolo. Tenetelo bene a mente. Domande costruttive per piacere.

Dunque, è ormai chiaro che dobbiamo trovare questo famigerato 'game code' per poter fottere il DMA.

CE e tutti i memory searcher come TSearch e simili hanno ottime funzionalità per fornirci informazioni avanzate di debugging. In poche parole ci aiutano a trovare gli indirizzi di memoria fissa (del game code) che richiamano o allocano gli indirizzi fasulli e variabili che noi troviamo con le nostre scansioni.

Dunque se noi troviamo l'indirizzo vero, l'indirizzo del 'game code' (e ripeto che gli indirizzi del codice di gioco sono FISSI, non possono cambiare!), possiamo, con una minima conoscenza di linguaggio assembler, patcharlo a nostro piacimento per il nostro scopo.

Passiamo all'esempio ma ricordiamoci che una buona conoscenza di Assembler ci aiuterà non poco.

Gli indirizzi del Game Code

Avviamo C&C3 e avviamo subito una partita in modalità schermaglia per fare i nostri test.

Notare che fa molto ma molto comodo avviare il gioco in modalità finestra e non a schermo intero, ci evita di passare dal gioco a CE in continuazione riducendo il gioco a icona e aspettare per ricaricarlo quando dobbiamo tornare in modalità fullscreen. Solitamente i giochi più recenti permettono da linea di comando questa modalità, comunque famo una prova che non è mai sbagliato. Se non funziona significa che il gioco non permette un passaggio a modalità finestra.

Per attivare la modalità finestra del gioco possiamo:

premere Alt+Invio una volta all'interno del gioco in fullscreen (su alcuni giochi come lineage2 funziona)
attivare il gioco da un collegamento sul desktop con aggiunta l'opzione -win. Per fare questo creiamo un collegamento al gioco sul desktop, apriamolo con tasto destro->proprietà e nel campo "Destinazione" racchiudiamo il percorso fra virgolette "" e aggiungiamo alla fine " - win" (attenzione agli spazi) come nella seguente figura

Se nessuno dei due metodi precedenti funziona forse il gioco non supporta la modalità a finestra. Ci sono altri metodi più invasivi per "forzare" un gioco a finestrizzarsi ma sono poco ortodossi, questi sono quelli certificati.

Comunque sia avviamo il gioco e avviamo anche CE con esso.

Sempre rispetto a C&C3, cerchiamo secondo il metodo classico i valori dei nostri crediti con CE e individuiamo due valori (che tanto per ricordare a proposito del DMA, sono totalmente diversi da quelli della precedente scansione).


A questo punto sfruttiamo le potenzialità di CE per trovare gli indirizzi del game code che li hanno allocati/modificati.

Per fare questo clicchiamo su uno dei due valori individuati col tasto destro e scegliamo "Find out what accesses to this address" (oppure specificatamente Find out what reads/writes from/to this address se sappiamo che un indirizzo legge o scrive in quel valore) per trovare tutti gli indirizzi che accedono all'area di memoria che abbiamo trovato, cioè tutti gli indirizzi che accedono per scrivere, cambiare o leggere i crediti che abbiamo nel gioco.


Solitamente i valori che troviamo con questo processo sono indirizzi del game code, cioè gli indirizzi fissi che ci permetterebbero di creare un trainer funzionante al 100%, ma in alcune occasioni ho trovato anche indirizzi allo stesso modo variabili (o forse avevo semplicemente fatto casino con CE, bho). In tal caso dovremmo ripetere la procedura fino a individuare i valori statici del game code.

In questo caso una volta scelta l'opzione "Find out what accesses to this address", CE si trasformerà in un vero e proprio Debugger che ci mostrerà il codice assembler (ecco perchè ci serve conoscere l'asm) e gli indirizzi delle istruzioni che hanno, per un motivo o per un altro, avuto accesso ai nostri crediti di gioco.


Perfetto, cliccando su di un valore e poi su "More information" CE tenta anche di dare una interpretazione dell'indirizzo a cui punta quell'istruzione (e di solito infatti coincide con i valori variabili che troviamo con la prima, classica scansione).

Ma ciò poco ci interessa, clicchiamo invece su di un valore che ci pare significativo (qui si va a tentativi se non abbiamo nessuna conoscenza di assembler, se ce l'abbiamo si va a tentativi lo stesso ma con più perizia come un bel sub [esi],eax (guardare figura precedente, è l'ultimo valore).

Come ho scelto questo valore?

sub è in asm l'operazione di sottrazione, e questo codice non fa altro che sottrarre dall'indirizzo a cui punta esi (More information ci dice che l'indirizzo puntato da esi 'probably' è l'indirizzo che abbiamo trovato con la prima scansione, quello variabile dal DMA), il valore che ha eax.

Insomma l'istruzione sub [esi],eax non fa altro che sottrarre dall'indirizzo puntato da esi la quantità eax. E siccome l'indirizzo puntato da esi "More information" ci dice che è l'indirizzo che abbiamo trovato nella scansione, questa maledetta istruzione non fa altro che farci decrementare i crediti di una quantità pari a eax.

Se vogliamo fare una prova possiamo andare immediatamente nel debugger integrato di CE, clicchiamo su sub [esi], eax e scegliamo "Show disassembler", ci viene presentata una finestra che è il Debugger del nostro gioco. Questo è il codice assembler del gioco che stiamo "trainando" e la prima istruzione è proprio quella che abbiamo scelto.


Questo codice è sicuramente game code, cioè le istruzioni che vediamo qui sono fisse, non cambiano indirizzo ogni volta che il programma viene attivato. Ed è qui che dobbiamo fare le nostre modifiche.

Non analizzerò per filo e per segno cosa sono tutti i valori che vediamo in questa finestra e tenete bene a mente che tutto ciò è a scopo informativo e basta. Se volete approfondire l'argomento e scoprire come funziona un debugger studiatevi l'assembler. Parte tutto da lì. Questa roba a dirla tutta non funziona nemmeno sull'ultima versione di C&C3 perchè con gli aggiornamenti cambiano gli indirizzi, dunque non scassate perchè manco lì funziona. Una volta che si padroneggiano questi concetti si adattano le nozioni e si fa quel che si vuole.

"perchè eax? che mi rappresenta eax? e quei valori sulla destra che rappresentano? perchè sotto ci sono quei segnacci? che significa tutto ciò?"

Tutte domande che differenziano un vero trainerista da un ragazzino che fa una cheat e che possono essere soddisfatte in questo stesso sito con un pò di buona volontà.

Detto ciò verifichiamo che l'istruzione che abbiamo individuato sia veramente l'istruzione che ci fa scendere i crediti nel gioco.

Una volta nel debugger integrato di CE posizioniamoci sopra l'istruzione in questione (la sub [esi],eax) e premiamo F5 che corrisponde a "Toggle breakpoint", cioè facciamo bloccare il gioco e il debugger non appena viene eseguita l'istruzione in questione.

Se CE rompe le scatole dicendo "I can't do that! You are currently using another bla bla" significa che uno dei componenti di CE sta già utilizzando la funzione di debugging e quindi dobbiamo chiudere la finestra corrispondente. Nel nostro caso dobbiamo chiudere la finestra dei valori che hanno avuto accesso al valore della nostra prima scansione. Dopo di ciò possiamo fare F5 e mettere un "breakpoint" sull'istruzione che ci interessa.

Quindi torniamo nel gioco e continuiamo la nostra costruzione in modo da decrementare i crediti. Il gioco si bloccherà e noteremo che CE si è impuntato sull'istruzione che avevamo brekkato con F5.


Dall'area di destra possiamo inoltre constatare che esi punta effettivamente all'indirizzo variabile dal DMA che avevamo trovato con la prima scansione e che eax ha valore 7.

Nota bene: tutti i valori espressi in questo contesto sono in esadecimale, base 16. Quindi 7 in esadecimale = 7 in decimale. Ma 10 in decimale non è 10 in esadecimale, bensì 0xA. Ancora una volta tutto questo fa parte del pacchetto di cultura di base del linguaggio assembler e non vi dirò una sola parola di più sulle numerazioni esadecimali o sul linguaggio asm. Non è lo scopo di questo tutorial.

Ad ogni modo l'istruzione non fa altro che decrementare di 7 crediti a botta i nostri fondi memorizzati nell'indirizzo puntato da esi.

Bene, e ora vediamo come evitare questo decremento.

Il patching degli indirizzi

Il più è fatto ma rimane qualche complicazione ancora.

In questo caso il patching è molto ma molto facile.

La soluzione è il NOPPING!

NOP nel linguaggio assembler è l'unica istruzione che consente di non fare assolutamente niente al programma, ovvero una istruzione NOP significa No Operations e quando il programma incontra una istruzione NOP, semplicemente non fa niente. "Non ti curar di loro ma guarda e passa" come diceva il mio professore mentre dormivo, ecco fa esattamente questo.

Dunque clicchiamo due volte sul valore di sottrazione sub [esi],eax e ci si aprirà una comoda finestra di CE che ci chiede di modificare il valore come meglio ci aggrada.


In questo caso scriviamo semplicemente "nop", no operations.

Premiamo OK e CE ci chiederà in sostanza che il codice sub [esi],eax è lungo 2 bytes ma ciò che abbiamo scritto è lungo 1 solo byte e se vogliamo noppare anche i rimanenti bytes con l'istruzione NOP. Scegliamo di sì ed ecco che al posto dell'istruzione sub compaiono un pò di NOP (precisamente due, un nop per ognuno dei due bytes da cui era costituita).


Perchè nelle due figure precedenti ho evidenziato i valori in mezzo all'indirizzo dell'istruzione e all'istruzione stessa?

Cosa rappresentano quei valori?

Questo lo dico dato che spesso i niubbi non ce l'hanno chiaro ma ancora una volta (e che palle..) ricordo che un corso di Assembler è la soluzione.

Prendiamo ad esempio la riga

004A02EF - 8b 53 0c - mov edx, [ebx+0c]
è una comune istruzione assembler e se studiassimo un pò l'asm sapremmo che sposta il valore contenuto nella locazione individuata da quanto vale ebx + 0c (che è in esadecimale e varrebbe 12 in base 10), in edx.

Il numero 004A02EF è l'indirizzo della istruzione e questo è puro game code, non varia mai per nessun motivo (non sono stabiliti da DMA).

Il numero 8b 53 0c è chiamato opcode.

Un opcode sarebbe, detto in parole grezze, la trasformazione della scrittura interpretabile mov edx, [ebx+0c] in un pezzo di linguaggio macchina vero e proprio.

8b 53 0c corrisponde dunque a mov edx, [ebx+0c] nel nostro programma.

E perchè 8b 53 0c è diviso in coppie? Cioè perchè non scrivere 8b530c?

Perchè ogni coppia corrisponde a un byte, e 8b è il primo byte, 53 il secondo e 0c è il terzo.

Per noppare questa istruzione CE avrebbe chiesto se volevamo rimpiazzare il codice di 3 bytes (il mov edx..ecc..) con un codice di 1 byte (il nop) aggiungendo altri bytes nulli alla fine (precisamente 2).

Insomma il risultato sarebbe stato al posto di 8b 53 0c, 90 90 90. Un nop per ogni byte.

Mai noppare a metà una istruzione.

Mai dire di no a CE quando ci domanda di rimpiazzare il codice aggiuntivo con nops a meno che non sappiamo bene cosa stiamo facendo, in quanto se il gioco viene eseguito ed esegue quelle istruzioni dopo il NOP (istruzioni dunque incomplete e incasinate dato che manca il bytes iniziale che abbiamo trasformato in NOP), quasi al 100% provocherà una eccezione e crasherà tutto il programma.

E adesso mi sono perso. Che stavo dicendo all'inizio di questa digressione?

Ah sì, torniamo a CE e notiamo che abbiamo una bella serie di NOP al posto di quel sub famoso.

Bene, rimuoviamo il breakpoint ritornando nella riga evidenziata dal colore rosso e premendo di nuovo F5 (torna di colore normale) e facciamo ripartire il gioco bloccato con F9 (queste scorciatoie le potete trovare nel menu Debug di CE).

Torniamo nel gioco e... uh magia!

La costruzione continua ma i soldi non decrementano!

Questo è il patching più facile, cioè noppare un valore.

Ma per cose più complesse potremmo dover cambiare il codice assembler in un'altra maniera. Molte volte il NOP non è una buona soluzione in quanto se l'istruzione è fondamentale, il nopparla provoca un crash del programma.

In questo caso non lo era ma facciamo un esempio in cui il semplice Nopping non basta.

Sempre relativamente a C&C3 (non ho altri giochi, non mi scassate!) proviamo ora a rendere istantanee le costruzioni.

Cioè proviamo a far dire al gioco "costruzione completa" un millisecondo dopo che abbiamo cliccato sul tasto per iniziare la costruzione.

Uno studio più approfondito

Bene, la cosa non sarà facile come per quella cretinata dei crediti.

In quanto la percentuale di completamento di una costruzione in C&C3 è indicata da un quadratino che si riempie a spicchi in senso orario.


Quando il quadratino è completamente riempito (gli spicchietti che avanzano hanno fatto un giro a 360°) la costruzione è completa.

Qua la cosa non è facile perchè il punto di partenza (la ricerca di un indirizzo con CE e poi la successiva ricerca per valori che sono cambiati fra quelli che abbiamo già trovato) non è più valido.

Quanto diavolo vale ogni singolo spicchietto?

1? Perchè fa un giro a 360 gradi?

Possiamo provarci ma per esperienza troveremmo nient'altro che valori inutili.

Lasciamo perdere i gradi.

Notiamo innanzitutto quanto costa una singola costruzione. Una centrale energetica (la prima che si costruisce) costa 800 crediti.

Dunque ciò significa (a parte la mafiata che abbiamo fatto prima sui fondi) che dev'esserci una variabile che controlla quanto abbiamo pagato quella costruzione man mano che procede fino a 800.

Allora vediamo di sfruttare questa informazione.

Riavviamo il gioco per rendere nullo il patching di prima (è inutile fare qualsiasi cosa se abbiamo bloccato il decremento dei crediti..) e torniamo in missione.

Prendiamo nota di quanti crediti abbiamo (io parto con la missione con 25.000 crediti).

Iniziamo la costruzione della centrale da 800 crediti.

Blocchiamola dopo un pò e mettiamo la costruzione in pausa. Prendiamo nota di quanti crediti abbiamo adesso e sottraiamoli ai crediti iniziali, avremo un valore compreso fra 0 e 800 che è la nostra percentuale di costruzione.

Ricerchiamo in CE questo valore con una prima ricerca e individuiamo tutti gli indirizzi che hanno tale valore.

Torniamo nel gioco e proseguiamo la costruzione per un altro poco e rimettiamola in pausa prima che termini.

Torniamo in CE e sottraiamo quanti crediti abbiamo adesso a quelli iniziali e troveremo un altro valore compreso tra 0 e 800 ma maggiore di quello della prima ricerca.

Dunque facciamo una seconda ricerca sui valori della prima con CE i cui indirizzi corrispondano al nuovo valore trovato.

Ed ecco che abbiamo i soliti due valori.

Questi valori, ancora, sono protetti da DMA e dunque cambiare questi non ci cambierà la vita al successivo riavvio del gioco.

La soluzione è ancora una volta "Find out what accesses to this address" come prima.

Torniamo nel gioco e terminiamo la costruzione.

Torniamo in CE e vediamo quali indirizzi hanno avuto accesso alla percentuale di costruzione.

Nel mio caso ho trovato un valore add [ecx+08], eax.

Controllo con il debugger quanto vale eax mettendo su di esso un bp (breakpoint).. vale 7

e ecx+08 corrisponde a uno dei due indirizzi che ho trovato. Bene.

Qui il patching non è facile però, un NOP non servirebbe a un bel niente in quanto noppare quel coso servirebbe solo a bloccare la percentuale di costruzione.

La soluzione sarebbe trasformare add [ecx+08], eax in qualcosa come add [ecx+08], XXX dove XXX è un valore spropositato come 2000000.

Ma c'è un'altra complicazione:


Per scrivere una fregnaccia come quella che ho detto abbiamo bisogno di almeno 7 bytes mentre dall'opcode di quel valore (01 41 08) vediamo che il codice è lungo 3 bytes!

Potremmo naturalmente sovrascrivere le istruzioni successive per raggiungere i 7 bytes che ci servono e noppare i rimanenti (ancora.. MAI lasciare opcodes incompleti che non siano noppati o faremmo un casino magistrale)

Ma la complicazione peggiore è che l'istruzione successiva è un RET.

Per la mia delizia vi dico che dovete studiarvi il maledetto codice assembler. Ret ad ogni modo è una istruzione che dice al programma di uscire dalla funzione in cui si trova per tornare ad un'altra serie di istruzioni che si trova.. bho.. in qualche altra parte (NdQue: la locazione di ritorno e' salvata semplicemente sullo stack ;p NdAlex: sì va beh ma volevo vedere se lo sapevano anche loro =D).

Può essere molto utile steppare (mettere un breakpoint e far eseguire le istruzioni una per una con F7 o F8 in CE, dove F7 se le fa proprio tutte e va dentro ogni subfunzione CALL mentre F8 salta le CALL permettendoci di non perdere il filo di dove siamo) fino al RET per poi tornare alla CALL chiamante. Ma tutto ciò va nella pratica del codice assembler. Non spenderò altre parole su questo.

Qui la situazione è complessa perchè non possiamo assolutamente sovrascrivere gli opcode del RET perchè altereremmo il flusso del programma in maniera catastrofica (crash al 200%!)

Le istruzioni RET sono quelle istruzioni che MAI E POI MAI vanno noppate o alterate a meno che non siate dei piccoli geni e sapete cosa diavolo state facendo.

Dunque siamo nella cacca perchè per risolvere questa questione ci vorrebbe un bel workaround mirato e preciso.

Ma io non ne ho voglia e nel mio caso la soluzione è facile perchè posso ripetere il procedimento "Find out what accesses to this address" con il secondo valore che ho trovato e qui i valori paiono quasi gli stessi:


Infatti c'è un mov che non so cosa fa, c'è un add [ebx+60],eax che pare spiccicato a quello del primo valore e c'è un bordellone che CE ci dice che è una conversione di dati da un tipo ad un altro e che non mi frega assolutamente.

Ancora una volta vado col debugger su quell'add [ebx+60],eax e qui la cosa pare più umana. C'è spazio di mafiaggio in quanto sotto all'add c'è un bel jmp, un salto a un altro indirizzo.

Naturalmente anche il nop di questo avrebbe potuto provocare qualche casino e avremmo dovuto inventarci qualcosa (come modificare il valore di eax prima che raggiunga l'istruzione add [ebx+60],eax) ma qui pare che non ce ne sia bisogno.

Ora farò una cosa che vi sconsiglio fortemente in quanto non è professionale (qualsiasi esperto di reversing mi darebbe una martellata in testa) ma è molto mafiosa e qui funge alla grande allo scopo. E poi la scienza passa per tentativi 8-)

Cambio dunque il valore eax in un valore spropositato ))

E dico di sì a CE quando mi chiede se voglio sovrascrivere i valori successivi e trasformare in NOP quelli incompleti di quelli che ho sovrascritto.

Ricordiamoci di aver messo un bp sull'istruzione che stiamo modificando o prima se no il gioco la esegue mentre la stiamo modificando (rara possibilità) e famo un casino.


E questo patching è una vergogna per la nobile arte del training.


Però se leviamo il breakpoint e torniamo nel gioco dopo aver premuto F9 per farlo ripartire, noteremo che le costruzioni ora vengono automaticamente realizzate D

Perchè ad ogni ciclo di costruzione al valore di ebx+60 (che è la nostra percentuale di costruzione) viene aggiunto 20000 che è un valore orrendamente grande per quanto supportato dalle costruzioni.

E ci è andata bene che il gioco non crasha dato che gli abbiamo sottratto una o due istruzioni (quelle sovrascritte e noppate alla fine, in questo caso i 7 bytes ci stavano tutti con una istruzione da 3 bytes, quella dell'add, e due istruzioni da 2 bytes, 3+2+2 = 7, preciso!)

Molto ma molto bene.

Lo scopo comunque era solo mostrare che non sempre un Nop è la soluzione migliore e che è pericoloso sovrascrivere o noppare istruzioni successive a quelle che ci interessano. Patching più professionali avrebbero avuto lo stesso effetto però modificando il valore del registro eax prima che venisse aggiunto a ebx+60 (cosa più ortodossa).

Ma non mi interessa.

Se volessimo (tanto per completezza ma non lo analizzerò) abilitare anche gli aggiornamenti istantanei in C&C3 della barra laterale (fra cui il mitico cannone ionico/arma nucleare/faglia!) avrei operato sulla ricerca di valori in riguardo al countdown del cannone ionico (si carica ogni 7 minuti circa e il tempo rimanente è visibile nella parte superiore sinistra dello schermo).

Direi che ora ci rimane l'ultimo punto..


Creare il Trainer

E questa è la parte più facile da fare una volta fatto tutto il resto.

Cosa ci serve per creare un trainer?

Conoscenze di programmazione se vogliamo fare un bel lavoro, oppure potremmo usare dei trainer-maker (CE ne ha anche uno integrato) ma dato che li odio, scriveremo un semplice trainer in C++ che patchi il gioco in modo da realizzare entrambi i patch che abbiamo analizzato in precedenza, ovvero trasformare

l'indirizzo 004a02ed da 29 06 (opcode per sub [esi], eax) a 90 90 (opcode per nop nop)

e l'indirizzo 005d76b6 - 01 43 60 - add [ebx+60],eax (3 bytes) in 005d76b6 - 81 43 60 00 00 02 00 - add [ebx+60],00020000 (7 bytes)

Il secondo patching ripeto che fa schifo ma sarà un interessante esercizio di programmazione realizzarlo.

Dunque per creare un trainer ci serve anche l'indirizzo e l'opcode di cosa andiamo a patchare (l'opcode non è indispensabile ma dobbiamo sapere quali e quanti bytes andiamo a scrivere!)

Il listato base di un trainer C++ che consenta di fare ciò (le interfacce grafiche, gli effetti, la musica di sottofondo e fregnacce varie sono a discrezione di quanto sapete programmare) consiste in:

Controllare se il processo del gioco è in esecuzione
Installare una hotkey (è più professionale, un tasto che premuto applichi la cheat)
Apra il processo di gioco (diritti amministrativi richiesti)
Usi la classica WriteProcessMemory
Bene.

Ecco un listato di codice VC++ che consente di registrare due hotkey (F9 e F10) per attivare i due cheat poc'anzi descritti:


// Trainer.cpp - created by AlexMark (c) 2007
// ISF Way
//

#include
#include //necessario per l'enumerazione dei processi
#include "resource.h"

HINSTANCE hinstance;
HWND hDlgMain;

void Cheat(int mode);
void UnRegisterHotkeys(HWND hwnd);
void RegisterHotkeys(HWND hwnd);
BOOL CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);

//La winmain iniziale
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Memorizza la hInstance
hinstance = hInstance;

//Crea una finestra dove ci sarà scritto "F9 per i crediti, F10 per le costruzioni istantanee.."
//e le assegna la funzione MainDlgProc
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);

return 0;
}

/* Smista i messaggi della finestra */

BOOL CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg){
case WM_INITDIALOG:{
hDlgMain = hDlg;

//Registra le hotkey
RegisterHotkeys(hDlgMain);
}
break;

case WM_HOTKEY:
switch(wParam){
case 5: Cheat(1); //primo cheat
break;
case 6: Cheat(2); //secondo cheat
break;
}
break;

case WM_COMMAND:{
switch(LOWORD(wParam)){
case IDC_CLOSE:{
UnRegisterHotkeys(hDlgMain);
EndDialog(hDlgMain, 0);
}
break;
}
}
}

return FALSE;
}


void RegisterHotkeys(HWND hwnd)
{
RegisterHotKey(hwnd,5,NULL,0x78); //F9
RegisterHotKey(hwnd,6,NULL,0x79); //F10
}

void UnRegisterHotkeys(HWND hwnd)
{
UnregisterHotKey(hwnd,5); //Unregistering HotKeys
UnregisterHotKey(hwnd,6); //Unregistering HotKeys
}

//Memory Patch
void Cheat(int mode)
{

DWORD Process_TID;
PROCESSENTRY32 proc;
HANDLE snapshot;
char process_name[32]="cnc3game.dat"; //game name
BOOL gotime=FALSE; //l'abbiamo trovato?
proc.dwSize = sizeof(proc);
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,0); /*
TH32CS_SNAPALL-> Secondo msdn: Includes all processes and threads in the system,
plus the heaps and modules of the process specified in th32ProcessID.
*/
Process32First(snapshot, &proc); //Ritrova informazioni sul primo processo

do{
// Ricerca del processo di gioco
if(strcmp(proc.szExeFile,process_name)==0) {
gotime = TRUE;
Process_TID = proc.th32ProcessID;
break;
}
}while (Process32Next(snapshot, &proc));

CloseHandle(snapshot);

if (!gotime) return; //se non lo trova, annulla il processo

HANDLE phandle;
phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, Process_TID); //Apre il processo di gioco,
// fondamentale che abbia accesso
if (phandle != 0){

if (mode == 1){ //Primo cheat
WORD hexstring = 0x9090; //una word sono 2 bytes
WriteProcessMemory(phandle, (LPVOID)0x004A02ED, &hexstring, 2 /* 2 bytes di lunghezza*/, NULL);
}

if (mode == 2){
BYTE hexstr[7] = {0x81, 0x43, 0x60, 0x00, 0x00, 0x02, 0x00}; // un array di 7 bytes
WriteProcessMemory(phandle, (LPVOID)0x005d76b6, &hexstr, 7 /* 7 bytes di lunghezza*/, NULL);
}

CloseHandle(phandle);
}else{
//Qualcosa è andato storto
Beep(100, 100);
}
}
Per avere almeno i rudimenti necessari a comprendere qualcosa di questo codice è necessario far riferimento al Corso di C del grande phobos o al Corso di C++ del mio sito.

Analizziamo le parti salienti del listato presentato: il tutto fa parte di un progetto a interfaccia grafica Win32 che crea una finestra dialog box con la funzione DialogBox richiamata nella WinMain.

La funzione MainDlgProc smista i messaggi della finestra in questione e da notare sono le due funzioni RegisterHotkeys e UnRegisterHotkeys che rispettivamente sono richiamate nell'inizializzazione della finestra (WM_INITDIALOG) e prima della sua distruzione ad opera di un pulsante "Chiudi finestra" di ID IDC_CLOSE che ho messo apposta.

Le funzioni in questione registrano e deregistrano i tasti F9 (0x78) e F10 (0x79) tramite le due funzioni quasi omonime per attivare le due cheat che abbiamo analizzato, dando loro id 5 e 6.

La funzione Cheat(int mode) riceve come argomento 1 o 2 a seconda della cheat che viene attivata con F9 o F10 e innanzitutto si sincera che il processo di gioco (nel nostro caso "cnc3game.dat") sia in esecuzione enumerando mediante una struttura PROCESSENTRY32 e uno snapshot dei processi in esecuzione (mi spiace ma non saprei come tradurre in italiano questi termini ._. magari immaginate che venga fatta una "fotografia" a tutti i processi e i sottomoduli di sistema).

Se la funzione strcmp(proc.szExeFile,process_name) restituisce zero (il process_name è stato trovato fra i processi di sistema) è tempo di attivare la cheat, altrimenti viene effettuata l'uscita della funzione ( if (!gotime) return; )

In caso di successo si proverà ad aprire il processo di gioco e qui è fondamentale la funzione OpenProcess che apre il processo con ID Process_TID e tenta di ricevere un handle (una variabile che ne consentirà l'accesso). In caso di fallimento... Beep!

Se anche qui la funzione ha successo, si opera la cheat e il training vero e proprio.

Per il primo cheat era necessario scrivere alla locazione di memoria 004a02ed (0x004a02ed in C++) un paio di nops, ed è esattamente ciò che fa la variabile WORD (una word è un gruppo di bit che corrisponde a 2 bytes o 16 bit, i suoi multipli sono la DWORD di 32 bit e la QWORD di 64 bit) con il valore 0x9090 (due 90 in esadecimale).

La funzione WriteProcessMemory è il cuore di tutto il trainer e scrive alla locazione specificata, una volta aperto il processo tramite l'handle phandle, i dati puntati dalla variabile hexstring che in questo caso è una word di 2 bytes.

Nel nostro secondo caso (tutto questo a scopo dimostrativo e ripeto che è un patching orrendo) abbiamo la necessità di scrivere 7 bytes. Avremmo potuto scrivere una DWORD una WORD e un BYTE ma con un array di 7 bytes la cosa migliora notevolmente.

E ogni singolo byte ha la valenza di un byte dell'opcode che andiamo a modificare.

Il resto è identico e alla fine si scarica l'handle del processo aperto, da bravi programmatori, con una chiamata alla CloseHandle.


Conclusioni

Il trainer è terminato.

Se avete avuto la pazienza di leggere tutto spero che avrete imparato qualcosa di nuovo.

Ricordo ancora una volta e fino alla nausea che per diventare dei traineristi professionisti dovreste studiarvi prima il codice Assembler e imparare la nobile arte del debugging. È questo che differenzia un bambinello che usa Tsearch o Cheat Engine da chi realizza dei trainer professionali.

Da ricordare è che quando si aggiorna un gioco gli indirizzi di memoria possono cambiare, dunque un trainer è strettamente legato alla versione del gioco cui fa riferimento.

Se avete domande (pertinenti e come ho già detto non provate nemmeno a rompere se questo metodo non va su un altro gioco o se le cose sono diverse sullo stesso gioco) come al solito potete contattarmi via mail o forum dell'ISF.

Un ringraziamento al grande Quequero per l'aiuto a postare questa guida qui nel wiki e a tutti coloro che mi hanno aiutato a scriverla.
Torna in alto Andare in basso
http://scommesse-sportive.blogfree.net/
 
Cheat Engine
Torna in alto 
Pagina 1 di 1
 Argomenti simili
-
» Willi27's D3D engine V8
» Willi27's D3D Engine v10

Permessi in questa sezione del forum:Non puoi rispondere agli argomenti in questo forum.
Warfans :: Programmazione :: Software :: Guide & Consigli-
Vai verso: