
Ricostruire un protocollo USB morto: i segreti di un palmare svelati da un coltello caldo, un viaggio multidisciplinare per far rivivere un'interfaccia USB dimenticata
Nel 2024, bjiru ha caricato un video sul dispositivo portatile ME2, un giocattolo prodotto intorno al 2008 che offriva la possibilità di utilizzare l'USB per sincronizzare punti e gemme tra il tuo dispositivo e un mondo online. Il gioco era estremamente di nicchia, quindi nessun software, driver o risorsa era stato archiviato, almeno finché bjiru non si è fatto avanti con il client del gioco online.
Sono il leader di Miuchiz Reborn, uno sforzo iniziato nel 2015 per preservare, fare reverse engineering, emulare e mantenere l'accessibilità di un gioco simile a questo, con una parte online e una parte portatile collegate tramite USB. A causa della simile epoca e tipo di gioco, il ME2 era già stato portato alla mia attenzione dalla comunità di Miuchiz nel 2018, poiché pensavano (erroneamente) che potessero condividere somiglianze architetturali. Nonostante fossi a conoscenza dell'esistenza del dispositivo da anni, il video di bjiru mi ha finalmente spinto a iniziare la ricerca su di esso.
I miei sforzi iniziali furono spesi esclusivamente per ricreare il server necessario per rendere di nuovo funzionante la copia del gioco per computer di bjiru, ma lungo il percorso, la mia attenzione è inevitabilmente scivolata verso il portatile. Una ricreazione del gioco online non potrebbe mai essere completa senza il meccanismo per sincronizzare i tuoi punti da e verso il dispositivo. Questa comunicazione tra il tuo computer e il dispositivo ME2 era la principale caratteristica del gioco, dopotutto. Immaginavo che la mia esperienza precedente con i dispositivi portatili Miuchiz mi avrebbe aiutato a districare velocemente qualsiasi rituale di comunicazione si aspettassero... a patto di riuscire a ottenere del codice da reverse engineering.
La mia curiosità richiedeva il sacrificio di ME2. eBay richiedeva il sacrificio di denaro. Ben presto, questi esemplari giacevano davanti a me.

Sono unità piccole con solo un paio di pulsanti e una porta mini-USB femmina. Nella scatola è incluso un cavo, ma manca qualsiasi disco per software e driver. Quella porta USB sarebbe stata il modo per sincronizzare i punti tra il computer e il portatile, ma quando ho intrapreso lo stesso viaggio per il dispositivo portatile Miuchiz, ho ottenuto pieno accesso alla sua memoria flash facendo reverse engineering del funzionamento del software Windows associato. Senza tale software per il ME2, non c'è nulla da reverse engineering per capire come comunicare con il dispositivo. Anche dopo aver controllato la Wayback Machine e bjiru, a quanto pare non c'erano copie sopravvissute del software utilizzato per parlare con questi oggetti. Penso si chiamasse ME2 Desktop Buddy, ma quell'applicazione era separata dal client di gioco recuperato da bjiru. Il portatile si presenta come un dispositivo di archiviazione rimovibile, ma i contenuti ti indirizzano online per scaricare il gioco ME2, che non è più disponibile.
La strada da percorrere è chiara, poiché rimane solo un'opzione: aprire l'hardware.

