ProHoster > Օրագիր > Վարչակազմը > Aigo-ի ինքնագաղտնագրող արտաքին HDD սկավառակի հետ շրջում և կոտրում: Մաս 2. Cypress PSoC-ից աղբավայր վերցնելը
Aigo-ի ինքնագաղտնագրող արտաքին HDD սկավառակի հետ շրջում և կոտրում: Մաս 2. Cypress PSoC-ից աղբավայր վերցնելը
Սա հոդվածի երկրորդ և վերջին մասն է արտաքին ինքնագաղտնագրող կրիչներ կոտրելու մասին։ Հիշեցնեմ, որ վերջերս գործընկերներից մեկն ինձ բերեց Patriot (Aigo) SK8671 կոշտ սկավառակ, և ես որոշեցի հետափոխել այն, և այժմ կիսվում եմ այն, ինչ ստացվել է դրանից: Նախքան հետագա կարդալը, անպայման կարդացեք առաջին մաս հոդվածներ:
4. Մենք սկսում ենք աղբավայր վերցնել ներքին PSoC ֆլեշ կրիչից
Այսպիսով, ամեն ինչ ցույց է տալիս (ինչպես մենք հաստատեցինք [առաջին մասում]()), որ PIN կոդը պահվում է PSoC-ի ֆլեշ խորություններում: Հետեւաբար, մենք պետք է կարդանք այս ֆլեշ խորքերը: Անհրաժեշտ աշխատանքի ճակատ.
գտնել միջոց՝ ստուգելու, թե արդյոք այս «հաղորդակցությունը» պաշտպանված է դրսից կարդալուց.
գտնել պաշտպանությունը շրջանցելու միջոց.
Երկու տեղ կա, որտեղ իմաստ ունի փնտրել վավեր PIN կոդ.
ներքին ֆլեշ հիշողություն;
SRAM, որտեղ կարող է պահվել փին կոդը՝ այն օգտագործողի կողմից մուտքագրված փին կոդի հետ համեմատելու համար:
Նայելով առաջ՝ ես կնշեմ, որ ես դեռ կարողացա վերցնել ներքին PSoC ֆլեշ կրիչը՝ շրջանցելով դրա անվտանգության համակարգը՝ օգտագործելով «սառը բեռնախցիկի հետագծում» կոչվող ապարատային հարձակումը, ISSP արձանագրության չփաստաթղթավորված հնարավորությունները շրջելուց հետո: Սա թույլ տվեց ինձ ուղղակիորեն հեռացնել իրական PIN կոդը:
$ ./psoc.py
syncing: KO OK
[...]
PIN: 1 2 3 4 5 6 7 8 9
«Հաղորդակցությունը» միկրոկոնտրոլերի հետ կարող է նշանակել տարբեր բաներ՝ «վաճառողից մինչև վաճառող» մինչև սերիական արձանագրության միջոցով փոխազդեցություն (օրինակ՝ ICSP Microchip-ի PIC-ի համար):
Cypress-ն ունի դրա համար սեփական սեփականության արձանագրություն, որը կոչվում է ISSP (ներհամակարգային սերիական ծրագրավորման արձանագրություն), որը մասամբ նկարագրված է. տեխնիկական բնութագրում. Արտոնագիր US7185162 տալիս է նաև որոշ տեղեկություններ. Կա նաև OpenSource-ի համարժեք, որը կոչվում է HSSP (մենք կօգտագործենք այն մի փոքր ուշ): ISSP-ն աշխատում է հետևյալ կերպ.
վերաբեռնել PSoC;
թողարկեք կախարդական համարը այս PSoC-ի սերիական տվյալների փինին. արտաքին ծրագրավորման ռեժիմ մտնելու համար;
ուղարկել հրամաններ, որոնք երկար բիթային տողեր են, որոնք կոչվում են «վեկտորներ»:
ISSP փաստաթղթերը սահմանում են այս վեկտորները միայն մի փոքր բուռ հրամանների համար.
Նախաձեռնել-1
Նախաձեռնել-2
Initialize-3 (3V և 5V տարբերակներ)
ID-SETUP
READ-ID-WORD
SET-BLOCK-NUM՝ 10011111010ddddddd111, որտեղ dddddddd=բլոկ #
ՍՈՒՐԲ ՋՆԵԼ
ԾՐԱԳԻՐ-ԲԼՈԿ
ՀԱՍՏԱՏՈՒՄ-ԿԱՐԳԱՎՈՐՈՒՄ
READ-BYTE՝ 10110aaaaaaZDDDDDDDDDZ1, որտեղ DDDDDDDD = տվյալների դուրսբերում, aaaaaa = հասցե (6 բիթ)
WRITE-BYTE. 10010aaaaaaddddddd111, որտեղ dddddddd = տվյալներ են, aaaaaa = հասցե (6 բիթ)
SECURE- ը
ՉԵՔՍՈՒՄ-ԿԱՐԳԱՎՈՐՈՒՄ
READ-CHECKUM: 10111111001ZDDDDDDDDDZ110111111000ZDDDDDDDDZ1, որտեղ DDDDDDDDDDDDDDDDDD = տվյալների դուրս. սարքի ստուգման գումար
Բոլոր վեկտորներն ունեն նույն երկարությունը՝ 22 բիթ: HSSP-ի փաստաթղթերում կան լրացուցիչ տեղեկություններ ISSP-ի վերաբերյալ. «ISSP վեկտորը ոչ այլ ինչ է, քան մի բիթային հաջորդականություն, որը ներկայացնում է հրահանգների մի շարք»:
5.2. Առեղծվածային վեկտորներ
Եկեք պարզենք, թե ինչ է կատարվում այստեղ: Սկզբում ես ենթադրում էի, որ այս նույն վեկտորները M8C հրահանգների չմշակված տարբերակներն են, բայց այս վարկածը ստուգելուց հետո հայտնաբերեցի, որ գործողությունների օպերացիոն կոդերը չեն համընկնում:
Հետո գուգլեցի վերևի վեկտորը և հանդիպեցի այստեղ է մի ուսումնասիրություն, որտեղ հեղինակը, թեև չի մանրամասնում, տալիս է մի քանի օգտակար խորհուրդ. «Յուրաքանչյուր հրահանգ սկսվում է երեք բիթով, որոնք համապատասխանում են չորս մնեմոնիկներից մեկին (կարդալ RAM-ից, գրել RAM-ում, կարդալ ռեգիստր, գրել ռեգիստր): Այնուհետև կա 8 հասցեի բիթ, որին հաջորդում են 8 տվյալների բիթ (կարդալ կամ գրել) և վերջապես երեք կանգառ բիթ»:
Այնուհետև ես կարողացա հավաքել մի քանի շատ օգտակար տեղեկատվություն Վերահսկիչ ROM (SROM) բաժնից: տեխնիկական ձեռնարկ. SROM-ը կոշտ կոդավորված ROM է PSoC-ում, որն ապահովում է օգտակար գործառույթներ (նմանապես Syscall-ի ձևով)՝ օգտվողի տարածքում աշխատող ծրագրի կոդի համար.
00h:SWBootReset
01h: ReadBlock
02h: WriteBlock
03 ժ․ ջնջել արգելափակում
06h: Սեղանի ընթերցում
07h: CheckSum
08h. Calibrate0
09h. Calibrate1
Համեմատելով վեկտորների անունները SROM ֆունկցիաների հետ՝ մենք կարող ենք այս արձանագրության կողմից աջակցվող տարբեր գործառնությունները քարտեզագրել սպասվող SROM պարամետրերին: Դրա շնորհիվ մենք կարող ենք վերծանել ISSP վեկտորների առաջին երեք բիթերը.
100 => «wrem»
101 => «րդմեմ»
110 => «wrreg»
111 => «ռեգեջ»
Այնուամենայնիվ, չիպային գործընթացների ամբողջական պատկերացում կարելի է ստանալ միայն PSoC-ի հետ անմիջական շփման միջոցով:
5.3. Հաղորդակցություն PSoC-ի հետ
Քանի որ Դիրկ Պետրաուցկին արդեն տեղափոխված Cypress-ի HSSP կոդը Arduino-ում, ես օգտագործել եմ Arduino Uno ստեղնաշարի տախտակի ISSP միակցիչին միանալու համար:
Խնդրում ենք նկատի ունենալ, որ իմ հետազոտության ընթացքում ես բավականին փոխեցի Դիրքի կոդը: Դուք կարող եք գտնել իմ փոփոխությունը GitHub-ում. այստեղ և Arduino-ի հետ շփվելու համապատասխան Python սկրիպտը՝ իմ պահոցում cypress_psoc_tools.
Այսպիսով, օգտագործելով Arduino, ես սկզբում օգտագործեցի միայն «պաշտոնական» վեկտորները «հաղորդակցության» համար: Ես փորձեցի կարդալ ներքին ROM-ը, օգտագործելով VERIFY հրամանը: Ինչպես և սպասվում էր, ես չկարողացա դա անել: Հավանաբար այն պատճառով, որ ընթերցման պաշտպանության բիթերը ակտիվացված են ֆլեշ կրիչի ներսում:
Այնուհետև ես ստեղծեցի իմ մի քանի պարզ վեկտորներ հիշողության/գրանցիչների գրելու և կարդալու համար: Խնդրում ենք նկատի ունենալ, որ մենք կարող ենք կարդալ ամբողջ SROM-ը, թեև ֆլեշ կրիչը պաշտպանված է:
5.4. Չիպային ռեգիստրների նույնականացում
«Ապամոնտաժված» վեկտորներին նայելուց հետո ես հայտնաբերեցի, որ սարքն օգտագործում է չփաստաթղթավորված ռեգիստրներ (0xF8-0xFA)՝ նշելու M8C օպերացիոն կոդերը, որոնք ուղղակիորեն կատարվում են՝ շրջանցելով պաշտպանությունը: Սա ինձ թույլ տվեց գործարկել տարբեր օպերացիոն կոդեր, ինչպիսիք են «ADD», «MOV A, X», «PUSH» կամ «JMP»: Նրանց շնորհիվ (դիտելով ռեգիստրների վրա նրանց ունեցած կողմնակի ազդեցությունները) ես կարողացա որոշել, թե չփաստաթղթավորված ռեգիստրներից որոնք են իրականում սովորական ռեգիստրներ (A, X, SP և PC):
Արդյունքում, HSSP_disas.rb գործիքի կողմից ստեղծված «ապամոնտաժված» կոդը այսպիսի տեսք ունի (պարզության համար ես ավելացրել եմ մեկնաբանություններ).
Այս փուլում ես արդեն կարող եմ շփվել PSoC-ի հետ, բայց դեռ վստահելի տեղեկություն չունեմ ֆլեշ կրիչի անվտանգության բիթերի մասին։ Ինձ շատ զարմացրեց այն փաստը, որ Cypress-ը սարքից օգտվողին ոչ մի միջոց չի տրամադրում ստուգելու՝ արդյոք պաշտպանությունն ակտիվացված է։ Ես ավելի խորացա Google-ում, որպեսզի վերջապես հասկանամ, որ Cypress-ի տրամադրած HSSP կոդը թարմացվել է այն բանից հետո, երբ Դիրքը թողարկեց իր փոփոխությունը: Եւ այսպես! Այս նոր վեկտորը հայտնվել է.
Օգտագործելով այս վեկտորը (տես read_security_data psoc.py-ում), մենք ստանում ենք SRAM-ի բոլոր անվտանգության բիթերը 0x80-ով, որտեղ յուրաքանչյուր պաշտպանված բլոկում կա երկու բիթ:
Արդյունքը ճնշող է. ամեն ինչ պաշտպանված է «անջատել արտաքին ընթերցումը և գրելը» ռեժիմում: Հետևաբար, մենք ոչ միայն չենք կարող որևէ բան կարդալ ֆլեշ կրիչից, այլև չենք կարող որևէ բան գրել (օրինակ, այնտեղ ROM-ի ինքնաթափ տեղադրելու համար): Իսկ պաշտպանությունն անջատելու միակ միջոցը ամբողջ չիպն ամբողջությամբ ջնջելն է։ 🙁
6. Առաջին (ձախողված) հարձակումը՝ ROMX
Այնուամենայնիվ, մենք կարող ենք փորձել հետևյալ հնարքը. քանի որ մենք ունենք կամայական օպերացիոն կոդեր գործարկելու հնարավորություն, ինչու՞ չգործարկել ROMX-ը, որն օգտագործվում է ֆլեշ հիշողություն կարդալու համար: Այս մոտեցումը հաջողության լավ հնարավորություն ունի: Քանի որ ReadBlock ֆունկցիան, որը կարդում է տվյալներ SROM-ից (որն օգտագործվում է վեկտորների կողմից), ստուգում է, թե արդյոք այն կանչվում է ISSP-ից: Այնուամենայնիվ, ROMX opcode-ը, հնարավոր է, նման ստուգում չունենա: Այսպիսով, ահա Python կոդը (Arduino կոդին մի քանի օգնական դասեր ավելացնելուց հետո).
for i in range(0, 8192):
write_reg(0xF0, i>>8) # A = 0
write_reg(0xF3, i&0xFF) # X = 0
exec_opcodes("x28x30x40") # ROMX, HALT, NOP
byte = read_reg(0xF0) # ROMX reads ROM[A|X] into A
print "%02x" % ord(byte[0]) # print ROM byte
Ցավոք, այս կոդը չի աշխատում: 🙁 Ավելի ճիշտ այն աշխատում է, բայց մենք ելքի վրա ստանում ենք մեր սեփական օպերացիոն կոդերը (0x28 0x30 0x40): Չեմ կարծում, որ սարքի համապատասխան ֆունկցիոնալությունը ընթերցանության պաշտպանության տարր է։ Սա ավելի շատ նման է ինժեներական հնարքի. արտաքին օպերացիոն կոդերի գործարկման ժամանակ ROM ավտոբուսը վերահղվում է ժամանակավոր բուֆեր:
Սա, ըստ էության, անվանում է SROM ֆունկցիա 0x07, ինչպես ներկայացված է փաստաթղթերում (շեղատառերը իմն են).
Այս ֆունկցիայի ստուգիչ գումարի ստուգում: Այն հաշվարկում է 16-բիթանոց ստուգման գումարը օգտատիրոջ կողմից նշված բլոկների քանակի մեկ ֆլեշ բանկում՝ սկսած զրոյից: BLOCKID պարամետրն օգտագործվում է բլոկների քանակը փոխանցելու համար, որոնք կօգտագործվեն ստուգիչ գումարը հաշվարկելիս: «1» արժեքը կհաշվի միայն ստուգիչ գումարը զրոյի բլոկի համար. մինչդեռ «0»-ը կհանգեցնի ֆլեշ բանկի բոլոր 256 բլոկների ընդհանուր ստուգման գումարի հաշվարկմանը: 16-բիթանոց ստուգման գումարը վերադարձվում է KEY1-ի և KEY2-ի միջոցով: KEY1 պարամետրը պահում է ստուգիչ գումարի ցածր կարգի 8 բիթ, իսկ KEY2 պարամետրը՝ բարձր կարգի 8 բիթ: Մի քանի ֆլեշ բանկ ունեցող սարքերի համար ստուգիչ գումարի ֆունկցիան կանչվում է յուրաքանչյուրի համար առանձին: Բանկի համարը, որով այն կաշխատի, սահմանվում է FLS_PR1 ռեգիստրով (դրա մեջ դնելով թիրախային ֆլեշ բանկին համապատասխան բիթը):
Նկատի ունեցեք, որ սա պարզ ստուգման գումար է. բայթերը պարզապես ավելացվում են մեկը մյուսի հետևից; ոչ մի շքեղ CRC տարօրինակություններ: Բացի այդ, իմանալով, որ M8C միջուկն ունի ռեգիստրների շատ փոքր շարք, ես ենթադրեցի, որ ստուգիչ գումարը հաշվարկելիս միջանկյալ արժեքները կգրանցվեն նույն փոփոխականներում, որոնք, ի վերջո, կգնան դեպի ելք՝ KEY1 (0xF8) / KEY2 ( 0xF9):
Այսպիսով, իմ հարձակումը տեսականորեն այսպիսին է թվում.
Մենք կապում ենք ISSP-ի միջոցով:
Մենք սկսում ենք չեկային գումարի հաշվարկը՝ օգտագործելով CHECKSUM-SETUP վեկտորը:
Մենք վերաբեռնում ենք պրոցեսորը նշված ժամանակից հետո:
Մենք կարդում ենք RAM-ը, որպեսզի ստանանք ընթացիկ ստուգիչ գումարը C:
Կրկնեք 3-րդ և 4-րդ քայլերը՝ ամեն անգամ մի փոքր ավելացնելով T-ն:
Մենք վերականգնում ենք տվյալները ֆլեշ կրիչից՝ հանելով նախորդ ստուգիչ գումարը C ընթացիկից:
Այնուամենայնիվ, խնդիր կա. Initialize-1 վեկտորը, որը մենք պետք է ուղարկենք վերաբեռնումից հետո, վերագրանցում է KEY1 և KEY2:
Այս կոդը վերագրանցում է մեր թանկարժեք ստուգման գումարը՝ զանգահարելով Calibrate1 (SROM ֆունկցիա 9)... Միգուցե մենք պարզապես կարող ենք ուղարկել կախարդական համարը (վերևի կոդի սկզբից) ծրագրավորման ռեժիմ մտնելու համար, իսկ հետո կարդալ SRAM-ը: Եվ այո, այն աշխատում է: Այս հարձակումն իրականացնող Arduino կոդը բավականին պարզ է.
Սպասեք որոշակի ժամանակահատվածի; հաշվի առնելով հետևյալ թակարդները.
Շատ ժամանակ կորցրի, մինչև պարզեցի, թե ինչ է ստացվում հետաձգելՄիկրովայրկյաններ ճիշտ է աշխատում միայն 16383 մկվ-ը չգերազանցող ուշացումներով;
և այնուհետև նորից սպանվեց նույնքան ժամանակ, մինչև ես հայտնաբերեցի, որ հետաձգումըՄիկրովայրկյանները, եթե 0-ը փոխանցվում է դրան որպես մուտքագրում, լիովին սխալ է աշխատում:
Վերագործարկեք PSoC-ը ծրագրավորման ռեժիմում (մենք ուղղակի ուղարկում ենք կախարդական համարը՝ առանց սկզբնավորման վեկտորներ ուղարկելու):
Վերջնական կոդը Python-ում.
for delay in range(0, 150000): # задержка в микросекундах
for i in range(0, 10): # количество считывания для каждойиз задержек
try:
reset_psoc(quiet=True) # перезагрузка и вход в режим программирования
send_vectors() # отправка инициализирующих векторов
ser.write("x85"+struct.pack(">I", delay)) # вычислить контрольную сумму + перезагрузиться после задержки
res = ser.read(1) # считать arduino ACK
except Exception as e:
print e
ser.close()
os.system("timeout -s KILL 1s picocom -b 115200 /dev/ttyACM0 2>&1 > /dev/null")
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=0.5) # открыть последовательный порт
continue
print "%05d %02X %02X %02X" % (delay, # считать RAM-байты
read_regb(0xf1),
read_ramb(0xf8),
read_ramb(0xf9))
Մի խոսքով, ինչ է անում այս կոդը.
Վերագործարկում է PSoC-ը (և ուղարկում է կախարդական համար):
Ուղարկում է ամբողջական սկզբնավորման վեկտորներ:
Կանչում է Arduino ֆունկցիան Cmnd_STK_START_CSUM (0x85), որտեղ ուշացումը միկրովայրկյաններով փոխանցվում է որպես պարամետր:
Կարդում է ստուգիչ գումարը (0xF8 և 0xF9) և 0xF1 չփաստաթղթավորված ռեգիստրը:
Այս կոդը կատարվում է 10 անգամ 1 միկրովայրկյանում։ 0xF1-ը ներառված է այստեղ, քանի որ դա միակ ռեգիստրն էր, որը փոխվեց չեկային գումարը հաշվարկելիս: Թերևս դա ինչ-որ ժամանակավոր փոփոխական է, որն օգտագործվում է թվաբանական տրամաբանական միավորի կողմից: Ուշադրություն դարձրեք այն տգեղ թալանին, որը ես օգտագործում եմ Picocom-ի միջոցով Arduino-ն վերականգնելու համար, երբ Arduino-ն դադարում է կյանքի նշաններ ցույց տալ (պատկերացում չունեմ, թե ինչու):
7.2. Արդյունքը կարդալը
Python-ի սցենարի արդյունքն այսպիսին է թվում (ընթեռնելիության համար պարզեցված).
DELAY F1 F8 F9 # F1 – вышеупомянутый неизвестный регистр
# F8 младший байт контрольной суммы
# F9 старший байт контрольной суммы
00000 03 E1 19
[...]
00016 F9 00 03
00016 F9 00 00
00016 F9 00 03
00016 F9 00 03
00016 F9 00 03
00016 F9 00 00 # контрольная сумма сбрасывается в 0
00017 FB 00 00
[...]
00023 F8 00 00
00024 80 80 00 # 1-й байт: 0x0080-0x0000 = 0x80
00024 80 80 00
00024 80 80 00
[...]
00057 CC E7 00 # 2-й байт: 0xE7-0x80: 0x67
00057 CC E7 00
00057 01 17 01 # понятия не имею, что здесь происходит
00057 01 17 01
00057 01 17 01
00058 D0 17 01
00058 D0 17 01
00058 D0 17 01
00058 D0 17 01
00058 F8 E7 00 # Снова E7?
00058 D0 17 01
[...]
00059 E7 E7 00
00060 17 17 00 # Хмммммм
[...]
00062 00 17 00
00062 00 17 00
00063 01 17 01 # А, дошло! Вот он же перенос в старший байт
00063 01 17 01
[...]
00075 CC 17 01 # Итак, 0x117-0xE7: 0x30
Այսպես ասած, մենք խնդիր ունենք. քանի որ մենք աշխատում ենք փաստացի ստուգիչ գումարով, զրոյական բայթը չի փոխում ընթերցված արժեքը: Այնուամենայնիվ, քանի որ ամբողջ հաշվարկման ընթացակարգը (8192 բայթ) տևում է 0,1478 վայրկյան (յուրաքանչյուր գործարկման ժամանակ աննշան տատանումներով), որը հավասար է մոտավորապես 18,04 մկվ մեկ բայթի համար, մենք կարող ենք օգտագործել այս ժամանակը համապատասխան ժամանակներում ստուգիչ գումարի արժեքը ստուգելու համար: Առաջին գործարկումների համար ամեն ինչ շատ հեշտ է ընթերցվում, քանի որ հաշվարկային ընթացակարգի տևողությունը միշտ գրեթե նույնն է: Այնուամենայնիվ, այս աղբավայրի ավարտը ավելի քիչ ճշգրիտ է, քանի որ յուրաքանչյուր վազքի ժամանակ «փոքր ժամանակի շեղումները» գումարվում են և դառնում էական.
134023 D0 02 DD
134023 CC D2 DC
134023 CC D2 DC
134023 CC D2 DC
134023 FB D2 DC
134023 3F D2 DC
134023 CC D2 DC
134024 02 02 DC
134024 CC D2 DC
134024 F9 02 DC
134024 03 02 DD
134024 21 02 DD
134024 02 D2 DC
134024 02 02 DC
134024 02 02 DC
134024 F8 D2 DC
134024 F8 D2 DC
134025 CC D2 DC
134025 EF D2 DC
134025 21 02 DD
134025 F8 D2 DC
134025 21 02 DD
134025 CC D2 DC
134025 04 D2 DC
134025 FB D2 DC
134025 CC D2 DC
134025 FB 02 DD
134026 03 02 DD
134026 21 02 DD
Դա 10 աղբանոց է յուրաքանչյուր միկրովայրկյան ուշացման համար: Ֆլեշ կրիչի բոլոր 8192 բայթը թափելու ընդհանուր գործառնական ժամանակը կազմում է մոտ 48 ժամ:
7.3. Ֆլեշ երկուական վերակառուցում
Ես դեռ չեմ ավարտել այն կոդը գրելը, որն ամբողջությամբ կվերակառուցի ֆլեշ կրիչի ծրագրային կոդը՝ հաշվի առնելով ժամանակի բոլոր շեղումները։ Այնուամենայնիվ, ես արդեն վերականգնել եմ այս կոդի սկիզբը։ Համոզվելու համար, որ ես դա ճիշտ եմ արել, ես այն ապամոնտաժեցի՝ օգտագործելով m8cdis.
0000: 80 67 jmp 0068h ; Reset vector
[...]
0068: 71 10 or F,010h
006a: 62 e3 87 mov reg[VLT_CR],087h
006d: 70 ef and F,0efh
006f: 41 fe fb and reg[CPU_SCR1],0fbh
0072: 50 80 mov A,080h
0074: 4e swap A,SP
0075: 55 fa 01 mov [0fah],001h
0078: 4f mov X,SP
0079: 5b mov A,X
007a: 01 03 add A,003h
007c: 53 f9 mov [0f9h],A
007e: 55 f8 3a mov [0f8h],03ah
0081: 50 06 mov A,006h
0083: 00 ssc
[...]
0122: 18 pop A
0123: 71 10 or F,010h
0125: 43 e3 10 or reg[VLT_CR],010h
0128: 70 00 and F,000h ; Paging mode changed from 3 to 0
012a: ef 62 jacc 008dh
012c: e0 00 jacc 012dh
012e: 71 10 or F,010h
0130: 62 e0 02 mov reg[OSC_CR0],002h
0133: 70 ef and F,0efh
0135: 62 e2 00 mov reg[INT_VC],000h
0138: 7c 19 30 lcall 1930h
013b: 8f ff jmp 013bh
013d: 50 08 mov A,008h
013f: 7f ret
Միանգամայն հավանական է թվում:
7.4. Գտեք PIN կոդի պահպանման հասցեն
Այժմ, երբ մենք կարող ենք կարդալ ստուգիչ գումարը մեզ անհրաժեշտ ժամանակներում, մենք հեշտությամբ կարող ենք ստուգել, թե ինչպես և որտեղ է այն փոխվում, երբ մենք.
մուտքագրեք սխալ PIN կոդը;
փոխել փին կոդը:
Նախ՝ պահեստավորման մոտավոր հասցեն գտնելու համար, ես վերագործարկումից հետո 10 ms-ի չափով ցուցիչ վերցրեցի: Հետո ես սխալ PIN մուտքագրեցի և արեցի նույնը:
Արդյունքն այնքան էլ հաճելի չէր, քանի որ փոփոխությունները շատ էին։ Բայց վերջում ես կարողացա որոշել, որ ստուգման գումարը փոխվել է ինչ-որ տեղ 120000 մկվ-ի և 140000 մկվ ուշացման միջև: Բայց «փինկոդը», որը ես ցուցադրեցի այնտեղ, ամբողջովին սխալ էր՝ delayMicroseconds ընթացակարգի արտեֆակտի պատճառով, որը տարօրինակ բաներ է անում, երբ 0 փոխանցվում է դրան:
Այնուհետև, գրեթե 3 ժամ անցկացնելուց հետո, ես հիշեցի, որ SROM համակարգի կանչը CheckSum-ը ստանում է արգումենտ որպես մուտքագրում, որը նշում է չեկային գումարի բլոկների քանակը: Դա. մենք հեշտությամբ կարող ենք տեղայնացնել PIN կոդի պահպանման հասցեն և «սխալ փորձերի» հաշվիչը՝ մինչև 64 բայթ բլոկի ճշգրտությամբ:
Իմ նախնական վազքերը տվեցին հետևյալ արդյունքը.
Այնուհետև ես փոխեցի PIN կոդը «123456»-ից «1234567» և ստացա.
Այսպիսով, PIN կոդը և սխալ փորձերի հաշվիչը կարծես թե պահված են թիվ 126 բլոկում։
7.5. Թիվ 126 բլոկի աղբավայր վերցնելը
Թիվ 126 բլոկը պետք է տեղակայվի ինչ-որ տեղ 125x64x18 = 144000 μվ-ի սահմաններում, ստուգիչ գումարի հաշվարկի սկզբից, իմ ամբողջական աղբավայրում, և դա բավականին հավանական է թվում: Այնուհետև, բազմաթիվ անվավեր աղբավայրերը ձեռքով մաղելուց հետո («ժամանակային փոքր շեղումների» կուտակման պատճառով), ես ստացա այս բայթերը (145527 μs ուշացումով).
Ակնհայտ է, որ PIN կոդը պահվում է չգաղտնագրված ձևով: Այս արժեքները, իհարկե, գրված չեն ASCII կոդերով, սակայն, ինչպես պարզվում է, դրանք արտացոլում են կոնդենսիվ ստեղնաշարից վերցված ընթերցումները։
Ի վերջո, ես անցկացրի ևս մի քանի թեստեր՝ գտնելու, թե որտեղ է պահվել վատ փորձերի հաշվիչը: Ահա արդյունքը.
0xFF - նշանակում է «15 փորձ» և յուրաքանչյուր անհաջող փորձի հետ այն նվազում է:
Խնդրում ենք նկատի ունենալ, որ իմ օգտագործած ուշացման արժեքները, ամենայն հավանականությամբ, կապված են մեկ կոնկրետ PSoC-ի հետ՝ այն, ինչ ես օգտագործել եմ:
8. Ի՞նչ է հաջորդը:
Այսպիսով, եկեք ամփոփենք PSoC-ի կողմը, մեր Aigo դրայվի համատեքստում.
մենք կարող ենք կարդալ SRAM, նույնիսկ եթե այն կարդացվում է պաշտպանված;
Մենք կարող ենք շրջանցել սահահարման դեմ պաշտպանությունը՝ օգտագործելով սառը բեռնման հետքի հարձակումը և ուղղակիորեն կարդալով PIN կոդը:
Այնուամենայնիվ, մեր հարձակումը որոշ թերություններ ունի համաժամացման խնդիրների պատճառով: Այն կարող է բարելավվել հետևյալ կերպ.
գրել կոմունալ ելքային տվյալները, որոնք ստացվել են «սառը բեռնման հետքի» հարձակման արդյունքում ճիշտ վերծանելու համար.
օգտագործել FPGA հարմարանք՝ ավելի ճշգրիտ ժամանակային ուշացումներ ստեղծելու համար (կամ օգտագործել Arduino ապարատային ժամանակաչափեր);
փորձեք մեկ այլ հարձակում. մուտքագրեք դիտավորյալ սխալ PIN կոդը, վերագործարկեք և թափեք RAM-ը՝ հուսալով, որ ճիշտ PIN կոդը կպահվի RAM-ում՝ համեմատության համար: Այնուամենայնիվ, դա այնքան էլ հեշտ չէ անել Arduino-ում, քանի որ Arduino ազդանշանի մակարդակը 5 վոլտ է, մինչդեռ մեր ուսումնասիրած տախտակն աշխատում է 3,3 վոլտ ազդանշաններով:
Հետաքրքիր մի բան, որը կարելի է փորձել, դա լարման մակարդակի հետ խաղալն է՝ կարդալու պաշտպանությունը շրջանցելու համար: Եթե այս մոտեցումը աշխատեր, մենք կկարողանայինք բացարձակապես ճշգրիտ տվյալներ ստանալ ֆլեշ կրիչից՝ ոչ ճշգրիտ ժամանակի ուշացումներով ստուգիչ գումար կարդալու փոխարեն:
Քանի որ SROM-ը հավանաբար կարդում է պահակային բիթերը ReadBlock համակարգի զանգի միջոցով, մենք կարող ենք անել նույնը, ինչ նկարագրված է Դմիտրի Նեդոսպասովի բլոգում` կոնֆերանսում հայտարարված Քրիս Գերլինսկու հարձակման կրկնակի իրականացում. «Recon Brussels 2017».
Մեկ այլ զվարճալի բան, որ կարելի է անել, դա չիպից հանելն է. վերցնել SRAM-ի աղբարկղ, բացահայտել չփաստաթղթավորված համակարգի զանգերն ու խոցելիությունները:
9. Եզրակացություն
Այսպիսով, այս սկավառակի պաշտպանությունը շատ ցանկալի է թողնում, քանի որ այն օգտագործում է սովորական (ոչ «կարծրացված») միկրոկոնտրոլեր PIN կոդը պահելու համար... Բացի այդ, ես (դեռևս) չեմ նայել, թե ինչպես են գործերը ընթանում տվյալների հետ: գաղտնագրում այս սարքում:
Ի՞նչ խորհուրդ կտաք Aigo-ին: Կոդավորված HDD կրիչների մի քանի մոդել վերլուծելուց հետո ես 2015թ ներկայացում SyScan-ի վրա, որտեղ նա ուսումնասիրեց մի քանի արտաքին HDD կրիչների անվտանգության խնդիրները և առաջարկություններ արեց, թե ինչ կարող է բարելավվել դրանցում: 🙂
Ես անցկացրել եմ երկու հանգստյան օրեր և մի քանի երեկո այս հետազոտությունն անելով: Ընդհանուր մոտ 40 ժամ։ Հաշվում հենց սկզբից (երբ ես բացեցի սկավառակը) մինչև վերջ (PIN կոդի աղբանոց): Նույն 40 ժամը ներառում է այն ժամանակը, որը ես ծախսեցի այս հոդվածը գրելու համար: Շատ հուզիչ ճամփորդություն էր: