
Saya punya teman yang bergerak dalam perbaikan besi otomotif. Dia entah bagaimana membawakan saya mikrokontroler yang disolder dari unit kontrol pemanas otonom. Dia mengatakan bahwa programmer-nya tidak mengambilnya, dan dia ingin dapat mentransfer firmware bolak-balik, karena ada banyak balok, di besi mereka sering sama, tetapi unit yang mereka kontrol berbeda. Dan tampaknya ada blok bukan yang salah, tetapi perangkat lunaknya berbeda dan Anda tidak bisa menggantinya. Karena tugas itu menarik, saya memutuskan untuk mencari-cari. Jika topiknya menarik bagi Anda, silakan, di bawah ...
Subjek adalah M306N5FCTFP. Ini adalah mikrokontroler dari grup M16C / 6N5. Inti M16C / 60 dikembangkan oleh Mitsubishi, dan sebagai Sejak 2003, penerus perusahaan ini dalam hal MK adalah Renesas, sekarang mikrokontroler ini dikenal dengan merek ini.
Sedikit tentang mikrokontroler itu sendiri
Kerikil adalah mikrokontroler 16-bit dalam paket QFP 100-pin. Kernel memiliki 1 MB ruang alamat, frekuensi clock 20 MHz untuk kinerja otomotif. Perangkat periferal juga sangat luas: dua timer 16-bit dan kemungkinan menghasilkan PWM 3-fase untuk mengendalikan motor, segala macam UART, SPI, I2C secara alami, 2 saluran DMA, terdapat pengontrol CAN2.0B bawaan, serta PLL. Menurut saya itu sangat baik untuk orang tua itu. Berikut ini adalah bagan ikhtisar dari dokumentasi:

Karena tugas saya adalah menghapus perangkat lunak, itu juga sangat tertarik pada memori. MK ini diproduksi dalam dua versi: bertopeng dan Flash. Saya mendapatkan, seperti yang disebutkan di atas, M306N5FCTFP. Tentang dia, deskripsi mengatakan sebagai berikut:
- Versi memori flash
- 128 KBytes + 4K (tambahan 4K - yang disebut blok A sebagai hadiah kepada pengguna untuk menyimpan data, tetapi juga dapat menyimpan program)
- V-ver. (versi otomotif dengan kisaran + 125 ° C)
Cara menarik dari perangkat apa yang diseret pengembang
Wajar jika Anda mulai mencoba mendapatkan sesuatu dari mikrokontroler dengan mempelajari mekanisme yang diintegrasikan oleh pengembang chip untuk tugas pemrograman memori. Manual menyatakan bahwa pabrikan dengan baik hati menempatkan bootloader di dalam memori untuk kebutuhan pemrograman dalam-rangkaian perangkat.

Seperti yang dapat Anda lihat dari gambar di atas, memori dibagi menjadi 2 bagian: area pengguna, dan area bootloader. Pada yang kedua, bootloader default dimuat dari pabrik, yang dapat menulis, membaca, menghapus memori pengguna dan berkomunikasi melalui antarmuka asinkron, sinkron, atau BISA. Diindikasikan dapat ditulis ulang untuk Anda sendiri, atau tidak dapat ditulis ulang. Pada akhirnya, ini mudah diverifikasi dengan mencoba mengetuk bootloader standar setidaknya melalui UART ... Ke depan: produsen pemanas tidak repot-repot dengan bootloader-nya, sehingga Anda dapat menggali lebih jauh ke arah ini. Segera lakukan pemesanan bahwa masih ada metode pemrograman paralel, tetapi sejak itu Saya tidak memiliki programmer untuk ini, saya tidak mempertimbangkan opsi ini.
Memasuki mode operasi bootloader disediakan oleh kombinasi tertentu pada input CNVSS, P5_0, P5_5 selama pengaturan ulang perangkat keras. Selanjutnya, tulis utilitas Anda sendiri untuk menyalin isi memori, atau gunakan yang sudah jadi. Renesas menyediakan utilitas sendiri, yang disebut "M16C Flash Starter," tetapi memiliki fungsi baca yang berkurang. Itu tidak menyimpan apa yang dibaca ke disk, tetapi membandingkannya dengan file dari disk. Yaitu sebenarnya, ini bukan bacaan, tetapi verifikasi. Namun, ada utilitas gratis Jerman bernama M16C-Flasher, yang dapat membaca firmware. Secara umum, toolkit awal diambil.
Tentang perlindungan baca

