Hai mai sentito il desiderio di smontare qualche meccanismo per scoprire come funziona? Beh, chi non l’ha fatto? Questo desiderio è la forza trainante del reverse engineering. Questa abilità è utile per analizzare la sicurezza del prodotto, scoprire lo scopo di un file .exe sospetto senza eseguirlo, recuperare la documentazione perduta, sviluppare una nuova soluzione basata su software legacy, ecc.
In questo articolo, discutiamo la base di conoscenza necessaria per eseguire il reverse engineering, i principi di base del reverse engineering di un pezzo di software Windows, i disassemblatori e gli strumenti. Forniamo anche un esempio passo dopo passo di reverse engineering di un’applicazione.
Scritto da
Sergii Bratus,
Coordinatore dello sviluppo,
Squadra sicurezza della rete
e
Anton Kukoba,
Security Research Leader
Contenuti
Che cos’è il software reversing?
Di cosa abbiamo bisogno per il reverse engineering?
Conoscenza teorica. Processo di Reverse Engineering del Software
Strumenti utili per il Reverse Engineering del Software Windows
Disassemblatori
Windows Sysinternals
Strumenti di monitoraggio della rete
Debugger
Esempio realeesempio di reverse engineering del software
Come fare il reverse engineering di un driver
Conclusione
- Cos’è il reverse engineering del software?
- Di cosa abbiamo bisogno per il reverse engineering?
- Conoscenza teorica. Processo di ingegneria inversa del software
- Strumenti utili per il reverse engineering del software Windows
- Disassemblatori
- Windows Sysinternals
- Strumenti di monitoraggio della rete
- Debugger
- Esempio di reverse engineering del software nella vita reale
- Come fare reverse engineering di un driver
- Conclusione
Cos’è il reverse engineering del software?
L’ingegneria inversa è il processo di scoprire i principi dietro un pezzo di hardware o software, come la sua architettura e struttura interna. La domanda che guida il reverse engineering è Come funziona?
Ovviamente, se si dispone di documentazione, l’intero processo diventa molto più semplice. Ma spesso succede che non c’è documentazione e bisogna trovare un altro modo per imparare come funziona un pezzo di software.
Quando potreste aver bisogno di fare reverse engineering di un pezzo di software e come potrebbe aiutarvi?
Ci sono molti usi del reverse engineering nel campo dell’informatica, tra cui:
- Ricerca di protocolli di comunicazione di rete
- Ricerca di algoritmi utilizzati in malware come virus informatici, trojan, ransomware, ecc.
- Ricercare il formato di file usato per memorizzare qualsiasi tipo di informazione, per esempio database di email e immagini disco
- Verificare la capacità del proprio software di resistere al reverse engineering
- Migliorare la compatibilità del software con piattaforme e software di terze parti
- Utilizzare caratteristiche non documentate della piattaforma
La legalità del reverse engineering dipende dal suo scopo e da come verrà usato il software. Tutti gli scopi menzionati sopra sono completamente legittimi, assumendo che abbiate ottenuto una copia del software legalmente. Ma se intendete, per esempio, fare il reverse engineering di una certa caratteristica di un’applicazione chiusa e poi implementarla in un’altra applicazione, probabilmente avrete dei problemi.
Per quanto riguarda la documentazione legale, il reverse engineering è spesso proibito dagli accordi di licenza con l’utente finale (EULA). Ma il Digital Millennium Copyright Act degli Stati Uniti specifica che l’inversione di un pezzo di software è legale se è fatta per migliorare la compatibilità con altri prodotti.
I requisiti legali variano da paese a paese, quindi prendetevi il vostro tempo per fare ricerche prima di iniziare.
Ora vediamo come fare reverse engineering del software.
Di cosa abbiamo bisogno per il reverse engineering?
Per iniziare il reverse engineering del software, hai bisogno di:
- conoscenze nel campo in cui vuoi applicare il reverse engineering
- strumenti che ti permetteranno di applicare le tue conoscenze mentre cerchi di smontare il software.
Consideriamo un esempio generico che non è collegato al software. Diciamo che avete un orologio e volete scoprire se è meccanico, al quarzo o automatico.
Avere conoscenze nel campo significa che dovreste sapere che ci sono tre tipi di orologi. Inoltre, dovresti sapere che se c’è una batteria, si trova all’interno dell’orologio, e puoi vederla se lo apri. Dovresti anche avere una conoscenza di base della struttura interna di un orologio, dell’aspetto della batteria e degli strumenti necessari per aprire la cassa di un orologio. Avere gli strumenti per applicare le tue conoscenze significa che devi avere un cacciavite o un altro strumento dedicato che ti darà la possibilità di aprire l’orologio.
Proprio come l’ingegneria inversa di un orologio richiede un set di abilità e strumenti specifici, l’ingegneria inversa del software richiede le proprie conoscenze e strumenti specifici del settore.
Conoscenza teorica. Processo di ingegneria inversa del software
Per diversi compiti di ingegneria inversa del software, hai bisogno di diversi tipi di conoscenza. Naturalmente, c’è una conoscenza comune che vi aiuterà nella maggior parte dei compiti di reverse engineering: la conoscenza delle strutture applicative comuni, dei linguaggi di programmazione, dei compilatori e così via. Tuttavia, senza una speciale conoscenza teorica, non puoi risolvere specifici compiti di reverse engineering.
Se tu… |
Ti serve la conoscenza di… |
reverse engineer di qualsiasi applicazione di rete |
principi di comunicazione interprocesso, la struttura delle reti, connessioni, pacchetti di rete, ecc. |
invertire algoritmi crittografici |
la crittografia e gli algoritmi più popolari usati nel campo |
ricercare file strutture dei file |
concetti di base sui file e come diversi sistemi o componenti lavorano con i file |
Tecniche speciali possono risparmiare molto tempo durante l’inversione di particolari tipi di software. Nel caso delle interazioni tra file, fare un test che scrive valori di tipo unico in un file mentre registra gli offset e la dimensione dei dati nel file di archiviazione effettivo può aiutarvi a trovare modelli comuni negli offset. Questo vi darà un suggerimento sulle strutture interne di questi file.
Quando iniziano un processo di reverse engineering, gli sviluppatori di software generalmente usano un disassemblatore per trovare algoritmi e logica di programma sul posto. Ci sono molti diversi formati di file eseguibili, compilatori (che danno diversi output) e sistemi operativi. Questa diversità di tecnologie preclude l’uso di una singola tecnologia per invertire tutti i tipi di software.
Per capire il codice decompilato, è necessaria una certa conoscenza del linguaggio assembler, delle convenzioni di chiamata delle funzioni, della struttura dello stack, del concetto di stack frame, ecc.
Conoscere l’output dell’assembler per diversi campioni di codice può aiutare a scoprire la funzionalità originale. Consideriamo alcuni esempi per la piattaforma Windows x86.
Diciamo di avere il seguente codice:
Se compiliamo questo codice in un file eseguibile, vedremo questo nel disassemblatore:
Come possiamo vedere, il ciclo regolare è diventato codice assembly con confronti e salti. Notate che il codice assembly non usa il regolare ciclo assembly con il contatore nel registro ecx. Inoltre, le variabili locali qui sono indicate come e di conseguenza.
Vediamo cosa succede se compiliamo questo codice usando la build di rilascio:
Questo pezzo di codice non assomiglia affatto al precedente. Questo è dovuto a come il codice è stato ottimizzato. Tecnicamente, il ciclo è stato rimosso, dal momento che non sta facendo nulla di utile se non incrementare la variabile count a 10. Così l’ottimizzatore ha deciso solo di mantenere il valore finale della variabile count e mettere il valore direttamente come argomento per l’operatore di output count.
I compilatori che usiamo oggi sono molto bravi a ottimizzare il codice. Ecco perché quando si fa reverse engineering, è meglio capire l’idea dietro il codice (i principi del codice) piuttosto che cercare di ottenere il codice originale stesso. Se capite l’idea dietro il codice, potete semplicemente scrivere il vostro prototipo che si adatta al compito originale.
Sarà molto utile sapere quale codice assembly otterrete se compilate diversi operatori, strutture e altre costruzioni del linguaggio. Capire il codice assembly risultante è un buon modo per iniziare il processo di reverse engineering del C++, ma non entreremo nei dettagli tecnici di questo qui.
Strumenti utili per il reverse engineering del software Windows
Abbiamo già descritto diversi strumenti di reverse engineering, inclusi ProcessMonitor e ProcessExplorer, nella nostra ricerca sull’architettura delle applicazioni. Questi strumenti sono assolutamente indispensabili per il reverse engineering.
In questa sezione, esamineremo i disassemblatori più popolari e alcuni altri strumenti che usiamo per i nostri progetti di reverse engineering.
Puoi avere maggiori dettagli ed esempi di utilizzo nel nostro articolo sui migliori strumenti di reverse engineering del software.
Disassemblatori
Un disassemblatore è un programma che traduce un file eseguibile in linguaggio assembly. Il più popolare è IDA Pro
IDA Pro
IDA Pro
IDA Pro è uno strumento comodo e potente per disassemblare. Ha un numero enorme di strumenti che permettono di disassemblare rapidamente un pezzo di software. Può mostrare l’albero delle chiamate di funzione, analizzare l’importazione e l’esportazione dell’eseguibile e mostrare informazioni su di esse. Può anche mostrare il codice in C. Inoltre, supporta più architetture di CPU, quindi è possibile utilizzare IDA Pro per il reverse engineering del codice per ARM, AVR, M68k, e molte altre architetture.
Radare
Radare
Il disassemblatore Radare è un’alternativa a IDA. Fondamentalmente ha tutte le caratteristiche di IDA senza essere altrettanto robusto e stabile. Ma è gratuito e open source. Radare stesso è uno strumento da console, ma ha un frontend Cutter, che lo rende una vera alternativa a IDA.
Windows Sysinternals
Le utilità Windows Sysinternals sono generalmente utilizzate per la gestione, la diagnostica, la risoluzione dei problemi e il monitoraggio dell’ambiente Microsoft Windows. Ma sono anche adatti per il reverse engineering del software Windows.
TCPView è uno sniffer di rete che mostra tutte le informazioni sui pacchetti TCP/UDP da tutti i processi. Questo strumento è utile per invertire i protocolli di rete.
PortMon è un monitor di porte fisiche del sistema. Monitora le porte seriali e parallele e tutto il traffico che le attraversa.
WinObj mostra tutti gli oggetti globali del sistema in una struttura gerarchica. Questo strumento può essere utile quando si inverte un’applicazione che lavora con primitive di sincronizzazione come mutex e semafori e anche quando si inverte l’ingegneria dei driver in modalità kernel.
Strumenti di monitoraggio della rete
Wireshark
Wireshark
Wireshark è uno dei più potenti sniffer di rete. Non solo permette di catturare il traffico di rete, ma contiene anche parser per vari protocolli di rete, a partire da quelli di basso livello come Ethernet, TCP e IP fino ai protocolli specifici delle applicazioni come WebSockets e XMPP.
Fiddler
Fiddler
Fiddler è un proxy web che registra il traffico dai browser e permette di analizzare le richieste HTTP/HTTPS. A differenza di Wireshark, mostra sessioni HTTP invece di pacchetti di rete separati. Fiddler permette anche di analizzare i dati compressi inviati su HTTP e analizzare i dati JSON e XML durante il monitoraggio delle richieste SOAP, REST e AJAX.
API Monitor
API Monitor
API Monitor è uno strumento utile per scoprire quali API sono chiamate da un’applicazione e quale comportamento l’applicazione si aspetta da queste API. Questo strumento ha un potente database e permette di vedere le chiamate a un numero enorme di funzioni API non solo di kernel32 e ntdll ma anche di COM, ambiente gestito e altri. Inoltre, API Monitor fornisce comodi meccanismi di filtraggio.
Debugger
Un debugger è inestimabile per qualsiasi sviluppatore per vedere cosa sta facendo un programma in questo momento. Si ottiene lo stesso beneficio dal debug quando si inverte l’applicazione come si ottiene dal debug delle applicazioni live.
I debugger più popolari sono OllyDbg, WinDbg e Windbg Preview.
OllyDbg
OllyDBG
OllyDbg (e il suo successore x64dbg) è probabilmente il miglior debugger per quanto riguarda il reverse engineering del software. È stato sviluppato specificamente per le necessità del reverse, e ha tutti gli strumenti necessari a tale scopo:
- un disassemblatore incorporato con la capacità di analizzare e identificare le strutture dati chiave
- una funzione di analisi di importazione ed esportazione
- un motore incorporato di assemblaggio e patch
La capacità di analizzare le funzioni API e i loro parametri rende facile l’inversione delle interazioni con un sistema. La vista dello stack fornisce molte informazioni sullo stack delle chiamate. Un altro importante vantaggio è che puoi usare OllyDbg con applicazioni protette dal debug, quando i normali debugger non possono fare nulla.
WinDbg
Windbg
Nonostante la sua semplice interfaccia, WinDbg ha potenti strumenti per il debug. Ha un disassemblatore incorporato, vari comandi che ti permettono di sapere quasi tutto sul processo/sistema che stai debuggando, e la capacità di fare debugging in modalità kernel, che è probabilmente la caratteristica più preziosa. È un grande vantaggio per l’inversione dei driver, in particolare quelli in kernel-mode.
Windbg Preview
Windbg Preview
Windbg Preview è una nuova versione di Windbg sviluppato da Microsoft. È distribuita solo tramite il Windows Store. Ha tutte le caratteristiche del classico Windbg accoppiate con una nuova UI e diverse nuove caratteristiche. Una di queste nuove caratteristiche è il Time Travel Debugging, che permette di registrare un certo periodo di esecuzione del programma e poi riprodurlo tutte le volte di cui avete bisogno. In questo modo, è possibile eseguire le parti interessanti del codice per gradi, senza aver paura di eseguire qualche codice accidentalmente e perdere il contesto o tutti i dati.
Leggi anche:
9 Migliori Strumenti di Reverse Engineering per il 2018
Esempio di reverse engineering del software nella vita reale
Ora vedremo un esempio di come fare reverse engineering di un pezzo di software. Immaginiamo di avere un file eseguibile sospetto. Avete bisogno di scoprire cosa fa questo programma e se è sicuro per gli utenti.
Considerando lo scenario, è una buona idea non eseguire questo eseguibile sul vostro computer di lavoro ma usare invece una macchina virtuale. Avviamo l’applicazione nella nostra macchina virtuale.
Processo crea un servizio
Come possiamo vedere, questo file crea un servizio Windows chiamato TestDriver. Ha il tipo kernel, quindi sappiamo che è un driver. Ma da dove prende il file del driver per funzionare? Possiamo usare ProcessMonitor di Sysinternals Suite per scoprirlo. Quando apriamo ProcessMonitor, possiamo impostare dei filtri per mostrarci solo l’attività dei file del processo che ci interessa. Il suo log delle attività assomiglia a questo:
FileMon information
Il file del driver è creato dal processo che stiamo invertendo, e questo processo mette questo file nella directory temp dell’utente. Non c’è bisogno di cercare il file nella cartella temp poiché vediamo che il processo lo cancella subito dopo l’uso. Quindi cosa fa il processo con questo file? Se decomprime il file, possiamo provare a trovarlo nella sezione risorse del processo, dato che questo è un posto comune per memorizzare tali dati. Cerchiamo lì. Useremo un altro strumento – Resource Hacker – per esaminare le risorse. Eseguiamolo:
Esamina le risorse con Resource Hacker
Bingo! Come possiamo vedere dal contenuto della risorsa trovata, questo è probabilmente il file eseguibile di Windows, poiché inizia con una firma MZ e ha la stringa “Questo programma non può essere eseguito in modalità DOS”. Verifichiamo se si tratta del nostro file di driver. A tal fine, estraiamo la risorsa utilizzando Resource Hacker e apriamola nel disassemblatore.
Schermo del disassemblatore
Come sappiamo, DriverEntry è il punto di ingresso dei driver in modalità kernel nei sistemi Windows. Possiamo continuare la nostra ricerca, dato che sembra che abbiamo trovato il driver giusto.
Come fare reverse engineering di un driver
Per iniziare il reverse engineering del driver, esaminiamo le funzioni che sono chiamate da DriverEntry una per una. Se andiamo a sub_14005, non troviamo nulla di interessante, quindi continuiamo con sub_110F0 e troviamo questo codice:
Codice pezzo 1
Codice pezzo 2
Codice pezzo 3
Codice pezzo 4
Qualche riga è omessa qui per semplicità.
Nel primo elenco, viene creata una stringa unicode, e questa stringa punta al percorso C:\hello.txt. Dopo di che, la struttura OBJECT_ATTRIBUTES viene riempita con valori regolari; sappiamo che questa struttura è spesso necessaria quando si chiamano funzioni come ZwCreateFile.
Nel secondo elenco, vediamo che ZwCreateFile viene effettivamente chiamato, il che ci rende abbastanza sicuri che il driver crea il file – e sappiamo dove si trova questo file dopo la sua creazione.
Dal terzo e quarto listato, possiamo vedere che il driver prende la stringa unicode e la scrive nel buffer (questo avviene nella funzione sub_11150), e il buffer sarà scritto nel file usando la funzione ZwWriteFile. Alla fine, il driver chiude il file usando l’API ZwClose.
Riassumiamo. Abbiamo scoperto che il programma originale estrae il file del driver dalle sue risorse, lo mette nella cartella temporanea dell’utente corrente, crea il servizio Windows per questo driver e lo esegue. Dopo di che, il programma si ferma e cancella il servizio e il file originale del driver dalla cartella temporanea. Da questo comportamento e dall’analisi del disassemblaggio, sembra che il driver non faccia nulla se non creare un file sull’unità C chiamato hello.txt e scrivere la stringa “Hello from driver”.
Ora dobbiamo controllare se abbiamo ragione. Eseguiamo il programma e controlliamo l’unità C:
Schermo dell’applicazione
Meraviglioso! Abbiamo fatto il reverse engineering di questo semplice programma e ora sappiamo che è sicuro da usare.
Abbiamo potuto ottenere questo risultato in molti modi diversi – usando il debug o l’API Mon, scrivendo test, ecc. Puoi trovare i tuoi modi di fare reverse engineering del software che funzionano per te.
Conclusione
Il reverse engineering del software Windows richiede un solido background educativo ed esperienza di programmazione. Al fine di eseguire il reverse engineering, è necessario combinare le competenze in disassemblaggio, monitoraggio della rete, debug, integrazione API, diversi linguaggi di programma, compilatori, ecc. Devi anche essere molto attento quando fai il reverse engineering del software per non infrangere le leggi sul copyright o danneggiare il sistema.
Apriorit, abbiamo un team esperto di reverse engineer. Se vuoi applicare le competenze di reverse engineering al tuo progetto, non esitare a contattarci!