Il firmware principale del ME2 è memorizzato su un SST39VF3201, un chip flash da 2 megaparole (4 megabyte, con unità indirizzabili a 16 bit). Il microcontrollore principale è... sotto un duro glob-top di epossidica. Questa è nota come chip-on-board (CoB) e di solito è una misura di risparmio sui costi, ma ha l'effetto collaterale di nascondere qualsiasi informazione identificativa sul circuito integrato all'interno. Un chip con package normale di solito ha marcature che lo identificano, proprio come fa il chip flash. Poiché i microcontrollori usati in dispositivi come questi spesso contengono una ROM interna, è possibile che parti o tutto il codice USB che volevo reverse engineering fossero in quella ROM. Avere quel codice in ROM ha il vantaggio di permettere il recupero di un dispositivo brickato o, se il produttore lo sceglie, di flashato dopo l'assemblaggio. Quella ROM esisteva all'interno di un chip che non avevo modo di identificare.
Recuperare i dati dal chip flash è un processo semplice e ben documentato: dissaldare il chip, metterlo in un programmatore flash standard come quelli di XGecu, e usarlo per estrarre i contenuti. Se ho bisogno anche di informazioni dalla ROM del microcontrollore, allora è meno semplice, ma comunque fattibile per un dispositivo come questo dove la protezione è improbabile. In passato, ho aggiunto codice alla flash SPI su un Tamagotchi Pix che avrebbe copiato la sua boot ROM nello spazio libero del chip flash, che poteva poi essere letto dallo stesso programmatore flash che ho usato per iniettare il codice. Tuttavia, in quel caso, il microcontrollore era adeguatamente incapsulato e aveva le informazioni del modello stampate sopra, quindi ho potuto trovare il suo datasheet per sapere quale set di istruzioni usava e dove si trovava la sua ROM nello spazio di memoria. A questo punto, non avevo nessuna di queste informazioni per il misterioso chip-on-board del ME2.
Nonostante le incertezze, l'unica strada apparente da qui è dissaldare il chip flash. Avevo anche acquistato alcuni socket per il chip flash nella speranza di poterne saldare uno al PCB del portatile. Questo mi avrebbe permesso di riprogrammare il ME2 e iterare rapidamente se avessi avuto bisogno di scrivere codice per estrarre la ROM interna dal microcontrollore. Sfortunatamente, non sono riuscito a rimuovere il chip flash con un saldatore senza danneggiarlo. Per risolvere questo problema di abilità dopo molti tentativi falliti, ho invece acquistato una stazione di rielaborazione (essenzialmente una pistola termica che afferma di poter raggiungere 500 °C) e ho rimosso il chip sciogliendo la saldatura con aria calda. Questo mi ha permesso di estrarre i contenuti della flash senza problemi, ma ha rivelato che usare effettivamente i socket che avevo acquistato sarebbe andato oltre le mie capacità. Non solo avrei dovuto saldare tutti i 48 minuscoli pin sul PCB, ma anche farlo abbastanza velocemente da evitare di fondere la plastica dei socket. Non avevo né gli strumenti né l'abilità per gestirlo, quindi se avessi avuto bisogno della ROM, avrei dovuto trovare un'altra strategia.
Il dump sembrava buono, comunque, e usando uno strumento che avevo già costruito specificamente per trovare bitmap non compressi in dump di firmware, ho potuto trovare immagini che sarebbero state normalmente visualizzate sul dispositivo:

Ho ottenuto un dump del firmware dal chip flash, ma prima di poter fare un serio reverse engineering, ho bisogno almeno di sapere quale set di istruzioni esegue il dispositivo. Non c'erano marcature sull'hardware stesso, quindi si sarebbe dovuto indovinare. Ho provato ad analizzare il codice in Ghidra, un disassembler, decompiler e incubo traballante open source che mi tiene occupato, con praticamente ogni tipo di specifica di processore con cui veniva fornito. Qualche variante ARM? Qualche discendente 6502? MIPS? Letteralmente qualsiasi altra cosa supportata da Ghidra? Tutto un sonoro 'no'.
Ho provato di tutto, e niente riusciva a disassemblare questo codice. Sapevo che era codice, perché riuscivo persino a trovare parti del codice che cercavo!

Grazie al mio lavoro passato sul dispositivo portatile Miuchiz, avevo una certa familiarità con il funzionamento dei dispositivi di archiviazione di massa USB. Ho identificato questo frammento come quasi certamente uno spostamento di 'U', 'S', 'B', 'S' da qualche parte, che è una firma specifica per il tipo di comunicazione di archiviazione di massa USB che stavo cercando. Parte o tutto il codice USB di cui avevo bisogno per fare reverse engineering per capire come interagire con questo dispositivo era sicuramente in questo dump della flash, ma senza alcun indizio su quale set di istruzioni fosse scritto, non potevo disassemblarlo.
A questo punto, avevo un paio di unità ME2 rotte. Sembra stupido, ma forse ci sono marcature da qualche parte sotto i blob di epossidica? Probabilmente no, ma per la fase di ricerca, a volte un'unità completamente decimata è più preziosa di una semplicemente rotta.
Beh, avevo una pistola termica e un coltello. Come si dice, quando hai una pistola termica e un coltello, tutto sembra... un chiodo? Penso sia così il detto.

Impostando la stazione di rielaborazione alla sua temperatura massima e facendo leva con un coltello, ho liberato l'intero blob di epossidica. La sua rimozione non ha rivelato marcature sotto il chip-on-board ora fuori dal board. Si può vedere il lato inferiore del die di silicio del microcontrollore, tuttavia, e l'epossidica ha un paio di bolle d'aria attraverso le quali si possono vedere i bond wire.
Come ho detto, a volte un'unità decimata vale più di un'unità rotta, e avevo una pistola termica, un coltello e un disperato bisogno di rispolverare i miei modi di dire.

