Tecniche anti-inversione (Parte 2)

Dec 05 2022
Nella prima parte abbiamo discusso alcune tecniche comuni utilizzate dagli autori di malware per proteggere le proprie applicazioni dal reverse engineering. In questa seconda parte, daremo un'occhiata a più metodi e tecniche utilizzate per rilevare e prevenire il reverse engineering.

Nella prima parte abbiamo discusso alcune tecniche comuni utilizzate dagli autori di malware per proteggere le proprie applicazioni dal reverse engineering. In questa seconda parte, daremo un'occhiata a più metodi e tecniche utilizzate per rilevare e prevenire il reverse engineering.

Rilevamento del debugger:

Tecnica di temporizzazione dell'esecuzione del codice:

Quando si utilizza un debugger per analizzare un eseguibile, a volte utilizziamo un'esecuzione a passo singolo per eseguire alcune istruzioni di assemblaggio, il tempo di esecuzione sarà molto più lungo della normale esecuzione, prendiamo questo codice come esempio:

All'inizio del codice abbiamo una chiamata alla funzione “ GetTickCount ” che restituisce il numero di millisecondi trascorsi dall'avvio del sistema. Il codice fino all'esecuzione della funzione " ShellExecuteW " impiegherà da 30 a 47 millisecondi come ho misurato sulla mia macchina. Successivamente chiamiamo nuovamente la funzione " GetTickCount " per ottenere l'ora e quindi ottenere la differenza tra i valori delle due chiamate e, se è più lungo di 70 millisecondi, uscire dal processo, altrimenti stampare il messaggio.

Esistono altre API di Windows che possono essere utilizzate per ottenere tempo come:

  • OttieniOraLocale().
  • GetOraSistema().
  • QueryPerformanceCounter().

I punti di interruzione del software sono una tecnica anti-debug comune utilizzata da attori malintenzionati per rendere più difficile il reverse engineering dei loro malware. Questa tecnica prevede l'inserimento di un'istruzione di codice specifica, nota come punto di interruzione, nel programma in una posizione specifica. Quando il programma viene eseguito, il punto di interruzione causerà l'interruzione dell'esecuzione del programma, rendendo difficile per un debugger analizzare il comportamento del programma.

Un modo per implementare un punto di interruzione utilizzando il linguaggio assembly consiste nell'utilizzare l' int 3istruzione. Questa istruzione è un interrupt software che provoca l'interruzione dell'esecuzione del programma e il trasferimento del controllo al debugger. Ecco un esempio di come utilizzare l' int 3istruzione in C++:

Punti di interruzione hardware:

I punti di interruzione hardware sono un tipo di tecnica anti-debug che utilizza funzionalità hardware specializzate della CPU per rilevare e impedire il debug di un programma. Questa tecnica prevede l'impostazione di un punto di interruzione su uno specifico indirizzo o registro di memoria e quindi l'istruzione alla CPU di attivare un interrupt ogni volta che il programma accede o modifica l'indirizzo o il registro specificato.

Di seguito è riportato un esempio di come verificare se è impostato un punto di interruzione hardware:

"Controllo del punto di interruzione hardware"

Un valore diverso da zero in uno qualsiasi dei registri di debug potrebbe suggerire che il processo viene eseguito in un debugger con un punto di interruzione hardware impostato.

Auto-debug:

È una tecnica utilizzata dagli autori di malware per impedire a un debugger di collegarsi al processo o per verificare se il processo si trova sotto un debugger. Implica l'utilizzo di un debugger per eseguire il debug del programma stesso, al fine di rilevare e impedire che altri debugger si colleghino al programma.

Di seguito è riportato un esempio di un'istanza che crea una seconda istanza del processo e crea un evento denominato con il nome "debugger_present". La seconda istanza del processo proverà ad associare un debugger al processo padre e, se fallisce, imposterà l'evento che indicherà al processo padre che ad esso è collegato un altro debugger:

Processo genitore
Processo figlio

UnhandledExceptionFilter()

Se un programma incontra un'eccezione che non è gestita da alcun gestore di eccezioni registrato, verrà chiamata la funzione kernel32!UnhandledExceptionFilter(). È possibile registrare un filtro per le eccezioni non gestite personalizzato utilizzando kernel32!SetUnhandledExceptionFilter(). Tuttavia, se è in corso il debug del programma, il filtro personalizzato non verrà chiamato e l'eccezione verrà invece passata al debugger. Pertanto, se il controllo viene passato al filtro delle eccezioni non gestite, si può dedurre che il programma non è in esecuzione in un debugger:

grazie per aver dedicato del tempo a leggere questo fino alla prossima volta.

Da Infosec Writeups: Ogni giorno nell'Infosec emergono molte cose di cui è difficile tenere il passo. Iscriviti alla nostra newsletter settimanale per ricevere tutte le ultime tendenze Infosec sotto forma di 5 articoli, 4 thread, 3 video, 2 repository e strumenti GitHub e 1 avviso di lavoro GRATIS!