Risolto Reversing Company of Heroes 3 problema con gli indirizzi

xivan

Utente Silver
26 Febbraio 2010
6
1
1
60
sapete se questo gioco ha qualche tipo di protezione sugli indirizzi di memoria?

Trovo l'indirizzo delle munizioni, trovo il codice che scrive a questo indirizzo utilizzando cheat engine. il problema è che quando faccio il contrario, cioè vedo dal codice a quale indirizzo scrive, noto che non scrive mai all'indirizzo della munizione che ho trovato in precedenza.

Com'è possibile?

Immagine 2023-11-11 185410.png



grazie a tutti per l'aiuto
 
Dalla situazione descritta mi viene da pensare che il gioco conservi quest'informazione in un oggetto, quindi l'indirizzo cambia in base all'oggetto in questione. Possibile che tra le due scansioni hai cambiato arma?
 
Dalla situazione descritta mi viene da pensare che il gioco conservi quest'informazione in un oggetto, quindi l'indirizzo cambia in base all'oggetto in questione. Possibile che tra le due scansioni hai cambiato arma?
Grazie per l'interessamento.
Il gioco consiste che hai delle scorte, munizioni, carburante e manodopera, ora, per costruire delle unità, consumo un certo quantitativo di munizioni, manodopera e così via. Questo per farti capire che non posso cambiare nessun tipo di arma. È un gioco di strategia in tempo reale.

La cosa che noto, è che l'istruzione che copia xmm0 nell'indirizzo, viene eseguita da più thread.
 
Riguardando meglio c'è qualcosa che non va perché gli indirizzi che hai trovato prima sono esattamente 0x0C più in alto di quelli nuovi ma non può essere la stessa struttura perché i valori xmm occupano 0x10, sospetto che quell'area di memoria venga liberata e poi riallocata. Comunque hai provato a vedere il codice chiamato da call [rax + 10] ? Essendo quello a ritornare il valore che poi viene scritto nella memoria potresti scoprire che prende il valore da un'altra parte e a te interessa trovare quell'indirizzo.
Sto un po andando alla cieca perché non ho abbastanza informazioni e non ho mai visto o reversato questo gioco, ma hai provato a vedere con un breakpoint se da quella funzione passa solo il valore delle munizioni o anche altro?
 
Riguardando meglio c'è qualcosa che non va perché gli indirizzi che hai trovato prima sono esattamente 0x0C più in alto di quelli nuovi ma non può essere la stessa struttura perché i valori xmm occupano 0x10, sospetto che quell'area di memoria venga liberata e poi riallocata. Comunque hai provato a vedere il codice chiamato da call [rax + 10] ? Essendo quello a ritornare il valore che poi viene scritto nella memoria potresti scoprire che prende il valore da un'altra parte e a te interessa trovare quell'indirizzo.
Sto un po andando alla cieca perché non ho abbastanza informazioni e non ho mai visto o reversato questo gioco, ma hai provato a vedere con un breakpoint se da quella funzione passa solo il valore delle munizioni o anche altro?
si esattamente, la memoria che fa riferimento [rsi+000002B0] viene riallocata continuamente. come se fosse un gestore di coda di eventi, dove rax è il puntatore dell'oggetto, e rax+10 è la chiamata di un funzione che esegue le operazioni che dovrebbe svolgere quell'oggetto in coda.
Scrivo la funzione un po piu allungata .
mov rax,[rbx] lea rdx,[rsp+30] mov rcx,rbx call qword ptr [rax+10] movups xmm0,[rax] movups [rsi+000002B0],xmm0 { qui assegna le munizioni} movups xmm1,[rax+10] movups [rsi+000002C0],xmm1 movsd xmm0,[rax+20] movsd [rsi+000002D0],xmm0 mov rax,[rbx] lea rdx,[rsp+58] mov rcx,rbx call qword ptr [rax+18] movups xmm0,[rax]
Comunque mi sono fatto sfuggire un particolare, guardando i registri xmm0, al momento dell'assegnazione del valore, ho notato che xmm0, come se fosse una struttura perche conteiene rispettivamanete il carbuarante(quello cerchiato in bianco), ed le munizioni(quelle cerchiate in rosso). al momento dell'assegnaione copia interamente il resgistro a 64 bit xmm0, per questo gli indirizzi si trovano a +0x0c
Immagine 2023-11-12 181657.png