Semuanya akan sangat sederhana jika bootloader tidak memberikan perlindungan terhadap akses tidak sah. Saya hanya akan memberikan terjemahan yang sangat gratis dari manual.
Fungsi Verifikasi ID
Digunakan dalam mode pertukaran serial dan CAN. Pengenal yang dikirimkan oleh programmer dibandingkan dengan pengenal yang direkam dalam memori flash. Jika pengidentifikasi tidak cocok, perintah yang dikirim oleh programmer tidak diterima. Namun, jika 4 byte dari vektor reset FFFFFFFFh, pengidentifikasi tidak dibandingkan, yang memungkinkan semua perintah dieksekusi. Pengenal adalah 7 byte yang disimpan secara berurutan, mulai dari byte pertama, di alamat 0FFFDFh, 0FFFE3h, 0FFFEBh, 0FFFEFh, 0FFFF3h, 0FFFF7h, dan 0FFFFBh.Jadi, untuk mengakses program, Anda perlu mengetahui 7 byte yang dihargai. Sekali lagi, melihat ke depan, saya terhubung ke MK menggunakan "M16C Flash Starter" yang sama dan memastikan bahwa kombinasi nol dan FF tidak berfungsi dan masalah ini harus dipecahkan entah bagaimana. Sebuah ide dengan serangan melalui saluran pihak ketiga segera muncul di sini. Saya sudah mulai berpura-pura menjadi jilbab di kepala saya, yang memungkinkan saya untuk mengukur arus di sirkuit daya, tetapi memutuskan bahwa internet itu besar dan sebagian besar sepeda sudah ditemukan. Setelah mendorong beberapa pencarian, saya dengan cepat menemukan di hackaday.io proyek Serge 'q3k' Bazanski, berjudul "Reverse engineering Toshiba R100 BIOS". Dan dalam kerangka kerja proyek ini, penulis pada dasarnya memecahkan masalah yang sama persis: mengekstraksi firmware dari MK M306K9FCLR. Apalagi - pada saat itu tugasnya sudah berhasil diselesaikan olehnya. Di satu sisi, saya sedikit kesal - sebuah teka-teki yang menarik tidak diselesaikan oleh saya. Di sisi lain, tugas berubah dari pencarian kerentanan, menjadi eksploitasi, yang menjanjikan solusi yang jauh lebih cepat.
Singkatnya, q3k, dengan logika yang persis sama, memulai penelitian dengan analisis konsumsi saat ini, dalam hal ini itu dalam kondisi yang jauh lebih menguntungkan, karena dia punya ChipWhisperer, aku masih belum mendapatkan benda ini. Tapi sejak itu penyelidikan pertamanya untuk menghapus konsumsi saat ini ternyata tidak sesuai dan dia tidak bisa mengisolasi sesuatu yang berguna dari kebisingan, dia memutuskan untuk mencoba serangan sederhana pada waktu respons. Faktanya adalah bahwa bootloader menarik output SIBUK selama pelaksanaan perintah untuk memberi tahu tuan rumah bahwa ia sibuk atau siap untuk menjalankan perintah berikutnya. Menurut asumsi q3k, mengukur waktu dari mentransmisikan bit terakhir dari pengidentifikasi untuk menghapus bendera yang sibuk dapat berfungsi sebagai sumber informasi selama enumerasi. Saat memeriksa asumsi ini dengan menghitung byte pertama kunci, penyimpangan waktu hanya ditemukan dalam satu kasus - ketika byte pertama sama dengan FFh. Untuk kenyamanan mengukur waktu, penulis bahkan memperlambat MK dengan mematikan resonator kuarsa dan menerapkan gelombang persegi 666 kHz ke input jam untuk menyederhanakan prosedur pengukuran. Setelah itu, pengidentifikasi berhasil dipilih dan perangkat lunak diambil.
Pancake pertama - garu
Ha! Saya pikir ... Sekarang saya dengan cepat memusatkan program ke STM32VLDiscovery c STM32F100 saya, yang akan mengirim kode dan mengukur waktu respons, dan memuntahkan hasil pengukuran di terminal. Karena Papan tempat memotong roti dengan pengontrol target sebelumnya terhubung ke PC melalui adaptor USB-UART, agar tidak mengubah apa pun di papan tempat memotong roti, kami akan bekerja dalam mode asinkron.

