ProHoster > Blog > Administrazioa > Aigo autoenkriptatutako kanpoko HDD diskoa alderantzikatu eta hackeatzea. 2. zatia: Cypress PSoC-tik zabortegi bat hartzea
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
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
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
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):
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:
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.
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:
ISSP bidez konektatzen gara.
Checksumaren kalkulua hasten dugu CHECKSUM-SETUP bektorea erabiliz.
T denbora zehatz baten ondoren prozesadorea berrabiaraziko dugu.
RAM irakurtzen dugu uneko C checksuma lortzeko.
Errepikatu 3. eta 4. urratsak, aldi bakoitzean T pixka bat handituz.
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:
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:
PSoC berrabiarazten du (eta zenbaki magiko bat bidaltzen dio).
Hasierako bektore osoak bidaltzen ditu.
Arduino Cmnd_STK_START_CSUM (0x85) funtzioari deitzen dio, non mikrosegundoetako atzerapena parametro gisa pasatzen den.
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):
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:
Ondoren, PIN kodea "123456"tik "1234567"ra aldatu nuen eta lortu nuen:
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):
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:
0xFF - "15 saiakera" esan nahi du eta huts egiten duen saiakera bakoitzean gutxitzen da.
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.