quello che vedi in rosso sono le munizioni che saranno copiate in una locazioni di memoria a + 0x0c rispettivamente agli indirizzi che ho trovato in basso.


ti faccio notare quest'altra cosa strana di questo gioco. io ho trovato l'indirizzo in memoria responsabile delle munizioni, studiando un po il codice sono riuscito a trovare la struttura del player.
Immagine 2023-11-12 182949.png

in questa foto, la variabile che sto monitorando, è una variabile che cambia continuamente, cioè viene incrementata, ma vedi un po, nulla nel codice ci scrive, ma com'e possibile???
 
si esattamente, la memoria che fa riferimento [rsi+000002B0] viene riallocata continuamente. come se fosse un gestore di coda di eventi, dove rax è il puntatore dell'oggetto, e rax+10 è la chiamata di un funzione che esegue le operazioni che dovrebbe svolgere quell'oggetto in coda.
Scrivo la funzione un po piu allungata .
Ok ma rsi a cosa punta, da dove viene?

Comunque mi sono fatto sfuggire un particolare, guardando i registri xmm0, al momento dell'assegnazione del valore, ho notato che xmm0, come se fosse una struttura perche conteiene rispettivamanete il carbuarante(quello cerchiato in bianco), ed le munizioni(quelle cerchiate in rosso). al momento dell'assegnaione copia interamente il resgistro a 64 bit xmm0, per questo gli indirizzi si trovano a +0x0c

quello che vedi in rosso sono le munizioni che saranno copiate in una locazioni di memoria a + 0x0c rispettivamente agli indirizzi che ho trovato in basso.

Questa è solo un'ottimizzazione del compilatore, di solito quando operi con strutture come questa:
C:
typedef struct {
    float ammo;
    float gas;
    float foo;
    float bar;
};

