2014-10-24 12 views
7

Ho cercato un po 'in Cheat Engine, che consente di controllare e manipolare la memoria dei processi in esecuzione su Windows: è la scansione per le variabili in base al loro valore, allora si possono modificare, per esempio imbrogliare in un gioco.Come possono esserci indirizzi statici nei programmi C/C++?

Per scrivere un bot o qualcosa di simile, è necessario trovare un indirizzo statico per la variabile che si desidera modificare, ovvero una che rimane la stessa se il processo viene riavviato. Il metodo per che va grosso modo così:

  1. Individuare l'indirizzo della variabile che ti interessa, la ricerca per il valore
  2. Cercare il codice utilizzando tale indirizzo, per esempio per trovare l'indirizzo della struct a cui appartiene (dal momento che gli offset struct sono fissi)
  3. cercare un altro puntatore che indica che il puntatore finché non si trova uno con un indirizzo statico (indicato come verde a Cheat Engine)

Sembra funzionare bene a giudicare dalle esercitazioni che ho visto, ma ho difficoltà a capire perché funziona.

Non tutte le variabili, tra cui quelli statici globali, ottenere un indirizzo abbastanza casuale in fase di esecuzione?

domande bonus:

  1. Come può Cheat Engine dire se un indirizzo è statico (cioè rimarrà lo stesso al riavvio)?
  2. Un tutorial di cui il fatto che molti anziani e alcuni giochi moderni (ad esempio Call of Duty 4) utilizzano solo indirizzi statici. Come è possibile?

risposta

10

Risponderò prima alle domande bonus perché introducono alcuni concetti che potrebbe essere necessario conoscere per comprendere la risposta alla domanda principale.

Rispondere alla prima domanda bonus è facile se si sa come funziona un file eseguibile: tutte le variabili globali/statiche sono all'interno della sezione .data, nella quale l'exe l'indirizzo di offset per la sezione in modo Cheat Engine controlla solo se la variabile si trova in questo intervallo di indirizzi (da questa sezione alla successiva).

Per la seconda domanda, è possibile utilizzare solo indirizzi statici, ma è quasi impossibile per un gioco. Anche i più grandi. Quello che probabilmente il creatore del tutorial stava cercando di dire è che tutte le variabili che desiderava, in realtà avevano un puntatore statico che punta a loro. Ma solo dal fatto che si crea una variabile locale, o addirittura si passa un argomento a una funzione, i loro valori vengono memorizzati nello stack. Ecco perché è quasi impossibile avere un programma "solo statico". Anche se si compila un programma che in realtà non fa nulla, è probabile che alcune cose vengano memorizzate nello stack.

Per l'intera domanda, non tutte le variabili di indirizzo dinamiche sono indicate da una variabile globale. Dipende totalmente dal programmatore. Posso creare una variabile locale e non assegnare mai il suo indirizzo a un puntatore globale/statico in un programma C, ad esempio. L'unico modo certo per trovare quell'indirizzo in questo caso è conoscere effettivamente il codice quando alla variabile è stato assegnato per la prima volta un valore nello stack.

Alcune variabili hanno un indirizzo dinamico perché sono solo variabili locali, che vengono memorizzate nello stack la prima volta che gli viene assegnato un valore.

Alcune altre variabili hanno un indirizzo statico perché sono dichiarate come variabili globali o statiche nel compilatore. Queste variabili hanno un offset di indirizzo fisso che fa parte della sezione .data nel file eseguibile.

Il file eseguibile ha un indirizzo di offset fisso per ogni sezione al suo interno e la sezione .data non fa eccezione.

Ma vale la pena notare che l'offset all'interno dell'eseguibile stesso è fisso. Nel sistema operativo le cose potrebbero essere diverse (tutti gli indirizzi casuali), ma questo è il lavoro di un sistema operativo, estrapolando questo tipo di cose per te (creando lo spazio degli indirizzi virtuali dell'eseguibile in questo caso). Quindi sembra proprio che le variabili statiche siano in realtà statiche, ma solo all'interno dello spazio di memoria dell'eseguibile. Sulla RAM le cose potrebbero essere ovunque.

