Il developer xyzz, membro del team Molecule e autore dell’applicazione Moonlight Vita, ha pubblicato un nuovo e sofisticato metodo pronto all’uso per poter eseguire con semplicità e arbitrariamente complessi payload ROP su Nintendo Switch.
L’utilizzo di questi script viene consigliato ai soli developer e ricercatori che vogliano cimentarsi nello sviluppo di applicazioni sulla console ibrida Nintendo.
Installazione
- Scaricare l’archivio da questo indirizzo.
- Copiare il file
config.py.sample
inconfig.py
e modificarlo per fare in modo che possa selezionare il tuo target.
Esecuzione
- Digitare
./server.py+indirizzo IP su Nintendo Switch
. Questo script andrà ad avviare il server web e il server socket (rpc).
Il server Web viene utilizzato per servire l’exploit JS e lo stage1 rop.js, per impostazione predefinita viene eseguito sulla porta 6969 quindi è necessario un nginx o simile per inoltrare conntest.nintendowifi.net (ma dipende dalla destinazione che si utilizza), io uso questa configurazione:
server { listen YOUR_IP_FROM_SWITCH:80; server_name conntest.nintendowifi.net; root /var/www/conntest.nintendowifi.net; location / { proxy_pass http://INDIRIZZO_IP_SU_SWITCH:6969; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
Il server socket è quello utilizzato per l’effettivo RPC, viene eseguito sulla porta 6970 per impostazione predefinita e non è necessario configurare nulla per farlo funzionare.
Una volta terminato, passate su Switch alla solita pagina Web (captive portal o puyo-puyo, a seconda dell’obiettivo) ed eseguire l’exploit.
Il server ora dovrebbe dirvi di eseguire da terminale il comando ./client.py
una volta che avrete tutto pronto.
Lo script client.py
utilizza socket localhost per comunicare con server.py
in modo da poter modificare e riavviare client.py
senza disconnettersi dallo switch.
Comandi di scrittura
Sempre all’interno dello script client.py
, ogni qualvolta che si esegue il comando self.execute()
, si “invia” un payload all’interno dello Switch recuperando il buffer dei risultati.
Il payload è 0x8000 byte di script rop e il risultato è 0x8000 byte di dati.
I dati che si ottengono provengono da data_base
, quindi in pratica se fai lo script rop:
rop.write64(0xDEADBEEF, data_base)
data = self.execute(rop)
data
inizia come "\xEF\xBE\xAD\xDE"
.
Si noti che il buffer che si ottiene è di dimensioni fisse, assicurarsi inoltre di NON utilizzare l’ultimo byte 0x1000 di dati; in pratica non scrivere a data_base + 0x7000
e aspettarsi di rileggere ciò che hai scritto!
Assistente di funzione
Function helper è un wrapper su client.execute()
, esegue una singola funzione e fornisce un valore di ritorno (e facoltativamente per tutti i registri).
Ciò significa che puoi scrivere payload come questo:
def some_cmd(self, args): handle = self.fh.fopen(args[0], "rb") for x in range(123): self.fh.fread(...) self.fh.fclose(handle)
Ogni invocazione del manager di funzioni richiama un singolo roundtrip di ropchain, quindi potrebbe essere lento se si vanno ad eseguire un sacco di cose, ma è abbastanza veloce nella maggior parte dei casi.
Inoltre, dopo che è stato richiamato l’helper della funzione, imposta self.mem sui dati restituiti in modo da poter scrivere ad es. una memoria dumper come questa:
def examine_mem(self, args): addr, length = int(args[0], 0), int(args[1], 0) self.fh.memcpy(data_base, addr, length) data = self.mem[0:length] print hexdump(data, start=addr)
Non dimenticare la limitazione delle dimensioni: non aspettarti di avere più di 0x7000 byte disponibili (se hai bisogno di più, titti robusti).
Shell interattiva
client.py
fornisce una shell interattiva simile a Python e ci sono molti comandi disponibili (vedi la fonte) con cui giocare!
Crediti
- Originariamente creato da @xyzz, un sacco di miglioramenti di @plutooo e @yellows8.
Download: rop-rpc (source code e script Python)