
Storico del firmware solo binario che impara a localizzare funzioni in binari grezzi estraendo funzioni note da binari simili, consentendo un rapido abbinamento di funzioni senza disassemblaggio per l'analisi del firmware embedded.
Polypyus impara a localizzare funzioni in binari grezzi estraendo funzioni note da binari simili. Pertanto, è uno storico del firmware. Polypyus funziona senza disassemblare questi binari, il che è un vantaggio per binari complessi da disassemblare e dove gli strumenti comuni perdono funzioni. Inoltre, l'approccio solo binario lo rende molto veloce e funziona in pochi secondi. Tuttavia, questo approccio richiede che i binari siano per la stessa architettura e abbiano opzioni del compilatore simili.
Polypyus si integra nel flusso di lavoro di strumenti esistenti come Ghidra, IDA, BinDiff e Diaphora. Ad esempio, può importare funzioni precedentemente annotate e imparare da esse, e anche esportare funzioni trovate per essere importate in IDA. Poiché Polypyus usa soglie piuttosto rigorose, nei nostri esperimenti ha trovato solo corrispondenze corrette. Sebbene ciò porti a meno risultati rispetto agli strumenti esistenti, è un buon punto di partenza per caricare queste corrispondenze in IDA per migliorare i suoi risultati di analisi automatica e poi eseguire BinDiff sopra.
Quando si lavora con binari di firmware grezzi, in particolare varie versioni del firmware Bluetooth Broadcom e Cypress, abbiamo scoperto che l'analisi automatica di IDA spesso identificava gli inizi di funzione in modo errato. In IDA Pro 6.8 l'analisi automatica è un po' più aggressiva, portando a più risultati ma anche a più falsi positivi. In generale, IDA Pro 7.2 era più pessimista, ma ha perso molte funzioni. Questo ha portato a solo poche corrispondenze BinDiff tra i nostri firmware in IDA Pro 6.8 e nessuna corrispondenza utile in IDA Pro 7.2.
È interessante notare che BinDiff spesso non riusciva a identificare funzioni che, a parte i rami, erano identiche byte per byte. Nota che Polypyus cerca esattamente queste funzioni identiche byte per byte. Supponiamo che BinDiff fallisca su queste funzioni a causa di un grafo delle chiamate diverso prodotto da funzioni mancanti e falsi positivi. A volte, queste funzioni erano già riconosciute da IDA, ma spesso IDA non le riconosceva come codice o non le marcava come funzione. Nota che Diaphora ha problemi simili, poiché esporta funzioni identificate da IDA prima di elaborarle ulteriormente. Il seguente mostra un benchmark sul binario del firmware Bluetooth CYW20735B1 che confronta vari disassemblatori e come i fallimenti del disassemblatore portino a problemi di diffing successivi.
Inoltre, mentre abbiamo scoperto che Amnesia trova molte funzioni, trova anche molti falsi positivi. Tuttavia, molte funzioni hanno una configurazione dello stack frame simile all'inizio. Pertanto, Polypyus ha un'opzione per apprendere gli inizi di funzione comuni dai binari di input annotati e applicarla ad altri binari per identificare funzioni senza abbinare il loro nome. Questo passaggio opzionale viene applicato solo alle regioni in cui non sono state precedentemente individuate funzioni, in questo modo il metodo degli inizi di funzione comuni e la ricerca della funzione principale non entrano in conflitto.
Poiché questi matcher lavorano sul binario grezzo, non dipendono da un disassemblatore. Questo ha anche uno svantaggio importante: se ci fossero opzioni del compilatore diverse o un'architettura target diversa, Polypyus non rileverà funzioni simili. Inoltre, mentre le corrispondenze identificate sono molto affidabili, l'identificazione dell'inizio della funzione è un po' meno affidabile, quindi usa quest'ultima con cautela. Nel seguente, puoi vedere che i kit di valutazione Cypress sono molto simili tra loro, ma il firmware del MacBook è molto diverso.
Polypyus crea matcher binari fuzzy confrontando funzioni comuni in una raccolta di binari di firmware annotati.
Attualmente, sono supportate le seguenti annotazioni:
patch.elf, che è un file ELF speciale contenente solo definizioni di simboli..symdefs come prodotto dalla maggior parte dei compilatori ARM..csv con un formato documentato nella cartella firmware.Queste annotazioni contengono l'indirizzo, la dimensione e il nome delle funzioni note. Più somiglianze hanno i binari di input nella raccolta storica, meglio è per le prestazioni e i risultati di Polypyus. Date diverse funzioni leggermente differenti, Polypyus crea matcher molto buoni.
Polypyus richiede Python 3 >= 3.6. Consigliamo l'uso di un virtualenv per la seguente installazione. Clona questo repository e in questa cartella esegui:
pip install .
Dopo l'installazione sono disponibili i seguenti comandi:
polypyus-guipolypyus-cliPolypyus è disponibile tramite un'interfaccia grafica e una a riga di comando.
Sia la GUI polypyus-gui che la CLI polypyus-cli accettano questi argomenti durante l'invocazione:
--verbose is the verbosity level. By default, it shows warnings -v shows info -vv show debug information.
--project sets the location of the project file. This is either a file path or ":memory:".
--help Show help message.
L'opzione project ti permette di salvare il tuo lavoro per diversi contesti in file diversi e anche di riaprirli.
Il flusso di lavoro generale della GUI va dal lato sinistro della finestra a destra.
Prima, i binari vengono aggiunti alla cronologia. Poi, seguono le annotazioni dei simboli per le voci
nella cronologia.
Successivamente, è possibile aggiungere binari target.
Per l'abbinamento, premi Create matchers from history. Una volta creati i matcher, è possibile selezionare
singoli target, o abbinare tutti i target selezionando batch match.
Infine, i risultati possono essere esportati in un file .csv.
Nel seguente puoi vedere un video demo in cui Polypyus impiega solo pochi secondi per apprendere da due binari di input, annotarli, creare matcher e applicare le corrispondenze a un nuovo binario.
Il vantaggio di usare la CLI è la sua capacità di essere automatizzata. Al momento, il formato di output della CLI è soggetto a modifiche. Tuttavia, ecco un esempio di chiamata:
polypyus-cli --history firmware/history/20819-A1.bin --annotation firmware/history/20819-A1_patch.elf --history firmware/history/20735B1.bin --annotation firmware/history/20735B1_patch.elf --project test.sqlite
polypyus-cli --target firmware/history/20739B1.bin --project test.sqlite
Il primo comando crea test.sqlite come nuovo file di progetto e importa 20819-A1.bin e 20735B1.bin
con i rispettivi file patch.elf.
La seconda invocazione riutilizza lo stesso file di progetto e abbina al binario 20739B1.bin.
Per ogni comando, il numero di --history e --annotation deve corrispondere.
Questi due comandi potrebbero anche essere combinati in uno aggiungendo l'argomento --target al primo comando.
Un articolo che spiega gli interni è stato pubblicato al Workshop on Binary Analysis Research (BAR) 2021 con il titolo Polypyus - The Firmware Historian. Ulteriori dettagli sono contenuti anche nella presentazione finale della tesi magistrale di Jan, che copre i problemi incontrati lavorando con approcci convenzionali di binary diffing in modalità ARM Thumb2, e come funziona l'approccio alternativo solo binario.
I simboli trapelati nei formati patch.elf o .symdefs contengono solo nomi di funzioni e
variabili globali. Tuttavia, ci sono anche un paio di file di progetto Eclipse .pdom
in WICED Studio 6.2 e 6.4. Questi contengono informazioni aggiuntive sui tipi. Eclipse li usa
internamente per l'autocompletamento, la ricerca di funzioni, ecc., e possiamo utilizzarli al contrario
per aggiungere informazioni sui tipi. Poiché i file .pdom contengono solo informazioni parziali e memorizzate nella cache, può
essere utile combinarne più di uno.
In un primo passaggio, esportiamo le informazioni sui tipi .pdom in un database SQLite. L'esportazione
richiede un po' di tempo, ma può anche essere interrotta e ripresa in seguito. L'esportazione funziona come segue:
java -jar pdom/export/export.jar -P BCM20739-B0.1462220149391.pdom
L'importazione PDOM cerca i nomi delle funzioni in un database IDA, li cerca nel PDOM per trovare
informazioni sui tipi, e quindi applica tali informazioni sui tipi nel database IDA. Pertanto, il database IDA
deve contenere nomi di funzione corretti in anticipo. In linea di principio, questi possono essere creati con
gli script import_export di Polypyus. Tuttavia, gli script un po' più avanzati
che supportano l'importazione PDOM possono anche gestire le sezioni patch.elf. Esegui l'importatore come segue:
T=0x1 (Alt-g).patch.elf (Select file).20739mapb0.h per nominare i registri hardware (Import map.h).Questo script è stato testato su IDA Pro 7.4 e 7.5.
Dopo alcuni test interni, possiamo raccomandare il seguente flusso di lavoro quando si lavora con IDA Pro e Polypyus:
Alt-g, T=0x1).0x0 con rx, RAM a 0x200000 con rwx (almeno per il firmware Bluetooth).0x4 (o).
Sul firmware CYW20735 punta a 0x3bc+1. Torna indietro di un byte e crea una funzione (p)....ora il tuo database IDA potrebbe essere in qualche modo utile :) Ancora molte cose in cui il disassemblatore fallisce in ARM Thumb2, ma molto meglio di qualsiasi cosa IDA faccia da solo.
La cartella firmware contiene vari firmware con e senza simboli.
Tutto nella history contiene simboli, tutto in targets è senza simboli.
Per la serie Samsung, S8 include anche Note 8 e S8+ ecc., e S10/S20 include anche tutto da S10e fino a Note 20 5G.
La qualità del dump può variare, alcuni hanno RAM e altri sono solo ROM. Abbiamo accesso alla maggior parte dei dispositivi in questa lista. Se hai bisogno di un dump con i livelli di patch più recenti e inclusa la RAM, sentiti libero di contattarci.
Alcuni dispositivi menzionati nell'articolo non sono inclusi qui, poiché potrebbero non essere dispositivi solo per ricerca ecc. Mancano anche alcuni iPhone e MacBook, poiché li abbiamo come dispositivi solo per ricerca ma il dump originale non lo era. Questi dispositivi verranno aggiunti presto :)
C'è un file .editorconfig in questo repository. Configura lo stile di indentazione, charset e separatori di riga. Segui questa configurazione quando contribuisci, il che può essere facilitato se usi un plugin IDE per .editorconfig.
Per installare le dipendenze di test esegui
pip install '.[test]'
questo installerà pacchetti necessari solo per l'esecuzione dei test case.
Le dipendenze di sviluppo forniscono, ad esempio, stub per i tipi di pacchetto. Per installarle esegui
pip install '.[development]'
pytest eseguirà tutti i test.
Il progetto usa tox per eseguire localmente i test contro diverse versioni di Python. Tox è configurato per testare le versioni 3.6, 3.7, 3.8 e 3.9 Per eseguire tox, installa le dipendenze di test e installa queste 4 versioni di Python menzionate. Il nostro modo consigliato per installare e gestire più versioni di Python è pyenv.
Passi:
pyenv install 3.9.1
pyenv install 3.8.6
pyenv install 3.7.9
pyenv install 3.6.12
pyenv virtualenv 3.9.1 polypyus
penv local polypyus 3.8.6 3.7.9 3.6.12
pip install '.[test]'
pip install '.[development]'
toxPolypyus usa GitHub Actions per esecuzioni automatiche di test e alcuni linting. Se vuoi, puoi eseguire i passaggi di linting localmente con i git hook pre-commit.
Ogni volta prima che venga creato un nuovo commit, questo attiverà il linting e mostrerà i problemi che impedirebbero a questo codice di superare il passaggio di linting di GitHub Actions. Formatterà anche i file modificati con black .
pip install '.[development]'
pre-commit install
Ringraziamo Anna Stichling per aver creato il logo Polypyus. Ringraziamo anche Christian Blichmann e Joxean Koret per i loro feedback.
Polypyus è open-source e concesso in licenza sotto GPLv3.
| Chip | Dispositivo | Data di build | Simboli |
|---|
| BCM20703A2 | MacBook/iMac 2016-2017 | Oct 22 2015 | ✔ |
| CYW20719B1 | Scheda di valutazione | Jan 17 2017 | ✔ |
| CYW20735B1 | Scheda di valutazione | Jan 18 2018 | ✔ |
| CYW20819A1 | Scheda di valutazione | May 22 2018 | ✔ |
| Chip | Dispositivo | Data di build | Simboli |
|---|
| BCM2046A2 | iMac Late 2009 | 2007? | - |
| BCM2070B0 | MacBook 2011, Thinkpad T420 | Jul 9 2008 | - |
| BCM20702A1 | Asus USB Dongle | Feb (?) 2010 | - |
| BCM4345B0 | iPhone 6 | Jul 15 2013 | - |
| BCM4335C0 | Google Nexus 5 | Dec 11 2012 | - |
| BCM4345B0 | Google Nexus 6P / Galaxy S6 | Oct 23 2014 | - |
| BCM43430A1 | Raspberry Pi 3 e Zero W | Jun 2 2014 | - |
| BCM4345C0 | Raspberry Pi 3+ e 4 | Aug 19 2014 | - |
| BCM4347B0 | Serie Samsung Galaxy S8 | Jun 3 2016 | - |
| BCM4375B1 | Serie Samsung Galaxy S10/20 | Apr 13 2018 | - |
| BCM4378B1 | iPhone 11/SE2 | Oct 25 2018 | Stringhe |