Oh.
Huh.
Non avevo idea che si potesse decapsulare un CoB in quel modo. È semplicemente uscito pulitamente, e data la sua temperatura, sono contento che non l'abbia fatto nella mia direzione. È molto bello, ma in realtà c'è una strada da qui. Lasciatemi solo dare un'occhiata più da vicino con il mio microscopio elettronico.

Beh, è ciò che il suo manuale utente afferma che sia. Per essere onesti, ho controllato, e contiene almeno un elettrone.
Mentre distruggevo "hackeravo" altri giocattoli i cui piccoli componenti mettevano alla prova i miei occhi, è diventato ovvio che sapevo raramente cosa stesse succedendo all'altra estremità del mio saldatore. Un cortese consiglio da un amico ha portato all'acquisto di un microscopio digitale economico, destinato a monete e saldatura.

Nonostante non fosse proprio l'attrezzatura adatta al lavoro, contrariamente a quanto afferma il suo manuale utente, ho catturato questa immagine con il microscopio. È lontano anni luce dall'essere in grado di decifrare qualsiasi testo sul die, ma la disposizione generale è chiara, e sapevo dove trovare altre immagini come questa.
Siliconpr0n, ora conosciuto come Siliconprawn, ha un archivio dove molte persone hanno caricato die shot, anche se di solito di qualità migliore della mia. Sfortunatamente, non c'è un modo utile per cercare nel sito data l'informazione che avevo, così ho iniziato a cliccare, scorrere e ripetere...

Le sue impronte sono agli atti!
Dopo diverse ore, alle 4 del mattino, ho finalmente individuato qualcosa di familiare. È di qualità migliore della mia, ma la disposizione è inconfondibile. Ho un GPL162002A (o B) ruotato di 180 gradi rispetto all'immagine corrispondente scattata da John McMaster. È un microcontrollore GeneralPlus, il suo datasheet è disponibile su internet, e il suo set di istruzioni è μ'nSP.
μ'nSP, a quanto pare, è abbastanza comune per giocattoli di questo tipo ed epoca. Spero di essere perdonato per non aver indovinato che era un set di istruzioni il cui nome contiene caratteri che non sono nemmeno nell'alfabeto latino. Nonostante ciò, è ancora abbastanza di nicchia da non essere supportato da Ghidra di default. Fortunatamente, esiste del lavoro di terze parti per esso, così ho potuto iniziare a disassemblarlo in Ghidra, nominare le funzioni e importare i nomi dei registri dal datasheet.
Ecco la funzione di cui ero così certo che fosse codice USB solo dal suo dump esadecimale, interagendo con i registri USB come specificato nel datasheet del microcontrollore:

Come ho notato in precedenza, avevo già una certa familiarità con il modo in cui comunicano dispositivi di archiviazione di massa USB come questo, specialmente grazie ad alcuni lavori sperimentali di porting della mia libreria USB Miuchiz su macOS usando libusb. I dispositivi di archiviazione di massa USB essenzialmente incanalano comandi SCSI, e questi sono ben documentati online. Ad esempio, ci sono comandi per richiedere una lettura o una scrittura dal dispositivo.

Tuttavia, sapevo che in generale, i comandi standard, come per lettura o scrittura, non mi sarebbero stati utili. Quelli sono ciò che il tuo computer sa già fare con i suoi driver di archiviazione di massa integrati. Li emetterà per interagire con esso come qualsiasi normale dispositivo di supporti rimovibili. In questo caso, il comando di lettura recupererà solo il filesystem contenente il file di aiuto, e il comando di scrittura non farà nulla, poiché non è previsto che sia scrivibile. Questi non sono per interfacciarsi con l'intero chip flash; invece, sono effettivamente un piccolo CD-ROM simulato per aiutare gli utenti alle prime armi.
Alcuni ID comando, tuttavia, sono riservati per ciò che il vendor vuole implementare. I gestori per alcuni ID riservati vengono brutalmente iniettati prima che venga eseguita la normale ricerca ID.

