Monitoraggio della Memoria in DOOM con Frida
In alcune situazioni, potrebbe capitare di imbattersi in dati di memoria intriganti e desiderare di identificare il codice che li gestisce. L'API MemoryAccessMonitor di Frida può risultare complicata a causa della granularità delle pagine, specialmente su sistemi moderni con pagine da 16K. Questo rende difficile raccogliere campioni sufficienti per catturare il codice che accede a specifici byte.
Nuove Funzionalità di Frida
Per migliorare questa esperienza, @hsorbo e un altro sviluppatore hanno implementato il supporto per breakpoint hardware e watchpoint. Ora, gli oggetti thread restituiti da Process.enumerateThreads()
dispongono di metodi come setHardwareBreakpoint()
e setHardwareWatchpoint()
, oltre a metodi per disattivarli successivamente. Questi possono essere combinati con Process.setExceptionHandler()
per gestire le eccezioni e riprendere l'esecuzione del codice.
Esempio Pratico: DOOM + DOOM II
Per testare queste nuove API, si è scelto di analizzare la recente riedizione del 2024 di DOOM + DOOM II. La prima operazione consiste nel localizzare in memoria il numero di proiettili disponibili. Si può creare un piccolo agente per facilitare questa operazione:
Caricando l'agente nel gioco, si sa che attualmente ci sono 50 proiettili. Si procede quindi a cercare tutte le allocazioni di heap contenenti il valore 50, codificato come un uint32
nativo.
Filtraggio dei Risultati
Dopo aver trovato molte allocazioni, si può restringere il campo sparando un proiettile e verificando quali posizioni ora contengono il valore 49.
Risultato: Si identifica con successo dove è memorizzato il numero di proiettili. Il passo successivo è trovare il codice che aggiorna questo numero quando un proiettile viene sparato. Si aggiunge quindi una funzione di supporto all'agente:
Dopo aver sparato un altro proiettile, si può simbolizzare l'indirizzo ottenuto. Utilizzando r2, si può osservare che il contatore del programma si trova sull'istruzione immediatamente successiva a quella che ha attivato il watchpoint.
Creazione di Hook e Cheat
Da qui, è possibile impostare un hook inline che si attiva ogni volta che un proiettile viene sparato. Inoltre, si può facilmente creare un cheat per avere munizioni infinite. È importante notare che si sarebbe potuto ottenere lo stesso risultato utilizzando Memory.patchCode()
per sostituire l'istruzione con un NOP
di 3 byte, ma l'hook dell'Interceptor ha il vantaggio di essere automaticamente annullato quando lo script viene scaricato.
Supporto per Windows su ARM
Un'altra novità significativa di questa versione è il supporto per Windows su ARM. Ciò significa che una versione arm64 di Frida può iniettarsi in processi nativi arm64, oltre a processi emulati x86_64 e x86. Tuttavia, non sono ancora disponibili i binari, poiché si attende che GitHub fornisca runner arm64 per progetti OSS, attualmente limitati ai clienti Team e Enterprise Cloud.
Altre Novità
Ci sono anche molte altre modifiche interessanti, tra cui:
- linux: Gestione dei processi chiusi durante il distacco. Grazie a @ajwerner!
- java: Gestione dei gestori del ciclo GC di Android non esportati. Grazie a @thinhbuzz!
- java: Supporto preliminare per OpenJDK 17 su Windows. Grazie a @FrankSpierings!
- meson: Aggiunta di frida-netif al frida-core pubblico, affinché i devkit di frida-core includano tutti i simboli necessari.