La tua domanda è molto ampia. Posso raccontarti di come I abbiamo fatto in un'istanza, per divertimento, in un piccolo gioco arcade diversi anni fa. Questo dovrebbe farti guadagnare qualche intuizione educativa, ma non ti aiuterà molto altrimenti, temo.
Ho semplicemente avuto un altro programma in esecuzione in background, mirando alla memoria del gioco arcade.
Ho iniziato a giocare, e poi ho perso una vita. Premi entrambi i tasti Maiusc e un'istantanea della memoria è stata salvata sul disco all'insaputa della sala giochi in esecuzione. Poi un altro BAM un'altra istantanea. Un terzo e un quarto. E poi game over e sono uscito dal gioco arcade.
Poi ho appena confrontato le istantanee, cercando una locazione di memoria che è cambiata da un'istantanea alla successiva, aumentando o diminuendo di una sola. Ricordo di averne trovato una ventina. Avrei potuto controllare tutti loro, ma ho notato immediatamente che uno di loro, e solo uno, aveva valore "cinque" all'inizio del gioco, e divenne "quattro" alla mia prima morte. E avevo iniziato con cinque navi. Ora è interessante ...
Così ho scritto un piccolo programma che cercava quell'indirizzo di memoria, riconoscendolo dalla sua distanza da altri pezzi di codice e stringhe che non cambiavano, controllandone il valore ogni pochi secondi, e basta rimandare indietro "5" non appena è diventato qualcosa di meno:
: install
look for string 'COPYRIGHT ACME GAMES'
add 1138
is it a five?
no, abort, something went wrong
yes. lie in wait.
: wait
is it still a five?
no. Set it to five.
sleep for a couple of seconds
goto wait
Certamente, alla prossima partita, sono morto - e un istante dopo, le mie quattro astronavi rimanenti sono diventate nuovamente cinque. Per quanto mi riguarda, ho scoperto che potevo ottenere fino a sette "vite" con questo metodo (otto si sono schiantati nel gioco).
Usando un "debugger" sarebbe stato anche possibile fermare il programma non appena la posizione è stata modificata, quindi vedere quale istruzione aveva fatto l'atto. Quindi cancelleresti quella singola istruzione dal codice assemblatore. Oppure puoi seguire il flusso del programma al contrario e scoprire dove, ad esempio, è stato effettuato il controllo della collisione tra lo sprite del tuo giocatore e i missili nemici. Contrastare quell'assegno ei missili nemici non ti riguardano più (forse anche i tuoi non li influenzano, è un affare complicato).
Mi aspetto che le tecniche siano maturate e progredite molto in questi anni, ma sono sicuro che sostanzialmente l'idea è sempre la stessa: individuare il cambiamento che non ti piace, o defang il codice che lo causa, o patch il codice in modo che il danno sia annullato non appena si verifica.
Per rendere le cose più difficili si potrebbero escogitare strategie per rendere meno rilevanti le modifiche o renderle apparentemente casuali. Aggiungi variabili "chaff" o "dummy" che cambiano proprio come se fossero utili. Usali come telltales: se tutte le variabili non coincidono, significa che qualcuno sta cercando di hackerare.
Alla fine, comunque, non puoi battere un hacker determinato ed esperto. Tutto quello che puoi fare è provare a fare in modo che l'azione non ne valga la pena. Ci sono gli offuscatori di codice, i protettori di codice, i crittografi di codice, i rilevatori di debugger, le tecniche di anti-virtualizzazione ...