Attraverso l'analisi statica, sono riuscito a identificare e nominare le funzioni che stavo cercando: lettura, programmazione e cancellazione della flash. Questi sono tutti comandi non standard che sono stati implementati per il ME2 e possibilmente altri dispositivi GeneralPlus, e quasi certamente usati dal software e dai driver originali del dispositivo. Puoi creare un messaggio USB per attivare uno qualsiasi di questi percorsi. La lettura ti consente di recuperare dati dalla flash. La programmazione ti consente di "programmare" la flash. La cancellazione ti consente di resettare tutti i bit in una regione della flash a 1, che se usata in combinazione con il comando di programmazione, può emettere una scrittura completa sulla flash, poiché la "programmazione" può solo invertire i bit da 1 a 0. Ciascuno dei comandi personalizzati che mi interessavano usa l'ID riservato 0xFF seguito da ID per i sottocomandi e qualsiasi parametro di cui l'operazione ha bisogno.
Le strutture esatte dei comandi non sono particolarmente rilevanti per il lettore, ma la metodologia potrebbe esserlo. Ho usato libusb (beh, in realtà, rusb) per facilitare tutta la mia interazione via USB. Questo metodo ti permette di scrivere codice in userland per interagire con il dispositivo USB, invece di scrivere un nuovo driver.
Quando il software Windows del ME2 è scomparso da internet, è stato come se il penultimo parlante della sua lingua fosse morto. Il dispositivo portatile ME2 è diventato, in un certo senso, un parlante terminale. Con un po' di sperimentazione e un po' di lettura di decompilazione a volte corretta, stavo leggendo la sua mente per imparare le parole della sua lingua quasi estinta. Quando ha risposto, ho capito di essere sulla strada giusta.
Č̶̯a̴̩͗n̵͉͆ ̴͍͠Ǐ̶̜ ̴͈͌h̷̙̔á̶͉v̸͈̽é̴̢ ̵͍͛a̵̞͝ ̴̤̉s̵̡͊ē̴̮c̸̭̅t̶̛͖o̸̡͠r̶̺̊ ̶̥̀ǫ̸̀f̸̦́ ̷̈́ͅỳ̷͎o̶̦̐u̵͙̚r̶͙͒ ̵̥̕f̸̡͝l̷͈̄a̶͍͋s̸̢̓h̸̗͝?̴̪̕
...No? Sarà il mio accento. Lasciatemi regolare e chiedere di nuovo: Posso avere un settore della tua flash? E il settore successivo? Sei disposto a programmare alcuni dei bit in quel settore? Posso avere di nuovo la tua flash per vedere se è cambiata? Oso chiederti di cancellare un settore... e sperare di capire quale ti sto chiedendo di distruggere?
Uno per uno, ho scritto il codice per strutturare, popolare e trasmettere i messaggi di cui avevo bisogno che il ME2 sentisse. Una volta che eravamo sulla stessa lunghezza d'onda, gli ho detto di inviarmi un paio di dump della flash mentre aveva diversi importi di punti. Dopo averli confrontati, sono riuscito a identificare dove sono memorizzati i punti nella flash e finalmente usare il mio computer per modificarli!

In effetti, potevo fare qualsiasi cosa volessi al dispositivo usando questi comandi, purché non comportasse la cancellazione di codice che era attivamente in uso. Il ME2 si è unito alla mia collezione di dispositivi che mostrano l'emblema di Miuchiz Reborn in posti dove non dovrebbe essere, incluso il microscopio digitale che ha scattato la die shot.

Ammettiamolo, la prima volta che ho provato a leggere/scrivere la flash, stavo agendo in modo un po' sconsiderato, perché non potevo vedere tutto il codice in esecuzione. Ad esempio, del codice chiama la ROM interna del microcontrollore, o routine nella RAM copiate lì dalla ROM. Alcune delle mie supposizioni per le altre funzioni sono state informate da come venivano impostati i registri di accesso diretto alla memoria (DMA). Se il DMA è impostato per copiare dal buffer USB, per esempio, probabilmente sta usando quei dati per programmare la flash, non per leggere dalla flash.

Questo codice, per esempio, chiama una funzione che risiede al di fuori della flash, in modo da non estrarre codice da sotto se stesso, prima di ritornare al codice che comunque ha appena estratto da sotto se stesso. Devi stare molto attento a non brickare il dispositivo.
La regione di memoria in questione è chiaramente disposta dal datasheet:

Ci sono 128 chiloparole di ROM particolarmente 'embadded' a cui non avevo ancora accesso, impedendomi di comprendere appieno il sistema.
Fortunatamente, la funzione per il comando di lettura personalizzato della flash non esegue il controllo dei limiti. Ciò significa che con un messaggio appositamente creato che tenta una lettura da un indirizzo flash molto alto, puoi avvolgerti l'intero spazio di indirizzi del microcontrollore, finendo di nuovo all'inizio. Poiché ciò equivale a una capacità di lettura arbitraria, non ho avuto bisogno di scrivere codice di dump sul dispositivo questa volta! Tutta la memoria è leggibile con questo bug, quindi l'ho usato per leggere la ROM Embadded, che ho salvato per un successivo reverse engineering.
Con tutta la memoria, sono riuscito a individuare il framebuffer del dispositivo in RAM, che mostrava l'immagine sullo schermo del dispositivo in quel momento:

