3 poin oleh GN⁺ 2025-01-06 | 1 komentar | Bagikan ke WhatsApp
  • 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 0x3f0f0f0f dan 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 login serta 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 SWL01U dengan label DMLCD
  • 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 TESTN dan PROTN untuk memeriksa perubahan mode boot
    • menyolder ke pin UART Tx untuk memeriksa output
    • membaca kode identifikasi chip lewat JTAG
    • melepas chip flash untuk dump firmware
  • Saat TESTN diaktifkan, synthesizer tidak mau boot, dan PROTN tidak 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 arm7tdmi di 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 alamat 0 dibaca lewat GDB, terlihat instruksi lompat berbentuk ldr pc, [pc, #24]
  • Setelah 16MiB data di-dump dari alamat 0 dan dibuka di Cutter, string tampak berulang setiap 64KiB
    • contoh: SWL01U Internal berulang di 0x0000bfd0, 0x0001bfd0, 0x0002bfd0, dan seterusnya
  • 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
    • GrandPno
    • Tr1 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

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, dan ver terkumpul 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 login serta Passwd 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 login dimasukkan, keluar passwd?
    • saat kata sandi #0000 dimasukkan, keluar login OK
    • setelah itu, perintah dapat dijalankan
  • Perintah shell yang teridentifikasi mencakup
    • logout, help, ?, info, ver
    • stack, perf-on, perf-off, perf-disp
    • d, dp, d xxxxx, d/s xxxxx
    • m ADDRESS DATA, m/b ADDRESS DATA, m/w ADDRESS DATA, m/l ADDRESS DATA
  • Perintah info mengembalikan informasi berikut
    • DevelopName PSR-E433
    • DevelopNumber #3341
    • Main DevelopNumber #3341
    • Make data & time MAY 16 2012 19:00:57
    • J/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
  • Pesan MIDI SysEx dimulai dengan 0xF0, melewati manufacturer ID dan payload, lalu berakhir dengan 0xF7, dan payload hanya boleh berisi byte dengan MSB 0
  • 0x43 pada 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\r melakukan 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 HeloWrld pada 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

 
GN⁺ 2025-01-06
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

    • Chip ini juga banyak dipakai di industri, dan Mitsubishi menggunakannya pada ECU beberapa kendaraan, termasuk Lancer Evolution
  • 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

    • Dot matrix-nya sebenarnya 8 karakter 5x8, jadi total 320 bit, dan 320 bit ini dipacking ke 4 bit per byte yang bisa dipakai dalam protokol shell
      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

    • Menyadari bahwa kamu tahu banyak tetapi tidak tahu apa-apa rasanya seperti sekitar tahap 4 pengalaman
      Tahap 1 adalah masih baru dan antusias tetapi sadar belum tahu; tahap 2 adalah “aku dewa”; tahap 3 adalah fase “aku bodoh”
    • Terutama insinyur nonprofesional yang sangat berbakat sering mengatakan hal seperti ini
  • 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

    • Ada banyak buffer overflow, tetapi apakah ada orang yang benar-benar menulis shellcode untuk kerentanan-kerentanan itu adalah persoalan lain
  • 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

    • Akan bagus kalau bisa memicu remote code execution dengan memainkan sebuah lagu
      Bayangkan mencolokkan keyboard MIDI lalu memainkan Am6,9/G#, dan jendela terminal dengan hak root terbuka—itu akan keren sekali
    • Saya menantikan hack SysEx macam apa yang akan diselipkan Google ke dukungan MIDI Chrome yang mereka bangun beberapa tahun terakhir
    • Saya sama sekali tidak tahu ada dunia seperti ini
      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
    • SysEx itu luar biasa
      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”

    • Pertanyaan sebenarnya sekarang adalah apakah kode yang berjalan di keyboard bisa diubah sehingga, ketika keyboard lain dengan model yang sama menerima data MIDI ini, ia akan mencoba menginfeksi
      Dalam satu sisi, ini seperti sedikit mengintip mimpi buruk Internet of Things
      Hampir perangkat apa pun bisa punya backdoor, bahkan backdoor bodoh seperti #0000
    • Kalau ini diputar seperti file MIDI, hasilnya mungkin terdengar seperti dubstep
    • Pernyataan bahwa memori synthesizer bisa dibaca dan ditulis lewat MIDI terdengar mudah, tetapi SysEx tidak punya jaminan pengiriman dan tidak ada konsep koneksi atau sesi, jadi bisa membuat frustrasi
      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

    • Itu kesalahan
      Pada detik-detik terakhir saya menambahkan *.bin ke .gitignore untuk mengecualikan potongan kode yang sudah di-assemble, tetapi sepertinya dump-nya ikut terhapus
      Akan saya unggah dalam beberapa jam
    • Sepertinya begitu
      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