Ketika pada bootloader mulai, input CLK1 ditarik ke tanah, ia menyadari bahwa mereka menginginkan komunikasi asinkron darinya. Itu sebabnya saya menggunakannya - suspender sudah disolder dan saya hanya menghubungkan dua papan dengan kabel: Discovery dan papan tempat memotong roti dengan target M306.
Catatan tentang harmonisasi level:
Karena Karena M16 memiliki level TTL pada terminal, dan STM32 memiliki LVTTL (disederhanakan, lihat datasheet untuk detail), maka pencocokan level diperlukan. Karena ini bukan perangkat yang, seperti baterai terkenal, harus bekerja, bekerja dan bekerja, tetapi pada kenyataannya itu menghubungkan sekali di atas meja, maka saya tidak repot-repot dengan penerjemah level: MK lima volt mencerna level output dari STM32, dalam arti 3 volt yang dirasakannya sebagai "1" , output dari M16 diumpankan ke input STM32 toleran 5V sehingga tidak terasa buruk, dan kami tidak lupa untuk meletakkan kaki yang menarik RESET M16 ke mode drain terbuka. Saya lupa, dan ini + 2 jam untuk celengan waktu yang hilang.
Minimal ini cukup untuk memahami kelenjar satu sama lain.Logika dari perangkat lunak penyerang adalah sebagai berikut:
- Kami membuat koneksi dengan controller. Untuk melakukan ini, Anda harus menunggu hingga reset selesai, kemudian mengirimkan 16 karakter nol dengan interval lebih dari 20 ms. Ini untuk mengetahui algoritma untuk secara otomatis menentukan nilai tukar, karena antarmuka asinkron, dan MK tidak tahu apa-apa tentang frekuensinya. Kecepatan awal pemancar harus 9600 baud, pada kecepatan inilah penghitung loader menghitung. Setelah itu, jika diinginkan, Anda dapat meminta nilai tukar yang berbeda dari lima yang tersedia di kisaran 9600-115200 (walaupun dalam kasus saya loader menolak untuk bekerja pada 115200). Saya tidak perlu mengubah kecepatan, jadi saya hanya meminta versi bootloader untuk mengontrol sinkronisasi. Kami melewati FBh, loader merespons dengan garis seperti "VER.1.01".
- Kami mengirim perintah "membuka", yang berisi iterasi kunci saat ini, dan mengukur waktu sampai bendera sibuk dihapus.

Perintah ini terdiri dari kode F5h, tiga byte alamat di mana area pengenal dimulai (dalam kasus saya, untuk kernel M16C, 0FFFDFh), panjang (07h), dan pengidentifikasi itu sendiri.
- Kami mengukur waktu antara pengiriman bit terakhir dari pengidentifikasi dan penghapusan bendera yang sibuk.
- Kami meningkatkan byte kunci yang sedang diurutkan (KEY1 pada tahap awal), kami kembali ke langkah 2 hingga kami menyortir semua nilai 255 dari byte saat ini.
- Kami mereset statistik ke terminal (baik, atau kami melakukan analisis "di papan").
Untuk berkomunikasi dengan target MK, saya menggunakan USART di STM32, untuk mengukur waktu - timer dalam mode Capture Input. Satu-satunya hal, untuk kesederhanaan, saya tidak mengukur waktu antara bit terakhir dari kunci dan penghapusan bendera, tetapi antara awal transmisi dan bendera. Alasannya adalah bahwa bit terakhir bisa berubah, dan dalam mode asinkron tidak ada yang bisa dilampirkan ke input pengambilan. Pada saat yang sama, UART adalah perangkat keras dan waktu transmisi pada dasarnya identik dan tidak boleh ada kesalahan nyata.
Akibatnya, untuk semua nilai, hasilnya identik. Sama sekali identik. Frekuensi jam dari timer adalah 24 MHz, masing-masing, resolusi waktu adalah 41,6 ns. Baiklah, ok, saya mencoba memperlambat target MK. Tidak ada yang berubah. Di sini muncul pertanyaan di kepala saya: apa yang saya lakukan salah, seperti yang dilakukan q3k? Setelah perbandingan, perbedaannya ditemukan: ia menggunakan antarmuka pertukaran sinkron (SPI), dan saya tidak sinkron (UART). Dan di suatu tempat di sini, saya menarik perhatian pada momen yang saya lewatkan di awal. Bahkan pada diagram pengkabelan untuk mode bootloader sinkron dan asinkron, output yang siap disebutkan secara berbeda:

