Disponibile un nuovo aggiornamento per FreePSXBoot, l’exploit consente di caricare codice arbitrario su di una console PSOne utilizzando semplicemente una Memory Card.
A differenza di TonyHAX, FreePSXBoot non necessita di alcun entrypoint. Attualmente sfrutta la memoria non inizializzata nello spazio del kernel che deve essere pari a 0
per poter funzionare correttamente.
I chip SDRAM hanno una velocità di decadimento piuttosto bassa e questo exploit sarà attualmente affidabile solo se la macchina è stata spenta per un tempo sufficientemente lungo.
Per utilizzarlo, è necessario un modo per copiare le immagini complete della scheda di memoria (non i singoli file) su di una scheda di memoria. Alcune possibilità sono:
- Una PS2 e il software Memory Card Annihilator v2 (utilizzando “Restore MC image”).
- Memcarduino. Richiede la saldatura di fili alla scheda di memoria.
- Utilizzando una Memcard Pro, che consente di creare schede di memoria virtuali su di una scheda SD, è sufficiente rilasciare il file immagine della scheda che si desidera utilizzare come Memory Card 1, Channel 1.
- Utilizzando Unirom e NOTPSXserial con un cavo seriale/USB, utilizzando il comando:
nops /fast /mcup 0 FILE.mcd COMPORT
doveFILE
è il file mcd corrispondente al tuo modello eCOMPORT
corrisponde alla porta seriale del tuo computer. - MemcardRex con DexDrive, Memcarduino o PS1CardLink. Assicurati di utilizzare l’ultima versione, che consente di scrivere dati grezzi sulla scheda di memoria (richiesta per FreePSXBoot).
- PSXGameEdit con DexDrive (successo non garantito).
Attenzione: Eseguire il flash della scheda di memoria con FreePSXBoot potrebbe portare , è necessario essere consapevoli di quanto segue:
- I file di immagine
.mcd
sostituiscono l’intero contenuto della scheda, il che significa che la scheda di memoria verrà COMPLETAMENTE CANCELLATA dopo aver flashato un’immagine.mcd
, quindi creare un backup dei salvataggi è obbligatorio. - Poiché l’exploit ha il filesystem della Memory Card corrotto appositamente per essere eseguito, la tua scheda diventerà inutilizzabile per le normali operazioni. Cioè, non sarai in grado di utilizzare questa scheda per salvare e caricare i salvataggi di gioco e causerà arresti anomali sulla tua PS1 o sulla tua console PS2 (se ne hai).
- Una volta installato, potrebbe diventare difficile da disinstallare, poiché il normale software per riformattare una scheda di memoria non funzionerà, a causa dell’exploit stesso. Potresti ritrovarti senza mezzi per recuperare la scheda di memoria; se per esempio il tuo metodo di installazione era Memory Card Annihilator v2, allora andrà in crash. Memcarduino, Unirom o l’utilizzo di Memcard Pro sarebbero attualmente scommesse sicure.
Guida
- Copia l’immagine completa della Memory Card corrispondente al tuo modello/BIOS su di una scheda di memoria.
- Inseriscilo nello slot 1.
- Se hai un modello SCPH-1001 o SCPH-1002 con BIOS versione 2.0: inserisci un’altra scheda di memoria nello slot 2 (il suo contenuto non ha importanza).
- Accendere la PlayStation con il coperchio aperto e andare al gestore della scheda di memoria.
- Dopo pochi secondi, lo schermo si riempirà di ciano. Attendere circa 30 secondi per visualizzare la schermata di benvenuto di Unirom.
- Se la schermata ciano non viene visualizzata, è stata utilizzata un’immagine della scheda di memoria errata o l’immagine della scheda di memoria non è stata scritta correttamente (il file mcd deve essere scritto come dati grezzi sulla scheda di memoria) o qualcos’altro è andato storto. Se sei sicuro al 100% che l’immagine della scheda di memoria sia stata scritta correttamente e che stai utilizzando l’immagine corretta, apri un problema.
- Una volta caricato Unirom, puoi inserire un CD, chiudere il coperchio e premere per caricare il gioco. Nota: La PlayStation giapponese non può avere la propria unità CD sbloccata da Unirom e quindi non può caricare i backup.
- Non dimenticare di rimuovere la scheda di memoria, poiché il suo exploit si attiverà anche nei giochi. Questo non è un problema quando si utilizza Memcard Pro, poiché cambierà automaticamente la scheda virtuale nel gioco che stai avviando.
Ripristino della scheda di memoria
- Utilizzare MemcardRex.
- Alcuni giochi che hanno un file manager di salvataggio (mostra il contenuto della scheda di memoria prima del salvataggio) integrato, come OddWorld: Abe’s Oddysee e Cool Boarders 4 (soffre di un avvertimento che impedisce al gioco di caricare la scheda di memoria con alcune versioni dell’exploit) ad esempio, può essere utilizzato per sovrascrivere FreePSXBoot durante il salvataggio dei progressi.
- Memory Card Annihilator v2 potrebbe essere in grado di formattare una scheda, ma deve essere inserita all’ultimo momento. Non è garantito che questo metodo funzioni.
- In generale, strumenti e giochi si bloccano quando si tenta di formattare una scheda di memoria caricata con FreePSXBoot, ma potrebbero essere in grado di formattarla inserendo prima una normale scheda di memoria e cambiandola con la scheda di memoria FreePSXBoot appena prima dell’inizio dell’operazione di formattazione.
- In futuro prevediamo di includere una versione completa di Unirom nelle immagini della scheda di memoria, con la possibilità di formattare le schede di memoria.
Modelli supportati
- Tutti i modelli sono supportati e testati su emulatore o hardware reale, ad eccezione dei modelli di debug (DTL-H) e Net Yaroze (possono funzionare, ma non vengono testati).
- A partire dalla versione 20210419, l’exploit è affidabile al 100% su tutti i modelli supportati. Tuttavia, alcune immagini di exploit sono state testate solo su emulatori e potrebbero non funzionare su hardware reale; il feedback è il benvenuto.
- Vedere la tabella seguente per maggiori dettagli e collegamenti per il download.
Changelog
- 05/05/2021: Versione Unirom aggiornata alla 8.0.H.
- 2021-04-28: Corretto l’exploit per le versioni BIOS 2.1 (A) e 2.2 (A) (leggi il frame fittizio per evitare errori).
- 2021-04-27: Aggiunto supporto per più versioni del BIOS, che ora sono identificate dal loro CRC32.
- 2021-04-22: Aggiunto supporto per BIOS 2.0 (1995-05-07), 4.0 e 4.1 (1997-11-14).
- 2021-04-21: Aggiunto supporto per BIOS 1.1 e corretto exploit BIOS 2.0 (per funzionare necessita di icache flush)
- 2021-04-21: Barra di avanzamento aggiunta nel payload della stage2 (grazie Nicolas Noble).
- 2021-04-20: Aggiunto supporto per BIOS 3.0 1996-09-09 (SCPH-5500) (grazie sickle).
- 2021-04-19: Aggiunto supporto per BIOS 1.0 e 4.3 (rispettivamente SCPH-1000 e SCPH-100).
- 2021-04-19: Exploit affidabile al 100% per ogni BIOS supportato; ora aggancia un ISR (grazie sickle).
- 2021-04-19: versione Unirom aggiornata a 8.0.F.
- 2021-04-14: L’exploit utilizza fastload, che legge la scheda di memoria molto più velocemente del codice di Sony (grazie Nicolas Noble).
- 2021-04-12: Nuova versione di Unirom, in grado di caricare i giochi. Enormi ringraziamenti ai collaboratori di psxdev.
- 2021-04-11: Exploit affidabile al 100% per SCPH-7002, SCPH-7502 e SCPH-9002.
Dettagli exploit
FreePSXBoot sfrutta un bug nel BIOS PSX per caricare codice arbitrario. Il bug è nel codice che legge la directory della scheda di memoria.
Questo exploit è attualmente disponibile solo per il BIOS SCPH-9002, ma dovrebbe essere portabile su ogni altra versione (a meno che Sony non abbia in qualche modo corretto il bug nelle versioni successive del BIOS).
Introduzione
Una scheda di memoria PSX ha 128 kB di memoria, divisa in 16 blocchi da 8 kB ciascuno. Il primo blocco è riservato per scopi speciali, lasciando 15 blocchi utilizzabili per i giochi.
Ogni blocco è diviso in 64 settori (o frame) di 128 byte ciascuno. Il settore è l’unità minima con cui può lavorare PSX, ovvero la PSX legge e scrive multipli di 128 byte.
Il primo blocco occupa i settori da 0 a 63. Contiene 15 voci di directory, che descrivono il contenuto dei blocchi seguenti (ad es. Nome file, dimensione, ecc…), e un elenco di settori danneggiati e la loro sostituzione, e altre cose non importanti. I dettagli sul formato dei dati possono essere trovati qui.
La struttura delle voci della rubrica è la seguente:
- 4 byte: stato di allocazione del blocco.
- 4 byte: dimensione del file, in byte.
- 2 byte: index del numero di blocco successivo se il file occupa più blocchi; 0xffff altrimenti.
- 21 byte: nome del file in ASCII (terminato da null).
- Rest: inutilizzato (tranne l’ultimo byte che è un checksum).
Il bug
Gestione della scheda di memoria
La shell PSX (ovvero il software avviato all’avvio di PSX senza CD) può gestire le schede di memoria (copiare ed eliminare file). Quando analizza le voci di directory, copia i primi 32 byte di ciascuna voce di directory nella RAM e controlla se sono sani:
- Copia tutte le voci della directory nella RAM (in un array di 15 elementi di 32 byte).
- Passa attraverso ogni voce che rappresenta il primo blocco di un file; le ripara se necessario.
- Passa attraverso ogni voce che non rappresenta il primo blocco di un file; le ripara se necessario.
Questo viene fatto in una funzione che viene chiamata ReadMemCardDirectory, situata in 0xbfc08b3c
in SCPH-9002.
Controlli limite mancanti
La shell PSX presume che la dimensione del file e l’index del blocco next in ciascuna voce siano validi e non esegue alcun controllo limite su di essi. Per il passaggio 3, passa attraverso ogni voce di directory e segue ciecamente il blocco next nel file:
entry* next = &entries[first->next_index];
Manipolando next index, possiamo creare il punto next
ovunque, dalle entries
alle entries + 0x20 * 0xfffe
. Tutti i dati presenti verranno elaborati come voce next.
Inoltre, la shell PSX non corregge le voci immediatamente: se si fa riferimento al blocco, verrà contrassegnato come tale e le riparazioni vengono elaborate dopo che tutte le voci sono state verificate. In pseudocodice:
uint32_t is_referenced[15] = { 0 }; for (int i = 0; i < 15; i++) { entry* ent = &entries[i]; if (is_beginning_of_file(entry)) { for (int i = 0; i < ent->size / 0x2000; i++) { uint16_t next_index = ent->next_index; is_referenced[next_index]++; if (next_index == 0xffff) { break; } } } }
Controlliamo next_index
e controlliamo anche ent->size
: possiamo incrementare qualsiasi variabile a 32 bit nell’intervallo (limitato) di next_index
. Ma dobbiamo assicurarci che ent
punti a blocchi noti di memoria, altrimenti perderemo il controllo di dove punta.
Fortunatamente, c’è una grande porzione di 00 byte poco dopo l’array entries
che verranno interpretate come puntanti all’index 0, facendo in modo che ent
punti nuovamente a una voce di directory che controlliamo.
In pratica, questo significa che possiamo incrementare di un valore controllato la memoria in una posizione scelta (ma limitata). e inizia a suonare come se il gioco fosse finito, ma c’è un problema …
is_referenced
è un array allocato nello stack e sembra che potremmo usarlo per sovrascrivere un indirizzo di ritorno e prendere il controllo del contatore del programma. Tuttavia, ciò non è possibile perché l’array si trova in cima allo stack e tutto ciò che segue sono solo dati inutilizzati.
Infatti, nella mappa di memoria PSX, lo stack è mappato agli ultimi indirizzi della RAM: l’array is_referenced
è a 0x801ffcd0
, solo 816 byte prima della fine della RAM, e questi 816 byte contengono solo dati non utilizzati …
Il mirroring della RAM
Per qualche ragione, i 2 megabyte di RAM della PSX (cioè 0x200000 byte, mappati da 0x80000000 a 0x80200000) vengono specchiati 4 volte. Ciò significa che la lettura (e la scrittura) all’indirizzo 0x80200000 in realtà leggerà/scriverà a 0x80000000.
Questo è l’inizio della RAM e contiene, tra le altre cose, una serie di puntatori a funzioni che possiamo andare a modificare.
Payload
Sovrascrivere il puntatore di funzione destro
ReadMemCardDirectory viene chiamato due volte, una per ogni slot della scheda di memoria. La prima cosa che fa è chiamare una funzione del BIOS tramite un puntatore a funzione, allow_new_card
(questo imposta solo un flag per dopo). Questo è il puntatore a funzione perfetto per sovrascrivere:
- Fa qualcosa di banale e relativamente inutile: è facilmente replicabile in un payload.
- Viene chiamato al momento perfetto: subito dopo che il nostro exploit ha sovrascritto il puntatore alla funzione.
- Può essere facilmente ripristinato dal payload.
Quindi il piano è trovare un index e una dimensione per la prima voce di directory, con i seguenti vincoli:
0x801ffcd0 + index * 4 == 0x802009b4
. Il primo indirizzo è l’arrayis_referenced
; il secondo è il puntatore alla funzioneallow_new_card
, nella RAM con mirroring: l’index deve essere 0x0339.entries + 0x20 * index
punta alla memoria che farà tornare il codice mostrato sopra alla prima voce della directory, permettendoci di controllare quante volte il valore viene incrementato. Fortunatamente, la memoria in quella regione è tutta 0, grazie al decadimento della SDRAM.- Il nostro carico utile si trova in 0xa000be48, che è un mirror di 0x0000be48. La funzione originale è a 0x00004d3c: dobbiamo incrementarla di 0x710c volte. Ciò significa che la dimensione della nostra voce di directory deve essere
0x710c * 2 * 0x2000 = 0x1c430000
. Questo numero deve essere positivo (ovvero inferiore a 0x80000000) o il codice PSX non lo elaborerà.
Ecco come deve apparire la nostra prima voce di directory (settore 1 della scheda di memoria, offset 0x80):
00000080 51 00 00 00 00 00 43 1C 39 03 46 52 45 45 50 53 Q.....C.9.FREEPS
00000090 58 42 4F 4F 54 00 00 00 00 00 00 00 00 00 00 00 XBOOT...........
000000A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6D ...............m
Loader
Come specificato il payload si trova a 0xa000be48. Questo indirizzo viene utilizzato come un buffer che contiene l’ultimo settore letto di una scheda di memoria nello slot 0.
Dopo aver eseguito le riparazioni, ReadMemCardDirectory leggerà l’elenco dei settori danneggiati (cioè i settori da 16 a 35 nella scheda di memoria). L’ultimo byte di ciascuno di questi settori è un checksum (tutti gli altri byte XORed).
Se un qualsiasi checksum di un settore letto è errato, ReadMemCardDirectory salta e cancella le voci della directory. Usiamo questo a nostro vantaggio:
- Metteremo il payload nel settore 16; avrà un checksum errato, che impedirà ulteriori letture, assicurandosi che rimanga nel buffer a 0xa000be48.
- La cancellazione delle voci della directory garantisce che nessun altro codice esegua una strana manipolazione della memoria quando lo attraversa.
- Questo è (trascurabilmente) più veloce.
Il payload deve trovarsi nel settore 16 (offset 0x800) ed è limitato a 128 byte. Questo è molto piccolo: solo 32 istruzioni MIPS. Fortunatamente, questo è appena sufficiente per creare un caricatore che caricherà più codice dalla scheda di memoria (vedere loader.S, che è grande esattamente 128 byte).
Problemi noti
- L’exploit non funziona sempre sull’hardware reale, a causa del decadimento della SDRAM e del fatto che il kernel non inizializza esplicitamente la sua memoria a tutti gli zeri, è probabile che questo venga migliorato con le versioni future, ma richiede un exploit più complicato.
- L’exploit è disponibile solo per SCPH-9002. Questo è quello che ho. Dovrebbe essere relativamente facile portarlo su altri sistemi.
[/spoiler]
Download
Queste immagini sono predefinite con Unirom.
Sono disponibili diversi download per diverse versioni del BIOS. Scaricare la ROM corretta per la tua versione del BIOS. Se manca un modello o una versione del BIOS, significa che non è ancora supportato.
Le immagini verranno aggiornate man mano che verranno sviluppate versioni più affidabili o più veloci dell’exploit. Le versioni precedenti possono essere trovate nella directory images
.
Versione e data del BIOS | Modelli | Exploit affidabile al 100%? | Download Link |
1.0 (22/09/1994) | SCPH-1000 | Si | 20210421 |
1.1 (22/01/1995) | SCPH-3000 | Si | 20210421 |
2.0 (07/05/1995) | SCPH-1001 | Si, vedere la nota sotto | 20210421 |
2.0 (10/05/1995) | SCPH-1002 | Si, vedere la nota sotto | 20210421 |
2.1 (17/07/1995-07-17) | SCPH-1001 SCPH-1002 SCPH-3500 | Si | 20210421 |
2.2 (04/12/1995) | SCPH-1001 SCPH-1002 SCPH-5000 SCPH-5003 SCPH-5903 | Si | 20210421 |
3.0 (09/09/1996) | SCPH-5500 | Si | 20210421 |
3.0 (18/11/1996) | SCPH-5001 SCPH-5501 SCPH-5503 SCPH-7003 | Si | 20210421 |
3.0 (06/01/1997) | SCPH-5502 SCPH-5552 | Si | 20210421 |
4.0 (18/08/1997) | SCPH-7000 SCPH-7500 SCPH-9000 | Si | 20210421 |
4.1 (14/11/1997) | SCPH-7000W | Si | 20210421 |
4.1 (16/12/1997) | SCPH-7001 SCPH-7002 SCPH-7501 SCPH-7502 SCPH-7503 SCPH-9001 SCPH-9002 SCPH-9003 SCPH-9903 | Si | 20210421 |
4.3 (11/03/2000) | SCPH-100 | Si | 20210421 |
4.4 (24/03/2000) | SCPH-101 SCPH-102 | Si | 20210421 |
4.5 (25/05/2000) | SCPH-101 SCPH-102 SCPH-103 | Si | 20210421 |
[stextbox id=’info’]Nota: Per il BIOS 2.0 (SCPH-1001 o SCPH-1002): la scheda di memoria contenente FreePSXBoot deve essere inserita nello slot 1 e un’altra scheda di memoria deve essere presente nello slot 2. La scheda di memoria nello slot 2 può avere qualsiasi contenuto.[/stextbox]
Vedere il generatore di cartelle per uno strumento che può essere utilizzato per generare i propri payload e le schede di memoria.
Le immagini della scheda di memoria sono dati grezzi: la scheda di memoria deve avere lo stesso identico contenuto dei file. Utilizzare Memcarduino o qualcosa di simile; non utilizzare un file manager per schede di memoria, poiché tenterà di correggere i dati che stiamo modificando.
Se l’exploit avrà successo, vedrete lo schermo lampeggiare in arancione. Altrimenti, spegnere e riaccendere la PSX e riprovare dopo circa un minuto. Potrebbero essere necessari alcuni tentativi.
L’exploit funziona anche negli emulatori e funziona sempre perché la memoria è sempre inizializzata a 0. Testato con no$psx e pcsx-redux.
Fonte: github.com