e assegni tutti i valori di seguito (o copi l'intera struttura), il compilatore userà un registro xmm a 128 bit per fare una copia più rapida di 4 numeri a 32 bit alla volta.
Ma se gli indirizzi che hai trovato in due step differenti si riferiscono alla stessa risorsa allora ad essersi spostata di 0xC è la base della struttura, mi viene difficile da pensare che cambiano la posizione dei campi a runtime, sarebbe inutilmente folle.

ti faccio notare quest'altra cosa strana di questo gioco. io ho trovato l'indirizzo in memoria responsabile delle munizioni, studiando un po il codice sono riuscito a trovare la struttura del player.

in questa foto, la variabile che sto monitorando, è una variabile che cambia continuamente, cioè viene incrementata, ma vedi un po, nulla nel codice ci scrive, ma com'e possibile???

Questo dipende dal modo in cui calcola l'offset al dato, cheat engine potrebbe non riuscire a trovarlo se fatto in modo dinamico, ti consiglio di mettere un hardware breakpoint a quell'indirizzo e vedere la call stack.
 
Ok ma rsi a cosa punta, da dove viene?



Questa è solo un'ottimizzazione del compilatore, di solito quando operi con strutture come questa:
C:
typedef struct {
    float ammo;
    float gas;
    float foo;
    float bar;
};

e assegni tutti i valori di seguito (o copi l'intera struttura), il compilatore userà un registro xmm a 128 bit per fare una copia più rapida di 4 numeri a 32 bit alla volta.
Ma se gli indirizzi che hai trovato in due step differenti si riferiscono alla stessa risorsa allora ad essersi spostata di 0xC è la base della struttura, mi viene difficile da pensare che cambiano la posizione dei campi a runtime, sarebbe inutilmente folle.



Questo dipende dal modo in cui calcola l'offset al dato, cheat engine potrebbe non riuscire a trovarlo se fatto in modo dinamico, ti consiglio di mettere un hardware breakpoint a quell'indirizzo e vedere la call stack.
guarda ti spiego dove sono arrivato ad oggi.

come ti dicevo, ho trovato la struttura del player, questa struttura è puntata da un registo ad un punto nel codice. Ai primi indirizzi di questa struttura sono allocati i 3 float, che sono munizioni manodopera ecc. ovviamente modificare direttamente i valori in questa struttura, era impossibile, perche c'era sempre un thread che sovrascriveva il valore esatto. poi scorrendo questa struttura, ho notato di nuovo i tre float, modifico quelli, ed ecco qua che tutto funziona, ora modificando quei valori, modifico effettiavemente i valori nel gioco. ma allora mi sono chiesto: com'e possibile che io ho cercato questi valori attraverso lo scann, ed ho trovato sempre i solit 4 indirizzi (tre float ed in integer)? cioè come mai quelli "veri" non li ho mai trovati?. Ho risolto questo problema cambiando alcune impostazioni dello scann, infatti dopo aver modificato le impostazioni dello scann di CE, rifaccio la scansione, ed ecco qua che compaiono questa volta 5 indirizzi , 4 float ed il solito integer, uno dei float e quello esatto. Poi mi sono messo ad andare a ritroso nel codice per verificare come calcola l'offset della struttura del player, ed ho notato questo:

Codice:
mov rax,gs:[00000058]

praticamente, utilizza il registro gs del thread per ottenere il puntatore della struttura del player. Quindi io per ottenere gli offset del puntatore alla struttura dovrei prima leggere il registro gs, mi pare che il registro gs si ricava attraverso il TEB del thread? o sbaglio.
 
guarda ti spiego dove sono arrivato ad oggi.

come ti dicevo, ho trovato la struttura del player, questa struttura è puntata da un registo ad un punto nel codice. Ai primi indirizzi di questa struttura sono allocati i 3 float, che sono munizioni manodopera ecc. ovviamente modificare direttamente i valori in questa struttura, era impossibile, perche c'era sempre un thread che sovrascriveva il valore esatto. poi scorrendo questa struttura, ho notato di nuovo i tre float, modifico quelli, ed ecco qua che tutto funziona, ora modificando quei valori, modifico effettiavemente i valori nel gioco. ma allora mi sono chiesto: com'e possibile che io ho cercato questi valori attraverso lo scann, ed ho trovato sempre i solit 4 indirizzi (tre float ed in integer)? cioè come mai quelli "veri" non li ho mai trovati?. Ho risolto questo problema cambiando alcune impostazioni dello scann, infatti dopo aver modificato le impostazioni dello scann di CE, rifaccio la scansione, ed ecco qua che compaiono questa volta 5 indirizzi , 4 float ed il solito integer, uno dei float e quello esatto. Poi mi sono messo ad andare a ritroso nel codice per verificare come calcola l'offset della struttura del player, ed ho notato questo:

Codice:
mov rax,gs:[00000058]

praticamente, utilizza il registro gs del thread per ottenere il puntatore della struttura del player. Quindi io per ottenere gli offset del puntatore alla struttura dovrei prima leggere il registro gs, mi pare che il registro gs si ricava attraverso il TEB del thread? o sbaglio.

Quell'istruzione serve a ottenere la base del Thread Local Storage (TLS) e si, ci puoi accedere da TEB->TlsSlots
 
Wow quindi c'è da fare un casino. Poi bisogna essere certi che è quello il thead giusto. Mi sa che mi conviene modificare l'assembly, invece di ottenere il puntatore alla struttura.

Penso anch'io che in questo caso sia più rapido fare una patch delle istruzioni, per farlo pulito senza cercare il thread bisognerebbe studiare quando e come il puntatore alla struttura viene settato nel tls e se è possibile trovarlo in altro modo ma è un lavoro evitabile se non c'è un anticheat che rileva le tue modifiche al codice.
 
Penso anch'io che in questo caso sia più rapido fare una patch delle istruzioni, per farlo pulito senza cercare il thread bisognerebbe studiare quando e come il puntatore alla struttura viene settato nel tls e se è possibile trovarlo in altro modo ma è un lavoro evitabile se non c'è un anticheat che rileva le tue modifiche al codice.
Guarda non so come ringraziarti per avermi aiutato. Grazie mille, se ho qualche altro dubbio, so dove cercare aiuto :)
 
  • Mi piace
Reazioni: JunkCoder