Infine, è difficile provare a spiegartelo perché dovrai capire come funzionano i file eseguibili. Un buon inizio sarebbe la ricerca di alcune spiegazioni riguardanti la programmazione di basso livello, come lo stack frame, le convenzioni di chiamata, il linguaggio Assembly stesso e come i compilatori utilizzano alcune tecniche ben note per gestire le funzioni (ambiti in generale), globale/statico/locale/variabili costanti e il sistema di memoria (sezioni, stack, ecc.) e forse qualche ricerca sui file PE (e persino ELF).

+0

Il mio male, ho fatto alcuni test con variabili statiche per vedere se i loro offset sono corretti e sembrava che non lo fossero, ma ho avuto un errore lì :(Quindi sì, le variabili statiche sembrano essere in compensazioni fisse in genere, Per quanto riguarda la domanda principale, che ne è di un programma in cui tutti i dati sono mantenuti nello stack/heap senza alcun riferimento statico a quello? È abbastanza tipico in C++ almeno. Come lo vedo, se non c'è statico variabile _somewhere_ che punta a questi dati, non è possibile ottenere un indirizzo statico per questo - ma sembra funzionare praticamente per tutti i giochi. – futlib

+0

Cheat Engine non cerca solo "indirizzi statici" quando si esegue una scansione puntatore. Questo è il motivo per cui è necessario eseguire la scansione molte volte in diversi stati del gioco (e diverse esecuzioni) per ottenere un indirizzo che sembra servire allo scopo per gli stati del gioco che hai passato durante la scansione. Ma non è garantito che questo puntatore conservi sempre l'indirizzo che desideri. Quindi fondamentalmente cerca puntatori statici e locali. –

+0

Ma allora perché un puntatore locale ha sempre lo stesso offset? Probabilmente perché è stato assegnato così presto nella pila, che rimane nei primi ambiti aperti all'inizio del gioco, forse prima del ciclo principale, che rimarrà valido fino a quando il gioco non chiuderà abbastanza ambiti per poi fare in modo che questo puntatore conservi la memoria inutile. –

2

Per quanto ho capito, le variabili dichiarate statiche hanno un offset permanente all'interno dei dati del programma. Ciò significa che quando il programma viene caricato nella RAM, l'offset della variabile sarà sempre lo stesso. Poiché l'indirizzo iniziale del programma è noto a livello globale, trovare una variabile statica basata sull'offset, come hai detto, dovrebbe essere un compito banale. Pertanto, mentre un puntatore a una variabile statica potrebbe essere casuale nello schema delle cose, il suo offset all'inizio della memoria del programma dovrebbe rimanere lo stesso, non importa quando il programma inizia. Quindi Cheat Engine (anche se non conosco il software) probabilmente memorizza l'offset della variabile statica, e quindi all'avvio del software applica questa logica per trovare quella variabile.

In quanto a come può dire che è una variabile statica in primo luogo ... beh, questo è parzialmente un'ipotesi, ma quando dichiari una variabile statica in C, sto assumendo che il compilatore/linker inserisca qualcosa di flag in modo che il sistema operativo sappia che si tratta di una variabile statica. Potrebbe anche essere che tutte le variabili statiche sono memorizzate in un certo modo, o ad un certo offset di indirizzo, per tutti i programmi compilati per un determinato sistema di destinazione. Di nuovo, non troppo sicuro su questo, ma da quello che capisco sulla gestione della memoria, sembra avere più senso. Con questi presupposti, è abbastanza possibile che un programma contenga solo variabili statiche. La differenza è che la memoria viene assegnata staticamente al runtime del programma, in opposizione a dinamicamente (come con una chiamata a malloc() o simile). Se le variabili fossero memorizzate dinamicamente, sono sicuro che ci sarebbe un modo per trovarle facilmente, quindi non penso che sia importante per Cheat Engine, indipendentemente dal fatto che una variabile sia statica o meno. Tuttavia, come presumo Cheat Engine vuole modificare un gioco all'avvio (proprio come i vecchi GameSharks abituati a ... ahh, perdere quei giorni) è probabilmente più affidabile modificare le variabili che sono statiche, invece di cercare di individuare i puntatori e smontare il codice, ecc. ecc.

Se sei interessato a saperne di più, ti consiglio di controllare qualcosa come this tutorial over at OSDev!

Problemi correlati