Dalam sinkron itu adalah "SIBUK", di asinkron itu adalah "Monitor". Kami melihat tabel “Fungsi Output dalam Mode I / O Seri Serial”:
"Semyon Semenych ..."Sepele, yang awalnya terlewatkan, membawa tempat yang salah. Sebenarnya, jika dalam mode sinkron ini persis flag bootloader sibuk, maka dalam mode asinkron (yang serial I / O mode 2) hanyalah "tanda bahayanya" untuk menunjukkan operasi. Mungkin, secara umum, sinyal perangkat keras kesiapan transceiver, dan karenanya keakuratan yang luar biasa.
Secara umum, kami menyolder resistor pada pin SCLK dari tanah ke VCC, menyolder kawat di sana, menghubungkan semuanya ke SPI dan memulai ...
Sukses!

Dalam mode sinkron, semuanya hampir sama, hanya tidak ada prosedur awal untuk membuat koneksi yang diperlukan, sinkronisasi disederhanakan, dan penangkapan waktu dapat dilakukan lebih akurat. Jika saya segera memilih mode ini, saya akan menghemat waktu ... Saya sekali lagi tidak menyulitkan dan mengukur waktu dari bit terakhir, tetapi memulai timer sebelum memulai transfer byte terakhir kunci, yaitu. kita menyalakan timer dan mengirimkannya ke pemancar KEY7 (pada tangkapan layar di atas, dari penganalisa logika, Anda dapat melihat jarak antara kursor. Ini adalah interval waktu yang diukur).
Ini lebih dari cukup untuk identifikasi yang sukses. Berikut adalah penghitungan satu byte:

Pada sumbu x, kami memiliki jumlah jumlah diskrit, pada sumbu y, masing-masing, nilai kunci yang dikirimkan. Rasio signal-to-noise sedemikian rupa sehingga bahkan tidak ada filter yang diperlukan, sama seperti di sekolah dalam pelajaran informatika: kami menemukan maksimum dalam array dan pergi ke pemilihan byte berikutnya. 6 byte pertama dipilih dengan mudah dan cepat, sedikit lebih sulit dengan yang terakhir: itu hanya penghilang kurang ajar yang tidak bekerja, Anda perlu mengatur ulang "korban" sebelum setiap upaya. Akibatnya, dibutuhkan sekitar 400 ms untuk setiap upaya, dan pencarian dalam kasus terburuk, di wilayah satu setengah menit. Tapi ini yang terburuk. Setelah setiap upaya, kami meminta status dan, segera setelah kami menebak, berhenti. Pada awalnya, saya biasanya hanya dengan cepat pergi ke pengenal dengan pena, memasukkan output konsol ke excel dan merencanakan grafik, terlebih lagi karena itu adalah tugas satu kali, tetapi untuk artikel saya memutuskan untuk menambahkan iterasi otomatis, demi konsol yang indah ...

Tentu saja, jika pengembang menghapus bootloader (diganti dengan miliknya sendiri), itu tidak akan mudah untuk keluar, tetapi dalam elektronik otomotif, MK sering tidak ditutup sama sekali. Secara khusus, di unit kontrol dari pemanas lain, di mana V850 dari Renesas yang sama dipasang, semuanya diputuskan dengan menyolder sepasang kabel dan menyalin firmware dengan utilitas standar. Ini adalah seluruh mesin cryptocurrency di dunia ECU. Rupanya produsen tidak menyukai fenomena tuning chip dan jenis gangguan lainnya ... Meskipun ini seperti perlombaan baju besi dan kerang - kelenjar lebih curam, lebih mahal, tetapi tidak ada pemenang ...
Referensi:
- https://www.dataman.com/media/datasheet/Renesas/M16C6N5Group.pdf
- https://hackaday.io/project/723-reverse-engineering-toshiba-r100-bios/log/51302-ec-firmware-dumped
- https://q3k.org/slides-recon-2018.pdf