- Dengan merekayasa balik chip SWL01U pada synthesizer Yamaha PSR-E433 lama, kode dapat ditulis ke RAM dan video Bad Apple ditampilkan di LCD hanya lewat pesan USB-MIDI SysEx
- Melalui eksperimen JTAG IDCODE
0x3f0f0f0fdan OpenOCD/GDB, dipastikan bahwa chip tersebut bekerja seperti inti ARM7TDMI, lalu ROM internal 64KiB dan firmware flash eksternal 16MiB berhasil di-dump - Di dalam firmware terdapat shell tersembunyi yang berjalan di atas MIDI SysEx, dan setelah
loginserta kata sandi#0000, perintah baca/tulis memori dapat digunakan - Dengan perintah tulis memori arbitrer, kode ARM disuntikkan ke RAM lalu alamat return pada stack ditimpa, sehingga eksekusi kode hanya dengan memutar file MIDI menjadi mungkin tanpa JTAG atau UART
- Output LCD ditingkatkan lewat kontrol CGRAM, penyalinan task table, penonaktifan display task, dan penggantian callback shell, sehingga volume transfer per frame turun dari 6732 byte menjadi 92 byte
Investigasi internal Yamaha PSR-E433
- Perangkat targetnya adalah synthesizer Yamaha PSR-E433 yang sudah lama dipakai, dan pada papan utamanya terdapat dua chip flash, chip RAM, serta chip
YAMAHA SWL01Udengan labelDMLCD - Informasi publik tentang SWL01U hampir tidak ada, dan hanya satu tulisan yang ditemukan secara online menyebut bahwa chip itu mungkin berbasis inti CPU SuperH
- Manual servis model serupa, E443, memuat pinout SWL01U, dengan penandaan
TESTN,PROTN, dua UART dua arah, serta test point JTAG - Pendekatan awal dibagi menjadi empat jalur
- memanipulasi pin
TESTNdanPROTNuntuk memeriksa perubahan mode boot - menyolder ke pin UART Tx untuk memeriksa output
- membaca kode identifikasi chip lewat JTAG
- melepas chip flash untuk dump firmware
- memanipulasi pin
- Saat
TESTNdiaktifkan, synthesizer tidak mau boot, danPROTNtidak mengubah perilaku perangkat - Penyolderan langsung ke pin UART Tx yang tidak digunakan juga tidak menghasilkan output pada keempat kombinasi
TESTN/PROTN
Perilaku ARM7TDMI yang terungkap lewat JTAG
- Karena detail rangkaian JTAG perlu dijelaskan per vendor, pembacaan IDCODE yang didukung hampir semua perangkat lebih dulu dicoba memakai OpenOCD
- OpenOCD melaporkan IDCODE
0x3f0f0f0f, dan nilai ini tampak dapat dikaitkan dengan mikrokontroler berbasis ARM7 seperti seri STMicroelectronics STR7xxx atau Atmel SAM7xxx - Ketika SWL01U ditetapkan sebagai target
arm7tdmidi OpenOCD, koneksi berhasil dibuat dan perangkat dilaporkan memiliki 2 unit breakpoint/watchpoint di hardware - Saat eksekusi dihentikan dan dilanjutkan lewat GDB, arus papan berubah secara konsisten
- sekitar 115mA saat berjalan
- sekitar 98mA saat jeda
- Perubahan arus ini menjadi indikasi kuat bahwa inti ARM7TDMI benar-benar sedang dihentikan dan dijalankan kembali
Dump firmware ROM dan flash
- Menurut dokumentasi ARM7TDMI, reset vector berada di alamat
0, dan ketika alamat0dibaca lewat GDB, terlihat instruksi lompat berbentukldr pc, [pc, #24] - Setelah 16MiB data di-dump dari alamat
0dan dibuka di Cutter, string tampak berulang setiap 64KiB- contoh:
SWL01U Internalberulang di0x0000bfd0,0x0001bfd0,0x0002bfd0, dan seterusnya
- contoh:
- Berdasarkan pola berulang dan string tersebut, dump ini dinilai bukan flash eksternal melainkan memori internal chip, sehingga disimpulkan SWL01U memiliki ROM 64KiB
- Target lompatan reset vector adalah
0x02000000, dan saat 16MiB di-dump lagi dari alamat ini, tidak ada pola pengulangan - Dump flash eksternal berisi string yang memang terlihat saat synthesizer digunakan
GrandPnoTr1 will be OverWritten!BogiWogi
- Tata letak memori yang teridentifikasi adalah sebagai berikut
- ROM internal:
0x00000000, 64KiB - flash eksternal:
0x02000000, 16MiB - saat boot, ROM segera menyerahkan kontrol ke flash eksternal
- ROM internal:
Shell tersembunyi yang ditemukan dengan Ghidra
- Karena Cutter saja tidak cukup untuk analisis, proses dialihkan ke Ghidra, lalu struktur firmware dipahami dengan mengikuti string dan xref
- String seperti
help,?,info, danverterkumpul di alamat yang berdekatan, dan masing-masing terhubung ke array yang tampak berupa pasangan nama perintah dan function pointer - Fungsi pemrosesan perintah berbentuk state machine, dan dari string
loginsertaPasswd Error, dipastikan bahwa ini adalah shell dengan prosedur login - Pemrosesan input shell berjalan dengan menelusuri circular buffer 256 byte per karakter, lalu mengeksekusi perintah saat menemukan karakter
\r - Alur login adalah sebagai berikut
- saat
logindimasukkan, keluarpasswd? - saat kata sandi
#0000dimasukkan, keluarlogin OK - setelah itu, perintah dapat dijalankan
- saat
- Perintah shell yang teridentifikasi mencakup
logout,help,?,info,verstack,perf-on,perf-off,perf-dispd,dp,d xxxxx,d/s xxxxxm ADDRESS DATA,m/b ADDRESS DATA,m/w ADDRESS DATA,m/l ADDRESS DATA
- Perintah
infomengembalikan informasi berikutDevelopName PSR-E433DevelopNumber #3341Main DevelopNumber #3341Make data & time MAY 16 2012 19:00:57J/E Select English
Shell yang berjalan di atas USB-MIDI SysEx
- Fungsi output shell membagi setiap byte menjadi nibble 4-bit atas dan bawah, menaruhnya ke byte terpisah, lalu menambahkan header dan footer tetap di depan dan belakang
- Struktur paket untuk prompt
>adalah sebagai berikut- header:
F0 43 73 01 52 19 00 00 - payload:
03 0E 02 00 - footer:
F7
- header:
- Pesan MIDI SysEx dimulai dengan
0xF0, melewati manufacturer ID dan payload, lalu berakhir dengan0xF7, dan payload hanya boleh berisi byte dengan MSB 0 0x43pada header adalah manufacturer ID Yamaha, dan struktur paket shell ini cocok dengan format pesan Yamaha SysEx- Descriptor USB synthesizer hanya menampilkan antarmuka MIDI dan tidak memiliki serial port terpisah
- Setelah skrip Python dibuat untuk menerjemahkan antara terminal dan protokol shell, shell dapat diajak berkomunikasi lewat USB-MIDI
Eksekusi kode dengan MIDI shellcode
- Perintah shell
m/l AAAAAAAA DDDDDDDD\rmelakukan penulisan memori 32-bit, dengan alamat dan data dikirim sebagai ASCII heksadesimal - Bahkan untuk menulis payload 4 byte, jumlah transfer nyata membengkak besar
- setiap byte perintah diubah menjadi dua byte nibble 4-bit
- 9 byte ditambahkan ke pesan SysEx
- setiap 3 byte dibungkus menjadi paket USB-MIDI 4 byte
- untuk penulisan 4 byte, synthesizer harus menerima 72 byte
- bila echo dan prompt dihitung, total 396 byte berpindah
- Setelah menemukan area RAM yang tampaknya tidak digunakan, kode assembly ARM ditempatkan di sana, lalu alamat return di stack ditimpa untuk mengeksekusi kode tersebut
- Payload pertama memanggil fungsi output string di dalam firmware untuk menampilkan
HeloWrldpada area teks 8 karakter di LCD - Metode ini bekerja tanpa JTAG maupun UART, dan dapat dijalankan hanya dengan menanamkan pesan ke file MIDI lalu memutarnya
- File MIDI untuk firmware PSR-E433 1.02 juga disediakan, tetapi diperingatkan bahwa memutarnya pada perangkat Yamaha lain atau versi firmware PSR-E433 lain dapat menyebabkan perilaku yang tidak dapat diprediksi
Menampilkan Bad Apple di LCD
- Pengendali LCD Yamaha PSR-E433 adalah ML9040A, dan secara default strukturnya dirancang untuk menangani karakter teks dot-matrix
- LCD tidak hanya memiliki area dot-matrix, tetapi juga area not musik, 7-segment, penanda chord, dan area tampilan keyboard di bagian bawah
- ML9040A memiliki tiga jenis memori
- DDRAM: host menulis data karakter yang akan ditampilkan
- CGROM: mengubah kode karakter menjadi pola grafis
- CGRAM: host dapat mendefinisikan hingga 8 karakter kustom
- Firmware memanipulasi CGRAM untuk mengendalikan elemen tampilan non-teks di bawah area dot-matrix, dan jalur ini dapat dipakai untuk menampilkan grafis kustom
- Setelah ditemukan fungsi firmware yang mengirim data arbitrer ke pengendali LCD dan pola checker dimuat ke CGRAM, firmware ternyata terus memperbarui CGRAM sehingga data itu segera tertimpa
Mengendalikan pembaruan tampilan lewat manipulasi RAM
- Karena menimpa flash secara langsung berisiko membuat perangkat brick, semua eksperimen dibatasi pada manipulasi RAM agar bisa dipulihkan hanya dengan menyalakan ulang daya
- Di dalam firmware terdapat struktur yang tampak seperti RTOS primitif, dan di flash ada tabel global yang mendefinisikan callback function, stack, dan atribut untuk 64 task
- Saat boot, firmware flash memberi tahu ROM lokasi task table, lalu ROM menyimpan lokasi itu ke variabel global di SRAM internal
- Dengan menyalin task table ke RAM lalu mengubah ROM agar memakai tabel baru itu, callback task dapat diganti tanpa memodifikasi flash
- Callback untuk task pembaruan display kemudian diganti dengan callback idle bawaan, sehingga firmware tidak lagi terus menimpa CGRAM
Peningkatan efisiensi transfer dan artefak layar
- Implementasi awal Bad Apple memang berjalan, tetapi efisiensi transfernya rendah sehingga frame rate sangat rendah dan muncul artefak di layar
- Bahkan jika per frame hanya mengirim 64 byte CGRAM dan penimpaan alamat return 32-bit, volume transfer nyata tetap 6732 byte untuk payload 70 byte
- Ada dua penyebab utama efisiensi rendah ini
- data harus dibungkus dalam bentuk perintah shell
- synthesizer meng-echo perintah per karakter sebagai paket SysEx besar
- Dengan mengganti callback task shell menjadi callback buatan sendiri yang menerima data mentah dan tidak merespons, overhead pembungkusan perintah dan echo dapat dihilangkan
- Setelah optimasi packing tambahan, volume transfer per frame turun dari 6732 byte menjadi 92 byte, atau berkurang 73 kali lipat
- Artefak yang tersisa muncul karena komunikasi LCD dan pemindaian tombol/LED panel berbagi 8 jalur GPIO yang sama
- Implementasi akhir tidak lagi menulis langsung ke LCD, melainkan meminta task multiplexing LCD/panel untuk mengirim data yang diinginkan setelah pemindaian panel selesai, sehingga kerusakan tampilan dapat dihindari
Prosedur akhir dan target analisis yang tersisa
- Prosedur akhir untuk menampilkan video di LCD melalui MIDI adalah sebagai berikut
- login ke shell
- menulis kode eksekusi ke RAM dengan perintah tulis memori shell
- menimpa alamat return di stack untuk mengeksekusi kode RAM
- menyalin task table ke RAM
- memodifikasi agar task table baru saling menunjuk satu sama lain
- mengubah ROM agar menggunakan task table baru
- mengganti callback display task dengan callback idle bawaan
- mengganti callback shell task dengan callback buatan sendiri
- di callback buatan sendiri, unpack data MIDI lalu meneruskannya ke task multiplexing LCD/panel
- memasok frame video melalui MIDI
- Pemahaman tentang wilayah MMIO pada SWL01U masih terbatas, dan DSP yang terpisah dari inti ARM utama juga tetap menjadi target analisis berikutnya
- Materi terkait
1 komentar
Komentar Hacker News
SuperH juga dipakai di Sega 32X, Sega Saturn, dan Sega Dreamcast, serta di beberapa Pocket PC awal seperti HP Jornada
Namun sebagian besar Pocket PC berbasis ARM
Premisnya terdengar sangat tidak masuk akal, jadi mengejutkan bahwa ini benar-benar berhasil dilakukan
Mereka menyebut “optimasi packing lain”; saya penasaran bagaimana frame-nya dikirim
Kalau dot matrix-nya 8 karakter 7x5, totalnya 280 bit, yaitu 40 grup 7-bit per frame, tetapi sepertinya pengirimannya memakai ruang dua kali lipat dari itu
Penasaran apakah ini terbuang karena data kontrol, atau cara transmisinya memang agak kurang optimal
Ditambah header dan footer paket 9 byte
Di artikel sepertinya tertulis 92, tetapi tampaknya itu salah hitung
Mencari cara memakai seluruh 7 bit terlalu sulit, jadi dibandingkan cara aslinya, mereka memilih solusi yang hanya sedikit lebih buruk daripada optimal
Kalau penasaran dengan algoritme tepatnya, kodenya memang belum rapi, tetapi bisa lihat berkas-berkas ini: https://github.com/portasynthinca3/swl01u/blob/master/fun/bi..., https://github.com/portasynthinca3/swl01u/blob/master/fun/ba...
Kalau “tidak punya banyak pengalaman reverse engineering” saja sudah seperti ini, entah orang-orang lain ada di level mana
Tahap 1 adalah masih baru dan antusias tetapi sadar belum tahu; tahap 2 adalah “aku dewa”; tahap 3 adalah fase “aku bodoh”
Disebut “shellcode MIDI pertama di dunia”, tetapi di sebagian besar platform utama, shellcode MIDI sudah ada lebih dari 20 tahun: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=midi
Tentu saja itu SysEx
Dalam MIDI standar, SysEx itu seperti inline assembler di Python
Hampir di dalam semua perangkat MIDI ada hal-hal proprietari yang tidak terdokumentasi tersembunyi
Bayangkan mencolokkan keyboard MIDI lalu memainkan Am6,9/G#, dan jendela terminal dengan hak root terbuka—itu akan keren sekali
Baru-baru ini saya mencari apa yang diperlukan untuk melakukan fuzzing MIDI, dan menemukan materi untuk membuat file .mid, tetapi itu agak berbeda dari yang saya inginkan
Sebagai gantinya, sisi ini tampaknya layak dieksplorasi
Sayang rasanya synthesizer zaman sekarang tampaknya makin jarang memakainya, terutama Roland
Namun Behringer masih mendukungnya cukup baik
Misalnya Deepmind sudah punya rentang MIDI CC yang bagus, dan lewat SysEx hampir 100% bisa diprogram
Riset yang menakjubkan
Ini sedikit mengingatkan pada riset tahun 2017 yang menyintesis shellcode ke dalam molekul DNA/RNA sungguhan dan menunjukkan remote code execution pada perangkat sequencing DNA: https://www.usenix.org/conference/usenixsecurity17/technical...
Tadinya saya mau bilang “berikutnya OSC?”, tetapi tampaknya MIDI masih dominan
Saya menyarankan membaca seluruh artikelnya, tetapi menurut saya kalimat-kalimat intinya kira-kira begini
“Orang-orang gila di [produsen keyboard] ini membuat shell yang berjalan di atas pesan MIDI SysEx di atas USB”
“Perintah yang paling menarik adalah perintah baca/tulis memori arbitrer. Kalau mau, kamu bisa mengintip dan mengutak-atik memori synthesizer lewat MIDI”
“Kalau mau, pesan-pesan ini bisa ditulis ke file MIDI dan diputar di synthesizer seperti file MIDI lain. Hmm, saya jadi terpikir ide bagus…”
“Setelah banyak malam tanpa tidur membedah firmware, saya menemukan fungsi yang mengirim data arbitrer ke controller LCD”
Dalam satu sisi, ini seperti sedikit mengintip mimpi buruk Internet of Things
Hampir perangkat apa pun bisa punya backdoor, bahkan backdoor bodoh seperti #0000
Kehilangan paket itu sepenuhnya normal
Saya penasaran apakah musik MIDI bisa disisipkan di antara perintah Bad Apple agar audionya juga diputar sendiri
README repositori menyebut ada dump image, tetapi sebenarnya tidak ada
Saya penasaran apakah memang begitu seharusnya
Pada detik-detik terakhir saya menambahkan
*.binke.gitignoreuntuk mengecualikan potongan kode yang sudah di-assemble, tetapi sepertinya dump-nya ikut terhapusAkan saya unggah dalam beberapa jam
Dump tersebut kemungkinan dilindungi hak cipta Yamaha, jadi mungkin itu justru keputusan yang baik
Kalau ada pembaca HN yang berada di Armenia, Porta akan memberi presentasi tentang topik ini pada 10 Januari di Hacker Embassy
Sebaiknya datang: https://t.me/hackerembassy/17