Sono anche riuscito a leggere i registri di I/O generico (GPIO) dallo spazio di indirizzi del dispositivo facendo riferimento a dove il datasheet diceva che dovessero essere. Attivando il bug decine di volte al secondo, potevo effettivamente interrogare le pressioni dei pulsanti e trasformarlo in un controller USB se volevo: (Video)

Ad un certo punto durante i miei test, ho notato una strana modifica di un valore nella flash che non sembrava nemmeno dovesse essere un dato di salvataggio.

0x00AA (ricorda, la dimensione della parola di questo sistema è 16 bit) è stato scritto in un punto della flash che non avevo richiesto. Con la ROM Embadded, possiamo finalmente vedere il codice che spiega questo.

Questi chip flash ricevono comandi scrivendo a offset specifici. A differenza della RAM, che impegna immediatamente i dati scritti, il chip flash tenterà solo di interpretare le scritture come parte di un comando, quindi una singola scrittura nello spazio di indirizzi della flash non è sufficiente per modificare effettivamente alcun dato. Quando un pezzo di codice vuole programmare la flash, emette una sequenza di comandi a più passaggi che inizia scrivendo 0xAA a 0x5555 e termina scrivendo i dati desiderati all'indirizzo desiderato.Se un utente con troppo tempo libero (e magari una pistola termica e un coltello) si mette a provare a capire come funziona il dispositivo, potrebbe finire per chiedere al dispositivo di programmare un settore oltre la capacità del suo chip flash. Il processore è consapevole di ogni passaggio, ma il chip flash no. Invece, quel ciclo di comando finale manca completamente lo spazio degli indirizzi del chip flash, quindi il flash attende con impazienza quale valore dovrebbe essere programmato dove.
Processore: Ehi flash! Voglio iniziare a programmare un'altra parola!
Flash: Ricevuto! Programmazione 0xAA su 0x5555!
Processore: ...Eh?
A causa dei cicli di comando desincronizzati, il flash confonde il primo ciclo del comando successivo con l'ultimo ciclo del comando precedente, e 0xAA viene programmata su 0x5555. L'indirizzo equivalente per i tipici byte a 8 bit è 0xAAAA, che corrisponde a dove 0x00AA è stato scritto nel mio dump del flash.
Questo potrebbe potenzialmente essere usato per una scrittura arbitraria, purché si sia disposti a corrompere quella specifica parola nel flash, ma il dispositivo è già sufficientemente compromesso che non mi interessa brickare altre unità. Potrebbe essere possibile salvare questi dispositivi, poiché il reverse engineering della ROM embedded ha anche mostrato che contiene il proprio gestore USB e implementazioni di lettura/programmazione/cancellazione del flash. Tuttavia, sono riuscito a far entrare la ROM in quello stato (invece di avviarsi dal codice flash) solo una volta, e mai più. Basandomi sulla decompilazione della ROM, sospetto che possa dipendere da una porta GPIO lasciata flottante, ma non ne sono sicuro. In ogni caso, la mia missione qui era già stata compiuta.
Il risultato finale di questo misfatto è un'utilità da riga di comando in grado di:
Questo, insieme al codice del server di gioco e ad altre ricerche, è disponibile nel repository ME2-Restoration. Poiché i dettagli implementativi sono disponibili lì e probabilmente non interessano il lettore tipico, i dettagli tecnici specifici sono stati omessi qui a favore della descrizione di processi e tecniche.
Ancora più importante, ciò dimostra che il software PC originale non è strettamente necessario per comprenderne o preservarne la funzionalità. Anche con il software ufficiale perso nel tempo, è stato possibile aprire la scatola nera che era l'ME2 e ricostruire il suo protocollo dall'hardware e dal firmware, ripristinando un'interfaccia altrimenti morta in qualcosa di nuovamente utilizzabile. Questo non si limita a interfacce come USB. Leggi come ho ricreato un server di licenze da tempo defunto per riportare in vita un editor vettoriale di un decennio fa.
Questa è anche la mia prima volta che decapsulo un circuito integrato, quindi per rendergli il rispetto che merita, ho acquistato un microscopio migliore e da allora ho contribuito con la foto di altissima qualità del GPL162002A/B a siliconprawn, qui in anteprima a risoluzione ridotta per essere più amichevole per il web:
