25.08.2013 Views

Rezumat teza - Universitatea Tehnic?

Rezumat teza - Universitatea Tehnic?

Rezumat teza - Universitatea Tehnic?

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

FACULTATEA DE ELECTRONICǍ, TELECOMUNICAŢII ŞI TEHNOLOGIA INFORMAŢIEI<br />

mat. Petrean Liviu<br />

TEZĂ DE DOCTORAT<br />

- REZUMAT -<br />

Securitatea Aplicaţiilor de Calculator – Contribuţii la Protecţia<br />

Fişierelor Executabile<br />

Comisia de evaluare a tezei de doctorat:<br />

1<br />

Conducător ştiinţific,<br />

Prof.dr.ing.Gavril Toderean<br />

PREŞEDINTE: - Prof.dr.ing. Tudor Palade, Prodecan, <strong>Universitatea</strong> <strong>Tehnic</strong>ă din Cluj-Napoca<br />

MEMBRI: - Prof.dr.ing. Gavril Toderean, Conducător ştiinţific, <strong>Universitatea</strong> <strong>Tehnic</strong>ă din<br />

Cluj-Napoca<br />

- Prof.dr.ing. Ionel Jian, Referent, <strong>Universitatea</strong> “Politehnica” din Timişoara<br />

- Prof.dr.ing. Nicolae Tomai, Referent, <strong>Universitatea</strong> “Babeş-Bolyai”, Cluj-Napoca<br />

- Conf.univ.dr. Ştefan Oniga, Referent, <strong>Universitatea</strong> de Nord din Baia Mare


Listă de abrevieri, simboluri şi denumiri<br />

API = Application Programming Interface, seturi de cod puse la dispoziţia programatorilor de către<br />

sistemul de operare sau diferitele medii de programare;<br />

BMS = Bit/Byte Most Significant, cel mai semnificativ bit al unui octet sau cel mai semnificativ octet al<br />

unui cuvânt;<br />

Cracker = persoană care se ocupă cu spartul parolelor, modificarea codului fişierelor executabile şi<br />

publicarea acestor modificări pe internet;<br />

Cracking = operaţia de spargere a unei parole sau de modificare a codului unui fişier executabil;<br />

DLL = Dynamic Link Library, fişiere librărie ale sistemelor de operare Microsoft Windows importate la<br />

rularea fişierelor executabile;<br />

EAT = Export Address Table, tabela de exporturi a unui fişier executabil;<br />

ENT = Export Name Table, tabela de exporturi după nume a unui fisier executabil;<br />

EOT = Export Ordinal Table, tabela de exporturi după număr ordinal a unui fişier executabil;<br />

IAT = Import Address Table, tabela cu adresele importurilor unui fişier executabil;<br />

PE = Portable Executable, fişier executabil, cu extensia .EXE, .DLL sau .OCX<br />

2


CUPRINS<br />

Pagina<br />

Teza <strong>Rezumat</strong><br />

1. Introducere………………………………………………………………….......................... 3 5<br />

1.1 Obiective de cercetare…………………………………………………............................ 3 5<br />

1.2 Structura tezei..................................................................................................................... 4 6<br />

2. Stadiul actual al securităţii aplicaţiilor de calculator........................................................... 6 8<br />

2.1 Situaţia actuală a pirateriei aplicaţiilor de calculator......................................................... 6 8<br />

2.2 Părţi vulnerabile ale unui fişier executabil......................................................................... 7<br />

2.3 Unelte folosite de crackeri.................................................................................................. 9<br />

2.4 Ollydebugger………………………………………………………….............................. 11<br />

2.5 Soluţii actuale de protecţie a aplicaţiilor de calculator...................................................... 12 9<br />

2.5.1 ASProtect................................................................................................................ 14<br />

2.5.2 Execryptor............................................................................................................... 14<br />

2.5.3 Molebox.................................................................................................................. 15<br />

2.5.4 Enigma Protector………………………………………………………................ 15<br />

2.5.5 SVKP………………………………………………………… …………………. 16<br />

2.5.6 ExeWrapper……………………………………………………………................ 16<br />

2.5.7 Themida…………………………………………………………………………...17<br />

2.5.8 Private Exe Protector...............................................................................................17<br />

2.6 Concluzii............................................................................................................................17 10<br />

3. Fundamente teoretice de bază..................................................................................................20 12<br />

3.1 Structura şi parametrii de bază ai unui fişier executabil......................................................20 12<br />

3.2 Secţiunea de exporturi a unui fişier executabil....................................................................25<br />

3.3 Secţiunea şi directorul de importuri a unui fişier executabil...............................................28<br />

3.4 Setul de instrucţiuni 8086....................................................................................................31<br />

3.5 Formatul instrucţiunilor în limbaj de asamblare.................................................................32<br />

3.6 Transformări la nivel de limbaj de asamblare.....................................................................35<br />

4. Proiectarea şi dezvoltarea unui program de protecţie a fişierelor executabile......................39 15<br />

4.1 Implementarea componentei packer....................................................................................40<br />

4.1.1 Salvarea unei copii de siguranţă a fişierului protejat................................................40<br />

4.1.2 Alocarea spaţiului de memorie pentru fişierul protejat............................................41<br />

4.1.3 Identificarea fişierului executabil şi citirea parametrilor de bază ai acestuia...........42<br />

4.1.4 Eliminarea tabelei de importuri originale.................................................................43<br />

4.1.5 Criptarea numelor librăriilor DLL şi ale funcţiilor Windows API...........................43<br />

4.1.6 Criptarea secţiunilor fişierului executabil utilizând cod polimorfic.........................44<br />

4.1.7 Adăugarea unei secţiuni noi fişierului executabil protejat.......................................50<br />

4.1.8 Construirea tabelei de importuri a componentei packer...........................................54<br />

4.2 Implementarea componentei depacker................................................................................55<br />

4.2.1 Apelul funcţiilor Windows API din componenta depacker.....................................55<br />

4.2.2 Saltul la punctul de intrare al fişierului executabil protejat.....................................56<br />

4.2.3 Iniţializarea şi reconstruirea tabelei de importuri cu componenta depacker............56<br />

4.2.4 Criptarea codului componentei depacker a programului protector......................... 57<br />

3


4.2.5 Obfuscarea statică a codului componentei depacker...................................................58<br />

4.2.6 Obfuscarea dinamică a codului componentei depacker...............................................60<br />

4.3 Concluzii.................................................................................................................................61 16<br />

5. Algoritmi de criptare a numerelor seriale..................................................................................63 17<br />

5.1 Noţiuni matematice de bază....................................................................................................63<br />

5.2 Algoritm de criptare cu două matrice cheie............................................................................67<br />

5.3 Rezultatele obţinute în uma criptării cu două matrice cheie...................................................70<br />

5.4 Generarea matricelor cheie.....................................................................................................73<br />

5.5 Algoritm de criptare cu o singură matrice cheie.....................................................................76<br />

5.6 Rezultatele obţinute în urma criptării cu o singură matrice cheie...........................................79 17<br />

5.7 Utilitatea algoritmilor de criptare cu matrice...........................................................................82 20<br />

6. Evaluarea performanţelor fişierelor executabile protejate cu programul prezentat în această<br />

teză....................................................................................................................................................83 21<br />

6.1 Teste de performanţă...............................................................................................................84 21<br />

6.2 Test de securitate al metodelor de obfuscare..........................................................................86 23<br />

6.3 Performanţele implementării algoritmilor de criptare cu matrice.......................................... 88 25<br />

7. Concluzii......................................................................................................................................89 26<br />

7.1 Concluzii finale.......................................................................................................................89 26<br />

7.2 Contribuţii...............................................................................................................................91 28<br />

7.3 Direcţii de cercetare ulterioară................................................................................................94 31<br />

Bibliografie......................................................................................................................................95 32<br />

Anexe..............................................................................................................................................100<br />

Anexa 1........................................................................................................................................100<br />

Anexa 2........................................................................................................................................105<br />

Anexa 3........................................................................................................................................110<br />

Anexa 4........................................................................................................................................130<br />

Listă de tabele..................................................................................................................................135<br />

Listă de figuri...................................................................................................................................135<br />

Listă de abrevieri şi denumiri..........................................................................................................136<br />

Listă de publicaţii............................................................................................................................136<br />

Curriculum Vitae.............................................................................................................................138 33<br />

4


1. Introducere<br />

1.1 Obiective de cercetare<br />

Scrierea de programe şi aplicaţii de calculator reprezintă un domeniu complex care ia amploare an de<br />

an odată cu dezvoltarea mediilor de dezvoltare integrate de la diferite companii precum Microsoft şi<br />

Borland, actualizarea limbajelor de programare existente şi apariţia unor limbaje noi.<br />

Complexitatea scrierii de programe de calculator rezultă din designul complex şi execuţia complexă a<br />

fiecărui program. Se crează astfel dificultăţi pentru programatori şi inevitabil, apar erori. În domeniul<br />

securităţii software, suma acestor erori poartă numele de vulnerabilitate software, [24]. Lucrarea de faţă<br />

îşi propune analiza critică a acestor vulnerabilităţi şi diminuarea lor maximă, crescând astfel fiabilitatea şi<br />

nivelul de securitate al programelor de calculator.<br />

Problema vulnerabilităţii programelor de calculator este discutată în numeroase lucrări unde se<br />

enumerează erori şi se propun soluţii dar cu prea puţine exemple practice care să vină în ajutorul<br />

programatorilor. Un program vulnerabil produce o scurgere de informaţii către un utilizator neautorizat<br />

care apoi face publice aceste informaţii şi compromite întregul program [20], [21].<br />

Rezolvarea eficientă a problemei vulnerabilităţii programelor de calculator presupune un studiu<br />

amănunţit al naturii şi comportamentului fiecărui program. Datorită volumului mare de aplicaţii<br />

comerciale şi medii de programare existente azi, soluţia problemei depinde de un punct comun al<br />

acestora. Acest punct comun îl reprezintă compilarea şi apoi execuţia fiecărui program în limbaj de<br />

asamblare la nivel de microprocesor.<br />

Studiul codului de asamblare [1], [2], [10], generat de fiecare mediu de dezvoltare este punctul de<br />

început în rezolvarea problemei vulnerabilităţii. În urma acestui studiu se pot extrage informaţii în<br />

legatură cu comportamentul, execuţia fiecărui program şi informaţii despre securitatea programului.<br />

Soluţia propusă în această teză constă în ascunderea cât mai eficientă a informaţiilor din interiorul unui<br />

program executabil şi ascunderea logicii programului în sine. S-au fixat şi s-au atins următoarele<br />

obiective:<br />

Prezentarea stadiului actual al securităţii programelor de calculator;<br />

Studiul şi determinarea unor puncte vulnerabile comune ale programelor de calculator;<br />

Studiul amănunţit al structurii unui fişier executabil, citirea parametrilor şi modificarea<br />

acestora;<br />

Propunerea unei soluţii pentru ascunderea logicii unui program de calculator în urma<br />

aplicării de transformări la nivel de instrucţiuni în limbaj de asamblare (polimorfism şi<br />

transformări metamorfice);<br />

Implementarea unei soluţii pentru diminuarea vulnerabilităţii programelor de calculator<br />

prin dezvoltarea unei aplicaţii de protecţie a fişierelor executabile, în limbaj de asamblare<br />

cu ajutorul mediului integrat de dezvoltare, distribuit gratuit, Winasm Studio;<br />

Elaborarea unei scheme de protecţie originală bazată pe criptarea cu una sau două matrice<br />

implementând transformări neliniare asupra elementelor matricelor de stare;<br />

Analiza rezultatelor obţinute cu programul de protecţie şi posibilităţi de îmbunătăţire ale<br />

acestuia.<br />

5


1.2 Structura tezei<br />

Teza este împărţită în 7 capitole după cum urmează:<br />

Capitolul 1, Introducere prezintă obiectivele de cercetare şi oferă o privire de ansamblu asupra<br />

celorlalte capitole ale tezei.<br />

Capitolul 2, Stadiul actual al securităţii aplicaţiilor de calculator prezintă un studiu efectuat<br />

asupra situaţiei actuale a pirateriei programelor de calculator şi enumerează soluţii existente pentru<br />

protecţia acestora. Studiul relevă faptul că pe lângă metodele legislative impuse de guvernele ţărilor cu o<br />

piraterie software ridicată se impun metode profesionale de protecţie a programelor. Astfel, în cadrul<br />

aceluiaşi capitol, se analizează părţile vulnerabile ale unui fişier executabil şi se face o trecere în revistă a<br />

metodelor de protecţie existente. Se prezintă un studiu efectuat asupra a aproximativ 400 de programe<br />

comercializate pe internet, în versiuni shareware sau time-trial, în urma căruia rezultă că majoritatea<br />

companiilor de software nu utilizează metode de protecţie a codului asamblare. Acest lucru scoate în<br />

evidenţă motivul principal care a dus la redactarea acestei teze şi anume elaborarea de soluţii noi de<br />

protecţie a programelor de calculator şi optimizarea celor existente. Tot în cadrul acestui capitol se<br />

enumerează programele utilizate de crackeri şi cele mai utilizate programe de protecţie automată a<br />

fişierelor executabile.<br />

Capitolul 3, Fundamente teoretice de bază prezintă în primul rând structura detaliată a unui fişier<br />

executabil. Deoarece <strong>teza</strong> are ca obiectiv protecţia programelor de calculator, se impune o cunoaştere<br />

amănunţită a tuturor structurilor care compun un fişier executabil. Astfel, sunt enumerate structurile antet<br />

DOS Header şi PE Header, tabelul de secţiuni şi apoi secţiunile unui fişier executabil. Se prezintă<br />

membrii fiecărei structuri, tipul lor de date şi informaţia conţinută în fiecare membru. Din antetul DOS<br />

Header sunt amintiţi membrii e_magic şi e_lfanew care stau la baza identificării unui fişier executabil.<br />

Din antetul fişierului executabil PE Header se amintesc membrii Signature, folosit tot la identificare,<br />

AddressOfEntryPoint care conţine adresa primei instrucţiuni care se execută din fişierului executabil,<br />

ImageBase care conţine adresa paginii de memorie unde este încărcat fişierul executabil de către sistemul<br />

de operare, SectionAlignment care conţine valoarea de aliniere a secţiunilor fişierului în memorie,<br />

FileAlignment care conţine valoarea de aliniere a secţiunilor în fişier, SizeOfImage care conţine<br />

dimensiunea totală a fişierului executabil în memorie şi SizeOfHeaders care conţine adresa offset a primei<br />

secţiuni a fişîerului executabil. Apoi se amintesc vectorul DataDirectory şi secţiunile de exporturi şi<br />

importuri a unui fişier executabil.<br />

Deoarece soluţiile de protecţie ale fişierelor executabile laborate în cadrul acestei teze sunt<br />

implementate în limbaj de asamblare, se face o trecere în revistă a setului de instrucţiuni 8086 şi a<br />

formatului acestor instrucţiuni. Capitolul se încheie cu noţiunile teoretice necesare efectuării de<br />

transformări asupra instrucţiunilor în limbaj de asamblare, prin exemple.<br />

Capitolul 4, Proiectarea şi dezvoltarea unui program de protecţie a fişierelor executabile<br />

prezintă punerea în practică a noţiunilor teoretice amintite în capitolul 3. Sunt prezentate componentele de<br />

bază ale unui program de protecţie automată, definite ca packer şi depacker. Se prezintă implemetarea<br />

acestor componente în limbaj de asamblare sub mediul de dezvoltare integrată Winasm Studio care<br />

integrează compilatorul MASM (Microsoft Macro Ass embler) şi operaţiile efectuate. Astfel, se trec în<br />

revistă operaţiile de identificare a unui fişier de tip executabil prin citirea parametrilor din antetele DOS şi<br />

PE, operaţiile de citire şi afişare a parametrilor amintiţi în capitolul 3, alocarea de memorie pentru fişierul<br />

executabil protejat, adăugarea de secţiuni noi fişierului executabil protejat, eliminarea unor membrii din<br />

structurile fişierului executabil sau înlocuirea acestora şi se prezintă soluţii originale de criptare a<br />

secţiunilor de date şi cod ale fişierului executabil protejat. Se prezintă o metodă originală de redirecţionare<br />

şi reconstruire a tabelei de importuri a fişierelui executabil protejat şi se defineşte metoda de criptare cu<br />

6


cheie incrementată a codului asamblare. Se definesc metodele de obfuscare statică şi dinamică a codului<br />

asamblare utilizate împreună cu rutine poli/metamorfice de criptare a codului asamblare la execuţie. Se<br />

testează fiabilitatea programului implementat prin protecţia programelor de calculator selectate în cadrul<br />

capitolului 2, se urmăreşte dacă programul intră în conflict cu sistemul de operare sau programe antivirus<br />

şi se compară cu alte programe asemănătoare rezultatele trecându-se într-un tabel.<br />

Capitolul 5, Algoritmi de criptare a numerelor seriale prezintă soluţii originale implementate în<br />

cadrul acestei teze şi menite să vină în ajutorul programatorilor de rutine de protecţie a programelor de<br />

calculator. Se extinde algoritmul de criptare Hill cu ajutorul noţiunii de matrice aritmetic echivalente, din<br />

algebra liniară. Se trec în revistă noţiuni teoretice care se pun apoi în practică făcând o analiză a<br />

rezultatelor obţinute în urma aplicării fiecărui algoritm elaborat. Se defineşte noţiunea de matrice de stare.<br />

Se amintesc o categorie de transformări neliniare din algebra computaţională, precum transformări<br />

pseudo-Hadamard, efectuate asupra elementelor matricei de stare, în scopul creşterii nivelului de<br />

complexitate a algoritmilor liniari prezentaţi. Capitolul se încheie cu prezentarea utilităţii algoritmilor de<br />

criptare elaboraţi. Astfel, algoritmii se vor aplica textului care formează numărul serial iar în final se<br />

aplică o funcţie hash care împarte şirul criptat în blocuri şi efectuează operaţii de control asupra acestora.<br />

Capitolul 6, Evaluarea performanţelor fişierelor executabile protejate cu programul prezentat<br />

în această teză prezintă testele de performanţă, securitate şi funcţionalitate a metodelor originale de<br />

protecţie implementate în programul protector şi a algoritmilor de criptare a numerelor seriale. Se fac teste<br />

de comparaţie a dimensiunii fişierului înainte şi după protecţie, se fac teste de viteză de execuţie a<br />

fişierului înainte şi după protecţie, se defineşte întârzierea de decriptare şi se măsoară, rezultatele<br />

trecându-se în tabel. Se defineşte noţiunea de buffer de criptare şi se fac teste de performanţă a fişierului<br />

executabil protejat în funcţie de dimensiunea acestui buffer.<br />

Capitolul 7, Concluzii prezintă concluziile finale, contribuţiile aduse în acestă teză şi direcţiile<br />

ulterioare de cercetare.<br />

Secţiunea Bibliografie enumerează referinţele bibliografice utilizate în această teză.<br />

Anexele lucrării conţin toate articolele publicate la sesiuni de comunicări ştiinţifice internaţionale, pe<br />

perioada elaborării tezei, şi codul sursă al programului de protecţie automată a fişierelor executabile<br />

dezvoltat în capitolul 4.<br />

7


2. Stadiul actual al securităţii aplicaţiilor de calculator<br />

2.1 Situaţia actuală a pirateriei aplicaţiilor de calculator<br />

În urma compilării unui program cu ajutorul oricărui mediu de programare existent rezultă un<br />

fişier de tip executabil ( Portable Executable) cu extensia .EXE, .DLL sau .OCX, [4], [5]. Analiza şi<br />

modificarea acestor fişiere este posibilă cu ajutorul unor programe speciale numite debuggere care<br />

afişează întregul cod al programului în limbaj asamblare. Dintre debuggerele cel mai des utilizate<br />

amintim: IDA Pro, Ollydebugger, Win32Dasm, TRW (pentru Windows 98, NT/XP) şi Softice (pentru<br />

Windows 98). Programele de tip debugger sunt proiectate şi implementate pentru a veni în sprijinul<br />

programatorilor la depanarea erorilor de execuţie, unul din marile avantaje oferite de acestea fiind<br />

posibilitatea executării programului, instrucţiune cu instrucţiune. Debuggerelor li se alatură şi<br />

dezasambloarele care constituie un set de programe dedicate depanării programelor scrise în limbaje de<br />

programare de nivel înalt cum ar fi Visual Basic sau Delphi, şi care fac posibilă reconstruirea completă a<br />

codului sursă al programului analizat. Menite să vină în ajutorul programatorilor, debuggerele utilizate de<br />

către persoane neautorizate pentru analiza codurilor programelor de calculator se transformă în arme<br />

eficiente folosite la modificarea şi reducerea fiabilităţii programelor. Examinarea şi modificarea unui<br />

fişier executabil cu ajutorul unui debugger se numeşte reverse engineering sau cracking. Persoanele care<br />

modifică fişiere executabile şi le utilizează după bunul plac se numesc reverse engineers sau crackeri.<br />

Un dezavantaj major pentru crackeri este faptul că debuggerele, deşi dezvăluie întregul cod<br />

asamblare al programului, nu oferă nimic despre codul sursă, acesta fiind imposibil de generat dintr-un<br />

simplu fişier executabil. Dintre alte utilitare care oferă modificarea fişierelor executabile mai amintim şi<br />

editoarele hexazecimale.<br />

Pentru creşterea fiabilităţii fişierelor executabile se impune implementarea unor metode de<br />

securitate care împiedică încărcarea şi analiza acestora într-un debugger, [2], [3], [9], [10]. Dacă<br />

încărcarea în debugger se realizează totuşi cu succes, trebuie ascunsă logica programului prin metode<br />

specifice limbajului de asamblare sau limbajului C. Aceste metode sunt optimizate în această teză<br />

împreună cu alte soluţii actuale de securitate şi se elaborează metode noi pentru obţinerea de fişiere<br />

executabile robuste, fiabile, care să reziste celor mai avansate tehnici de cracking din pirateria de<br />

programe actuale.<br />

Pirateria aplicaţiilor de calculator continuă să tulbure industria de calculatoare, producând pierderi<br />

financiare enorme an de an, [20]. Pentru a înţelege mai bine efectele pirateriei şi ale cracking-ului, se pot<br />

citi rapoartele online ale societăţii internaţionale Business Software Alliance (BSA) începând cu 23 Mai<br />

2006. Acestea dezvăluie că 35% din programele instalate pe calculatoare in 2005 au fost piratate<br />

înregistrând o pierdere globală pentru companiile producătoare de software de 34 miliarde de dolari, cu<br />

1,4 miliarde de dolari mai mult decât în 2004. În 2008, valoarea programelor utilizate ilegal în întreaga<br />

lume a atins bariera de 59 miliarde de dolari şi până în 2011 a crescut cu 11 procente.<br />

Acelaşi raport relevă că SUA şi Noua Zeelandă sunt ţările cu pirateria cea mai redusă, la polul<br />

opus aflându-se Vietnam, Zimbabwe şi Pakistan. Un fapt îmbucurător care reiese din raportul BSA este că<br />

în China, Rusia, India, Orientul Mijlociu şi Europa Centrala şi de Est pirateria a scăzut ca urmare a<br />

măsurilor luate de guvernele ţărilor şi zonelor respective.<br />

Cercetările individuale efectuate în ultimii trei ani asupra fişierelor executabile a sute de aplicaţii<br />

comercializate astăzi prin intermediul internetului relevă faptul că din fişierele examinate doar 50% sunt<br />

protejate împotriva crackerilor, cealaltă jumătate nefiind protejată deloc sau doar cu ajutorul unor<br />

algoritmi uşor de depăşit prin metode elementare.<br />

8


Ce metode există pentru a combate pirateria, înafara celor legislative? Cum pot să-mi protejez<br />

produsul cât mai bine? Sunt doar două din întrebările pe care şi le pun producătorii de programe de<br />

calculator. Răspunsul este dobândirea de cunoştinţe avansate de limbaj de asamblare şi de structură a unui<br />

fişier executabil şi aplicarea acestor cunoştinţe la protecţia părţilor vulnerabile ale fişierelor executabile<br />

obţinute.<br />

2.5 Soluţii actuale de protecţie a aplicaţiilor de calculator<br />

Pentru orice mecanism de protecţie al unei aplicaţii de calculator, cheia este verificarea autenticităţii<br />

produsului [4], [5]. Producătorul trebuie să ştie dacă persoana care foloseşte programul este sau nu cea<br />

sau cel care se pretinde a fi şi dacă acea persoană este autorizată să folosească produsul. În acest context<br />

prin persoană se înţelege nu numai utilizatorul ca atare ci şi calculatorul sau mediul pe care este păstrată<br />

copia înregistrată a aplicaţiei. Astfel, putem deosebi două tipuri de protecţie folosite de producătorii de<br />

programe:<br />

- protecţie care se bazează pe cunoaştere (a unei parole, număr serial, etc);<br />

- protecţie care se bazează pe posesia (unui disc cheie, a unei documentaţii, etc)<br />

Protecţia care se bazează pe cunoaşterea unei parole anume, se dovedeşte a fi ineficientă dacă<br />

posesorul parolei se decide să o facă cunoscută altor utilizatori, sau mai mult, public. În acest caz orice<br />

persoană care cunoaşte parola poate folosi aplicaţia. Dacă acest tip de protecţie se dovedeşte a fi<br />

ineficient, de ce se mai foloseste de către producatori? Răspunsul e simplu: producătorii îşi protejează<br />

proprietatea intelectuală împotriva atacurilor prin “forţă brută”. De asemenea, acest tip de protecţie este<br />

ideal pentru firme şi companii mari, nu pentru utilizatori mici, cum ar fi programatori individuali sau<br />

grupuri de programatori.<br />

Pentru cei din urmă, protecţia prin posesia unui disc cheie extrem de dificil de copiat se dovedeşte a fi<br />

mult mai eficientă. Primele protecţii de acest tip au apărut pe discuri floppy, unde informaţia era<br />

înregistrată într-un mod imposibil de copiat prin deteriorarea suprafeţei discului cu un obiect ascuţit.<br />

Sectorul defect de pe discul floppy se identifică în aplicaţia originală şi se verifică de fiecare dată la<br />

pornirea acesteia. În zilele de azi acest mecanism este folosit pentru suporturi optice de tip CD/DVD,<br />

discuri compacte, dar deteriorarea se face de cele mai multe ori cu laser. Legarea aplicaţiei de existenţa<br />

unui disc cheie imposibil de copiat era menită să descurajeze mult pirateria programelor.<br />

Alte tipuri de protecţie bazate pe posesia unei componente cheie limitează numărul de execuţii al<br />

programului sau permite folosirea acesteia doar o perioadă de timp limitată. Aceste mecanisme sunt<br />

folosite adesea în aplicaţia care instalează programul, unde cheia este cerută o singură dată, ulterior<br />

programul urmând să funcţioneze independent de existenţa componentei cheie.<br />

Ambele tipuri de protecţie discutate pot să conţină şi alte restricţii pe perioada de încercare a<br />

programului sau în versiunea demonstrativă. Din acestea menţionăm interzicerea accesului la anumite<br />

componente din meniu şi limitarea numărului de instalări ale programului. Restricţiile diferă de la o<br />

aplicaţie la alta, depinzând de alegerea producătorilor. Acelaşi producător poate folosi acelaşi tip de<br />

protecţie pentru produsele sale sau tipuri diferite pentru fiecare produs, caz în care protecţia se dovedeşte<br />

a fi mai eficientă, dar preţul produsului mai ridicat.<br />

Diversificarea mecanismelor de securitate a programelor de calculator a favorizat protecţia cu numere<br />

seriale care e mult mai populară decât protecţia cu componente cheie. Producătorii de programe trebuie să<br />

aleagă sisteme de securitate ale produselor care nu crează inconveniente pentru utilizatorii autorizaţi. În<br />

caz contrar chiar şi aceşti utilizatori vor vizita primul distribuitor ilegal de programe, în ciuda<br />

avertismentelor şi legilor în vigoare.<br />

9


La soluţiile de protecţie explicate la începutul acestui paragraf se adaugă şi cele comerciale. Prin<br />

soluţii de protecţie comerciale se înţelege mulţimea de programe dedicate protecţiei fişierelor executabile.<br />

Multe companii producătoare de programe recurg la aceste soluţii comode care prezintă avantaje şi<br />

dezavantaje şi necesită o documentare riguroasă înainte de a le cumpăra şi folosi. Enumerăm mai jos<br />

câteva din programele de protecţie de fişiere executabile existente azi pe piaţă.<br />

2.6 Concluzii<br />

Din studiului situaţiei actuale în domeniul protecţiei aplicaţiilor de calculator, prezentate în<br />

paragrafele anterioare, rezultă următoarele concluzii:<br />

Orice soluţie de protecţie a unui program de calculator este menită să întârzie cât mai mult apariţia<br />

unui crack valid pentru programul respectiv. Această întârziere conduce la o creştere automată a<br />

timpului de vânzare şi a profiturilor programatorilor.<br />

Protecţia cu un protector existent deja pe piaţă implică riscul existenţei unor metode de cracking a<br />

protectorului utilizat. Din această cauză, înainte de procurarea oricărui program protector trebuie<br />

făcută o documentare riguroasă şi o analiză a programelor existente. Se vor procura programe care<br />

sunt actualizate în permanenţă şi se va evita achiziţionarea celor ale căror proiecte au fost<br />

abandonate.<br />

Fiecare program protector de fişiere executabile oferă aceleaşi opţiuni standard de protecţie ale<br />

unui fişier executabil, şi anume: protecţie anti-dumping, adică împiedică descărcarea din memorie<br />

a codului asamblare complet al fişierului executabil protejat; protecţia tabelei de importuri, care<br />

ascunde numele librăriilor importate şi ale funcţiilor Windows API apelate; protecţie antidebugging,<br />

adică face imposibilă citirea logicii codului asamblare a unui fişier executabil încărcat<br />

într-un debugger sau împiedică încărcarea fişierului executabil protejat în debugger prin<br />

închiderea ferestrei principale a debugger-ului fără o anunţare în prealabil a crackerului.<br />

Implementarea acestor opţiuni depinde de creativitatea şi experienţa programatorilor, făcând<br />

posibilă astfel aducerea de contribuţii noi în domeniu prin optimizarea soluţiilor existente sau<br />

elaborarea unor soluţii originale. Acestor direcţii de cercetare deschise în continuare li se adaugă şi<br />

posibilitatea de inovare a unor opţiuni de protecţie originale, cum ar fi algoritmi de criptare noi,<br />

utilizaţi asupra numerelor seriale la înregistrarea unui program de calculator. Dezavantajul<br />

utilizării aceluiaşi protector asupra mai multor programe constă în aplicarea aceleiaşi scheme de<br />

protecţie mai multor programe, prin urmare compromiterea unuia dintre ele duce la<br />

compromiterea înregii serii de programe protejate.<br />

Dacă nu se doreşte procurarea unui protector comercial se vor implementa scheme de protecţie<br />

originale şi complexe care să efectueze cât mai multe calcule şi cât mai complicate la verificarea<br />

numerelor seriale pentru a întârzia cât mai mult procesul de cracking. Pentru programele protejate<br />

care utilizează internetul se va implementa în mod obligatoriu o rutină de verificare online a<br />

autenticităţii utilizatorului programului. Se vor evita mesajele de eroare şi de succes din fereastra<br />

de înrregistrare, iar validarea numărului serial sau a parolei de înregistrare se va face într-un fişier<br />

separat, eventual de tip .DLL prin apelare dinamică a rutinelor din acest fişier. Acest tip de<br />

protecţie dă rezultate foarte bune. Pe lângă utilizarea unui număr serial pentru înregistrare se<br />

recomandă utilizarea unui fişier cheie a cărui existenţă şi conţinut să fie verificate în permanenţă la<br />

utilizarea programului protejat. În final, se poate proiecta propriul program de protecţie, si acesta<br />

este unul din obiectivele acestei teze, pentru a veni în sprijinul programatorilor. O rutină eficientă<br />

de protecţie trebuie scrisă într-un limbaj de programare de nivel scăzut sau mediu. În cazul<br />

10


utinelor de protecţie scrise în C/C++ se recomandă optimizarea lor prin inserarea de porţiuni de<br />

cod asamblare.<br />

În decursul acestor 3 ani de elaborare a tezei am efectuat un studiu asupra a mai mult de 400 de<br />

programe de calculator din care amintesc jocuri, convertoare audio şi video, diverse utilitare<br />

educaţionale şi programe antivirus. Aceste programe provin de la exact 196 companii de software.<br />

Obiectivele studiului au fost:<br />

1. observarea utilităţii elaborării unui nou program de protecţie şi optimizării celor existente;<br />

2. elaborarea unei statistici a utilizării protectoarelor comerciale existente şi enumerate în<br />

paragraful 2.5 din această teză, vezi tabelul 1.<br />

Rezultatele studiului efectuat relevă că doar 25% din companiile de soft selectate au optat pentru<br />

utilizarea unui protector comercial, şi se observă că ASProtect este în topul preferinţelor acestora urmat de<br />

Molebox şi de Execryptor, ultimul pierzând teren datorită neactualizării programului din 2005. Faptul că<br />

celelalte programe sunt puţin utilizate, sau deloc, cum ar fi Private Exe Protector, care nu a fost întâlnit<br />

deloc în eşantionul examinat, se datorează probabil faptului că intră în conflict cu programele antivirus şi<br />

preţului ridicat în comparaţie cu ceea ce oferă. Ultimele afirmaţii reies din analiza impresiilor<br />

utilizatorilor de protectoare comerciale.<br />

Rămân 147 de firme, adică 75% din totalul analizat, care preferă elaborarea schemei proprii de<br />

protecţie sau chiar dezvoltarea propriului protector. Prin elaborarea propriei scheme de protecţie se<br />

înţelege de cele mai multe ori o simplă comparare de caractere ale unui şir sau operaţii simple cu şiruri de<br />

caractere, nivelul avansat de protecţie lipsind cu desăvârşire.<br />

Număr Protector utilizat<br />

companii<br />

25 ASProtect<br />

11 Molebox<br />

7 Execryptor<br />

3 Enigma Protector<br />

3 Alte protectoare:<br />

ExeWrapper, Themida,<br />

SVKP<br />

147 Nu utilizează protector<br />

comercial<br />

Tabelul 1 –Utilizarea programelor comerciale de protecţie a fişierelor executabile<br />

Obţinerea acestor rezultate au stat la baza elaborării acestei teze, deoarece reiese că se impun soluţii<br />

noi de protecţie a programelor de calculator şi optimizarea celor existente, care să ducă la o fiabilitate<br />

ridicată şi să întârzie cât mai mult procesul de cracking şi să crească timpul de vânzare.<br />

Din motive de securitate, numele companiilor din eşantionul selectat pentru efectuarea testelor nu pot<br />

fi divulgate deoarece acest lucru ar putea crea inconvenienţe programatorilor.<br />

11


3. Fundamente teoretice de bază<br />

3.1 Structura şi parametrii de bază ai unui fişier executabil<br />

Aşa cum am precizat la începutul capitolului 2, la finalizarea procesului de compilare şi legare a unui<br />

program, cu oricare din mediile de programare existente, rezultă un fişier cu extensia .exe, .dll, .ocx, etc.<br />

în funcţie de mediul de programare folosit, [6], [13], [14], numit fişier executabil, în limba engleză<br />

portable executable, prescurtat PE. Aşa cum reiese din studiile efectuate în capitolul 2, în forma sa<br />

imediat după compilare, fişierul executabil este vulnerabil şi se impun metode de protecţie pentru a<br />

ascunde informaţiile legate de structura lui. Pentru o protecţie eficientă şi de nivel avansat se impune<br />

cunoaşterea amanunţită a structurii şi parametrilor care trebuie preluaţi şi modificaţi din fişierul<br />

executabil.<br />

Formatul unui fişier de tip EXE (Portable Executable File, PE) a fost definit din necesitatea obţinerii<br />

unei metode de executare de cod, pentru sistemul de operare Windows. Pe lângă faptul că un fişier<br />

executabil execută un anume cod, el mai înmagazinează o serie de date necesare executării codului<br />

respectiv, cum ar fi: valori constante, variabile, etc structurate în segmente separate, bine definite.<br />

Structura de bază a unui fişier PE este rezumată în tabelul 2.<br />

Header DOS MZ<br />

Trunchi DOS<br />

Header PE<br />

Tabel secţiuni<br />

Secţiunea 1<br />

…<br />

Secţiunea n<br />

Tabelul 2 – Structura unui fişier executabil<br />

Un fişier executabil are cel puţin două secţiuni: una pentru cod şi una pentru date. O aplicaţie<br />

dezvoltată pentru WindowsNT/2000/XP conţine 9 secţiuni predefinite cu numele: .text, .bss, .rdata, .data,<br />

.rsrc, .edata, .idata, .pdata, şi .debug. Unele programe pot să nu conţină toate aceste secţiuni pe când altele<br />

pot să conţină secţiuni adiţionale necesare execuţiei.<br />

Secţiunile cele mai întâlnite într-un program executabil sunt:<br />

a. secţiunea de cod executabil numită .text (Microsoft) sau .CODE (Borland);<br />

b. secţiunea de date numită .data, .rdata, .bss (Microsoft) sau .DATA (Borland);<br />

c. secţiunea de resurse numită .rsrc;<br />

d. secţiunea de date exportate numită .edata;<br />

e. secţiunea de date importate numită .idata;<br />

f. secţiunea .debug<br />

Numele secţiunilor sunt irelevante deoarece sunt ignorate de sistemul de operare şi sunt prezente<br />

numai pentru convenienţa programatorului. Un alt aspect important al fişierelor executabile este că<br />

structura acestora de pe disc se păstrează şi atunci când sunt încărcate în memorie astfel încât dacă este<br />

posibilă localizarea informaţiei în fişier pe disc atunci este posibilă şi când fişierul este copiat în memorie.<br />

De fapt fişierul executabil nu este copiat exact în memorie. Windows decide ce părţi anume se copiază,<br />

celelalte fiind omise. Copierea se face începând cu headerul DOS, de la adrese mici iar părţile omise sunt<br />

plasate la sfârşitul fişierului la adrese mai mari decât părţile deja copiate. De asemenea locaţia unei<br />

12


componente a fişierului în memorie diferă adesea de cea de pe disc datorită organizării memoriei virtuale<br />

Windows în pagini. Când secţiunile sunt încărcate în RAM ele sunt aliniate astfel încât să ocupe pagini de<br />

memorie de 4Kb, fiecare secţiune ocupând o nouă pagină.<br />

Memoria virtuală reprezintă un intermediar între software şi hardware, stabilind astfel un strat<br />

invizibil între cele două componente ale calculatorului şi interzicând accesul direct la componentele<br />

hardware. La fiecare încercare de accesare a memoriei, procesorul consultă un tabel de pagini care spune<br />

procesului executat care memorie fizică sa o folosească. Avantajele memoriei virtuale sunt:<br />

Oferă posibilitatea creării spaţiilor de adrese multiple. Un spaţiu de adresă reprezintă un tabel de<br />

pagini care permite accesul la memoria corespunzătoare procesului curent. Asigură independenţa<br />

proceselor executate astfel încât la întreruperea bruscă a unui anume proces spaţiile de adrese a<br />

mai multor procese să nu se suprapună ducând astfel la o întrerupere bruscă a întregului sistem.<br />

Oferă procesorului posibilitatea de a crea reguli de acces la memorie. Organizarea pe secţiuni a<br />

unui fişier executabil este necesară deoarece părţi diferite ale fişierului sunt tratate diferit de către<br />

managerul de memorie la încărcarea unui anumit modul. În momentul încărcării, managerul de<br />

memorie stabileşte drepturile de acces pe pagini de memorie pentru fiecare secţiune în parte în<br />

funcţie de setările din headerul secţiunii. Acest lucru determină dacă o secţiune dată se poate citi,<br />

scrie sau executa pe o pagină nouă. Dimensiunea implicită a unei pagini pentru Windows este de<br />

4096b (1000h). Pe disc în schimb repartiţia fişierelor executabile pe pagini de 4Kb ar constitui o<br />

risipă de spaţiu. Din această cauză antetul PE conţine două câmpuri de aliniere diferite: aliniere<br />

secţiuni şi aliniere fişier adică “section alignment” şi “file alignment”. Câmpul aliniere secţiuni<br />

stabileşte modul în care sunt încărcate secţiunile şi este explicat mai sus. Câmpul aliniere fişier (de<br />

obicei de 512 bytes sau 200h) reprezintă modul în care secţiunile sunt aliniate în fişier pe disc şi<br />

este un multiplu de dimensiunea fiecărui sector de pe disc pentru a optimiza procesul de încărcare.<br />

Oferă posibilitatea creării unui fişier temporar pe hard-disk, care să conţină pagini de memorie<br />

neutilizate momentan. De exemplu, dacă o aplicaţie a fost executată şi apoi este trecută în mod<br />

“idle” spaţiul ei de memorie este copiat pe hard-disk şi astfel se eliberează spaţiu în memorie<br />

pentru alte aplicaţii executate ulterior. Executarea aplicaţiilor este la discreţia utilizatorului,<br />

sistemul de operare comutând automat între spaţiile de memorie corespunzătoare fiecărei aplicaţii<br />

curente şi copiind pe hard-disk spaţiile aplicaţiilor neutilizate temporar.<br />

Când fişierele executabile sunt încărcate în memorie, versiunea încărcată se numeşte modul. Pointerul<br />

care conţine adresa de start unde începe copierea fişierului se defineşte HMODULE. Un modul din<br />

memorie conţine tot codul, datele şi resursele dintr-un fişier executabil pe când termenul proces se referă<br />

la un spaţiu de memorie dedicat care poate fi folosit la executarea unui astfel de modul.<br />

Antetul DOS, DOS Header, Toate fişierele executabile încep cu un antet DOS care ocupă primii 64<br />

octeţi ai fişierului. În acest caz dacă programul este executat din DOS sistemul de operare îl recunoaşte ca<br />

un program executabil valid şi rulează în continuare trunchiul DOS imediat după header. Trunchiul DOS<br />

afişează de obicei mesajul “This program must be run under Microsoft Windows".<br />

DOS Header este o structură IMAGE_DOS_HEADER definită în fişierele antet windows.inc şi<br />

windows.h care pot fi localizate uşor în subdirectoarele \include\directory ale diverselor medii integrate de<br />

programare de la Microsoft.<br />

Antetul fişierului executabil, PE Header, este termenul general pentru structura definitită<br />

IMAGE_NT_HEADERS. Această structură conţine informaţii esenţiale folosite de Windows la<br />

încărcarea fişierului EXE. Structura are 3 membri şi este definită în fişierul antet windows.inc.<br />

Signature este o constantă de tip DWORD care conţine valoarea 50h 45h 00h 00h, adică iniţialele<br />

“PE” urmate de două zerouri.<br />

13


FileHeader reprezintă următorii 20 de octeţi ai fişierului PE şi conţine informaţii despre structura<br />

fizică a fişierului cum ar fi numărul lui de secţiuni. FileHeader este definit de asemenea în fişierul<br />

windows.inc.<br />

OptionalHeader este prezent în fiecare fişier executabil şi formează următorii 224 de octeţi conţinând<br />

informaţii despre structura logică a fişierului<br />

Din cei 224 de octeţi ai structurii OptionalHeader ultimii 128 sunt ocupaţi de DataDirectory. Membrii<br />

acestei structuri care prezintă un interes aparte pentru această lucrare sunt:<br />

AddressOfEntryPoint care este adresa relativă ( Relative Virtual Address) a primei instrucţiuni<br />

executată la încărcarea fişierului executabil în Windows. De exemplu, dacă se doreşte devierea de la<br />

fluxul execuţiei din start atunci această valoare trebuie schimbată cu una nouă care va fi executată prima<br />

la încărcarea fişierului.<br />

ImageBase reprezintă adresa de bază implicită la care sistemul de operare Windows încarcă în<br />

memorie fişierul executabil. Această adresă este atribuită fişierului executabil la legare. În 99% din<br />

cazuri adresa este 400000h. Windows poate să nu încarce fişierul la adresa respectivă dacă un alt modul<br />

ocupă spaţiul respectiv.<br />

SectionAlignment reprezintă modul de aliniere al secţiunilor în memorie. De exemplu, dacă valoarea<br />

acestui câmp este 4096 (1000h), fiecare secţiune trebuie să înceapă la multipli de 4096 octeţi.Dacă prima<br />

secţiune este la 401000h şi dimensiunea ei este 10 octeţi, următoarea secţiune trebuie să înceapă la<br />

402000h chiar dacă spaţiul de adresă dintre 401000h şi 402000h rămâne în majoritate neutilizat.<br />

FileAlignment reprezintă modul de aliniere al secţiunilor în fişier. De exemplu, dacă valoarea în acest<br />

câmp este 512 (200h), fiecare secţiune trebuie să înceapă la multipli de 512 octeţi. Dacă prima secţiune se<br />

află la offsetul 200h şi are o mărime de 20 de octeţi, următoarea secţiune trebuie să înceapă la offsetul<br />

400h iar spaţiul dintre offseturile 532 şi 1024 rămâne neutilizat.<br />

SizeOfImage reprezintă dimensiunea totală a imaginii fişierului PE în memorie. Este egală cu suma<br />

tuturor antetelor şi secţiunilor aliniate la SectionAlignment.<br />

SizeOfHeaders suma dintre dimensiunea tuturor antetelor şi dimensiunea tabelului de secţiuni. Altfel,<br />

această valoare reprezintă dimensiunea fişierului minus suma tuturor dimensiunilor secţiunilor fişierului.<br />

Se mai poate folosi şi ca offsetul primei secţiuni din fişierul PE.<br />

DataDirectory este un vector de 16 structuri de tipul IMAGE_DATA_DIRECTORY, fiecare<br />

ocupând 8 octeţi şi care conţin locaţiile şi dimensiunile unor date din fişierul executabil, expuse în tabelul<br />

2. Analog tabelului de secţiuni care reprezintă directorul rădăcină al secţiunilor fişierului executabil,<br />

DataDirectory reprezintă directorul rădăcină al celor 16 componente logice înmagazinate fiecare în<br />

secţiunea corespunzătoare.<br />

14


4. Proiectarea şi dezvoltarea unui program de protecţie a<br />

fişierelor executabile<br />

Această teză are ca obiectiv proiectarea şi implementarea unui program destinat protecţiei automate a<br />

fişierelor executabile. Motivele care au dus la dezvoltarea acestui program sunt următoarele:<br />

în urma studiului prezentat în paragraful 2.6 rezultă că aproximativ 75% din companiile de<br />

software nu utilizează mijloace de protecţie pentru a-şi proteja programele produse.<br />

lipsa prezentării unei infrastructuri necesare implementării unui program protector de fişiere<br />

executabile din literatura de specialitate.<br />

Primul pas în implementare este alegerea limbajului de programare. Aşa cum reiese din paragraful<br />

2.6, cea mai bună alegere este un limbaj de programare de nivel scăzut sau mediu. În această teză am<br />

optat pentru dezvoltarea completă a programului protector în limbaj de asamblare. Se poate alege C sau<br />

Delphi datorită posibilităţii de scriere de cod asamblare intercalat cu oricare din aceste două limbaje de<br />

programare.<br />

Un program protector de fişiere executabile are două componente principale:<br />

Componenta packer, care efectuează următoarele operaţii:<br />

1. crează o copie de siguranţă a fişierului executabil protejat;<br />

2. alocă spaţiu de memorie fişierului care se doreşţe să fie protejat;<br />

3. identifică fişierul protejat ca fiind de tip executabil, prin citirea şi verificarea unor valori<br />

înglobate în fişier;<br />

4. elimină tabela de importuri a fişierului protejat;<br />

5. criptează numele fişierelor librărie .DLL şi ale funcţiilor Windows API;<br />

6. criptează secţiunile de cod din fişierul protejat sau numai o parte din acestea utilizând cod<br />

polimorfic;<br />

7. adaugă în final o nouă secţiune fişierului protejat, creând astfel spaţiu pentru injectarea<br />

codul componentei depacker în fişierul protejat;<br />

8. construieşte porpria-i tabelă de importuri.<br />

Componenta depacker sau loader care efectuează următoarele operaţii:<br />

1. efectuează apelul funcţiilor Windows API din componenta depacker;<br />

2. face saltul la punctul de intrare al fişierului executabil protejat;<br />

3. iniţializează şi reconstruieşte noua tabelă de importuri a fişierului executabil protejat, după<br />

eliminarea celei originale din componenta packer;<br />

4. criptează propriul cod şi conţine motorul metamorfic al programului protector, responsabil<br />

de toate artificiile efectuate asupra codului protejat. Ca metode de protecţie se utilizează<br />

obfuscarea statică şi dinamică.<br />

Programul protector trebuie să satisfacă următoarele condiţii:<br />

să nu intre în conflict cu niciunul din sistemele de operare Windows existente şi să ruleze pe<br />

oricare din acestea;<br />

să nu intre în conflict cu niciunul din programele antivirus. Intrarea în conflict cu oricare din<br />

acestea duce la avertizarea utilizatorilor şi evident la diminuarea încrederii în programul<br />

protector.<br />

Ca mediu integrat de dezvoltare am ales Winasm Studio deoarece este distribuit gratuit pe internet la<br />

http://www.winasm.net, suportă sintaxa MASM32 şi oferă toate facilităţile unui mediu integrat de<br />

dezvoltare de nivel avansat.<br />

15


Convenim ca toate variabilele declarate şi utilizate în program să fie editate începând cu literă mică şi<br />

apoi toate cuvintele din care se compun se vor distinge prin majuscula cu care încep. Fiecare variabilă<br />

declarată şi utilizată în program va avea nume cât mai sugestiv şi va fi explicată la finalul anexei 3.<br />

De asemenea convenim ca toate etichetele utilizate în program să fie redactate cu cuvinte începând cu<br />

majuscule separate de caracterul “underline”.<br />

În paragrafele care urmează sunt prezentate şi analizate în detaliu fiecare din operaţiile efectuate de<br />

componentele packer şi depacker.<br />

Codul sursă al programului protector dezvoltat în această teză este conţinut în întregime în anexa 3.<br />

4.3 Concluzii<br />

În urma implementării şi utilizării programului de protecţie a fişierelor executabile dezvoltat în<br />

această teză rezultă următoarele concluzii:<br />

Datorită alegerii limbajului de asamblare pentru scrierea codului sursă, programul are o viteză<br />

mare de execuţie şi permite efectuarea de operaţii imposibile unor limbaje de nivel înalt. Aceste<br />

operaţii sunt: efectuarea transformărilor la nivel de limbaj de asamblare, numite transformări<br />

metamorfice, scrierea de cod care se automodifică la execuţie numit cod polimorfic, inserarea de<br />

segmente de cod pentru obfuscarea codului asamblare generat de compilatoare şi parcurgerea<br />

opcode instrucţiune în limbaj de asamblare. În urma testelor efectuate în Visual C++, Visual Basic<br />

şi Delphi, obfuscarea codului implementat este redusă datorită optimizării codului de către<br />

compilatoarele mediilor de programare. Utilizarea buclelor prezentate în paragraful 4.2.6 a fost<br />

imposibilă în oricare din mediile de programare enumerate.<br />

Programul protector rulează sub orice sistem de operare Windows: 98, XP, Vista, Windows 7.<br />

Programul protector nu intră în conflict cu următoarele programe antivirus: Norton Antivirus,<br />

Norton Internet Security, AVG, Nod32.<br />

Din metodele alese pentru implementare reiese maleabilitatea programului de protecţie. Codul<br />

sursă prezentat în anexa 3 oferă o soluţie de implementare care stă la dispoziţia programatorilor<br />

individuali, sau echipelor de programatori fie pentru a-şi proteja programele în forma în care este<br />

prezentată, fie pentru a schimba codul sursă.<br />

Programul de protecţie a fost testat pe toate cele aproximativ 400 de programe care au constituit<br />

obiectul studiului din paragraful 2.6, funcţionând fără nicio problemă. Rezultă că poate fi utilizat<br />

pentru a proteja orice fişiere executabile rezultate în urma compilării cu oricare din mediile de<br />

programare de la Microsoft sau Borland.<br />

În urma compararării programului de protecţie dezvoltat în aceată teză cu programele de protecţie<br />

enumerate în paragraful 2.5 rezultă datele din tabelul 7.<br />

În tabelul 7 am folosit abrevierile: Err = mesaj de eroare cauzat de insuficienţa spaţiului în fişierul<br />

executabil protejat pentru adăugarea noii secţiuni, OK = funcţionează corect, PE = fişer de tip executabil.<br />

Se observă că dacă tabela de importuri a fişierului protejat conţine 2 sau mai puţine importuri,<br />

programul nostru dă mesaj de eroare, fiind în imposibilitatea de a adăuga propria secţiune care conţine<br />

componenta depacker. Acest lucru nu constituie un impediment deoarece nu se vor întâlni programe<br />

executabile cu 2 sau mai puţine importuri, excepţie făcând viruşii. S-a realizat totuşi o optimizare faţă de<br />

ASProtect şi ExeWrapper, care dau aceste mesaje la o tabelă cu 1, 2, 3, 4, 5, şi 6 importuri.<br />

16


Nr. Denumire<br />

program<br />

protector<br />

Număr importuri<br />

1 2 3 4 5 6 7<br />

17<br />

VC++ 6 VBasic<br />

1 Program teză Err Err OK OK OK<br />

2 Execryptor Conflict cu Norton Antivirus Invalid PE OK<br />

3 AS Protect Nu Nu Err Err Err Err OK OK OK<br />

4 AS Protect SKE Nu Nu Err Err Err Err OK OK OK<br />

5 Enigma Conflict cu Norton Antivirus<br />

6 Exe Wrapper Err Err Err Err Err Err OK OK OK<br />

7 Molebox OK OK OK<br />

8 SVKP Conflict cu Norton Antivirus<br />

9 Themida Conflict cu Norton Antivirus<br />

10 Private Exe<br />

Protector<br />

OK OK OK<br />

Tabelul 7 – Compararea programului protector cu programe existente<br />

Ca soluţii fiabile în urma acestei comparaţii rămân Molebox, Private exe Protector şi programul<br />

nostru.<br />

5. Algoritmi de criptare a numerelor seriale<br />

5.6 Rezultate obţinute în urma criptării cu o singură matrice cheie<br />

Considerăm fixate aceleaşi elemente din paragraful 3, exemplul 2, şi criptăm numărul serial<br />

UTCN*PROTECTOR folosind o singură matrice de criptare, împreună cu transformările din paragraful 4<br />

asupra elementelor matricei de stare<br />

<br />

<br />

T = <br />

<br />

<br />

<br />

3ˆ 9ˆ 0<br />

1<br />

ˆ 2<br />

3ˆ 1<br />

2ˆ 2<br />

5ˆ 1<br />

7ˆ 1<br />

4ˆ 1<br />

9ˆ 1<br />

<br />

<br />

<br />

<br />

<br />

9<br />

<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

5ˆ a<br />

<br />

= a<br />

<br />

a<br />

Aplicăm prima transformare cu formula ai’ = a(i+k)mod(mn) în care punem 1{0,1, ..., 11}, k=4, şi<br />

obţinem elementele noii matrice de stare:<br />

care devine reactualizată<br />

0<br />

1<br />

2<br />

a<br />

a<br />

a<br />

3<br />

4<br />

5<br />

a<br />

a<br />

a<br />

6<br />

7<br />

8<br />

a<br />

a<br />

a<br />

9<br />

10<br />

11<br />

<br />

<br />

<br />

<br />

<br />

a0’ = a4; a1’=a5; a2’=a6; a3’=a7; a4’=a8; ...; a8’=a0; a9’=a1; a10’=a2; a11’=a3<br />

a<br />

0 '<br />

<br />

T’ = a<br />

1'<br />

<br />

a<br />

2 '<br />

a3<br />

'<br />

a4<br />

'<br />

a5<br />

'<br />

a6<br />

'<br />

a7<br />

'<br />

a8<br />

'<br />

a9<br />

' a<br />

<br />

a10<br />

'=<br />

a<br />

a '<br />

<br />

11 a<br />

Aplicăm a doua transformare cu formula:<br />

4<br />

5<br />

6<br />

a<br />

a<br />

a<br />

7<br />

8<br />

9<br />

a<br />

a<br />

a<br />

10<br />

11<br />

0<br />

a 1<br />

<br />

a2<br />

=<br />

<br />

a <br />

3 <br />

<br />

<br />

<br />

7ˆ 5<br />

1<br />

ˆ<br />

2<br />

1<br />

ˆ 2<br />

5ˆ 9ˆ 4<br />

1<br />

ˆ 1<br />

0ˆ 9<br />

2<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

<br />

<br />

<br />

<br />

<br />

3<br />

<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

9ˆ 1


fiecărui element din noua stare a matricei T’:<br />

şi noua matrice de stare este<br />

ai’ = ai ai+1 ai+2 ai+3 ai+4 ai+5<br />

a0’ = a0 a1 a2 a3 a4 a5=0ˆ ; a1’ = a1 a2 a3 a4 a5 a6= 4ˆ a2’ = a2 a3 a4 a5 a6 a7=8ˆ ; a3’ = a3 a4 a5 a6 a7 a8= 1ˆ 1<br />

a4’ = a4 a5 a6 a7 a8 a9= 6ˆ 1 ; a5’ = a5 a6 a7 a8 a9 a10=0ˆ a6’ = a6 a7 a8 a9 a10 a11=8ˆ ; a7’ = a7 a8 a9 a10 a11 a0= 4ˆ a8’ = a8 a9 a10 a11 a0 a1= 0ˆ ; a9’ = a9 a10 a11 a0 a1 a2= 0ˆ 2<br />

a10’ = a10 a11 a0 a1 a2 a3= 5ˆ 1 ; a11’ = a11 a0 a1 a2 a3 a4=8ˆ <br />

<br />

T” = <br />

<br />

<br />

<br />

8ˆ 4ˆ 0ˆ 0ˆ 6ˆ 1<br />

1<br />

ˆ 1<br />

18<br />

0 ˆ<br />

8 ˆ<br />

4 ˆ<br />

<br />

<br />

<br />

<br />

<br />

8<br />

<br />

ˆ<br />

5ˆ 0<br />

1<br />

ˆ 2<br />

Deplasăm ciclic liniile noii matrice de stare conform celei de-a treia transformări şi obţinem a treia<br />

stare a matricei:<br />

Utilizăm matricea cheie<br />

<br />

<br />

T’’’ = <br />

<br />

<br />

<br />

4ˆ 6ˆ 0<br />

1<br />

ˆ<br />

<br />

<br />

P = <br />

<br />

<br />

<br />

2ˆ 1ˆ 1ˆ 8ˆ 1ˆ 1<br />

8 ˆ<br />

2 ˆ<br />

1 ˆ<br />

1 ˆ<br />

8ˆ 5ˆ 0<br />

1<br />

ˆ<br />

<br />

<br />

<br />

<br />

<br />

1<br />

<br />

ˆ<br />

2ˆ 0ˆ ,<br />

<br />

<br />

<br />

<br />

<br />

0<br />

<br />

ˆ<br />

4ˆ 0ˆ 2<br />

aceeaşi ca şi în exemplul 2 din paragraful 3, iar Q=I2. Efectuăm înmulţirea matricelor<br />

<br />

<br />

PT’’’ = <br />

<br />

<br />

<br />

2ˆ 1ˆ 1ˆ 2 ˆ<br />

1 ˆ<br />

1 ˆ<br />

<br />

<br />

<br />

<br />

<br />

1<br />

<br />

ˆ<br />

2ˆ 0ˆ <br />

<br />

<br />

<br />

<br />

<br />

4ˆ 6ˆ 0<br />

1<br />

ˆ<br />

8ˆ 1ˆ 1<br />

8 ˆ<br />

8ˆ 5ˆ 0<br />

1<br />

ˆ<br />

<br />

<br />

<br />

<br />

<br />

0<br />

<br />

ˆ<br />

4ˆ 0ˆ 2 <br />

<br />

= <br />

<br />

<br />

<br />

0ˆ 1<br />

2<br />

ˆ<br />

9ˆ 5ˆ 2<br />

1<br />

ˆ<br />

4<br />

1<br />

ˆ<br />

7 ˆ<br />

8 ˆ<br />

0 ˆ<br />

<br />

<br />

<br />

<br />

<br />

9<br />

<br />

ˆ<br />

1<br />

1<br />

ˆ<br />

5ˆ =Tc<br />

iar rezultatul obţinut dă criptarea numărului serial: JAUDLOGHXEAS.<br />

Decriptarea acestui cuvânt se efectuează aplicânt inversele fiecărei transformări efectuate, şi<br />

anume:


P -1 <br />

<br />

Tc = <br />

<br />

<br />

<br />

<br />

<br />

9<br />

<br />

ˆ 9ˆ 9 1 ˆ<br />

8ˆ 4 1 ˆ 9 1 ˆ<br />

0<br />

1<br />

ˆ 8 1 ˆ 9 1 ˆ <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

9<br />

<br />

ˆ 0 1 ˆ 5ˆ 0 1 ˆ<br />

1<br />

2<br />

ˆ 8ˆ 2ˆ 1 1 ˆ<br />

5ˆ 7ˆ 4ˆ 9ˆ <br />

<br />

<br />

<br />

= <br />

<br />

<br />

<br />

<br />

<br />

<br />

0<br />

<br />

ˆ 8ˆ 8ˆ 4ˆ 4ˆ 5ˆ 8 1 ˆ 6ˆ 0<br />

1<br />

ˆ 0 2 ˆ 1ˆ 0 1 ˆ<br />

=T’’’<br />

apoi liniile matricei T’’’ se deplasează ciclic spre dreapta în ordinea următoare: prima linie nu se<br />

deplasează, a doua linie se deplasează la dreapta cu o poziţie şi a treia linie se deplasează la dreapta cu 2<br />

poziţii, rezultând matricea T’’. Asupra elementelor acestei matrice se aplică formulele:<br />

care determină matricea<br />

a0 = a0’-( a1 a2 a3 a4 a5)= 2ˆ 2 ; a1 = a1’-( a2 a3 a4 a5 a6)= 5ˆ 1<br />

a2 = a2’-( a3 a4 a5 a6 a7)= 7ˆ 1 ; a3 = a3’-( a4 a5 a6 a7 a8)= 4ˆ 1<br />

a4 = a4’-( a5 a6 a7 a8 a9)= 9ˆ 1 ; a5 = a5’-( a6 a7 a8 a9 a10)=5ˆ a6 = a6’-( a7 a8 a9 a10 a11)=3ˆ ; a7 = a7’-( a8 a9 a10 a11 a0)= 9ˆ 1<br />

a8 = a8’-( a9 a10 a11 a0 a1)= 0ˆ 2 ; a9 = a9’-( a10 a11 a0 a1 a2)= 9ˆ 1<br />

a10 = a10’-( a11 a0 a1 a2 a3)=3ˆ ; a11 = a11’-( a0 a1 a2 a3 a4)= 3ˆ 1 .<br />

<br />

<br />

T’ = <br />

<br />

<br />

<br />

7ˆ 5<br />

1<br />

ˆ<br />

2<br />

1<br />

ˆ 2<br />

5ˆ 9ˆ 4<br />

1<br />

ˆ 1<br />

Asupra fiecărui element din T’ se efectuează substituţiile:<br />

şi rezultă prima matrice de stare<br />

19<br />

0ˆ 9<br />

2<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

<br />

<br />

<br />

<br />

<br />

3<br />

<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

9ˆ 1<br />

.<br />

a0 = a4’; a1=a5’; a2=a6’; a3=a7’; a4=a8’; ...; a8=a0’; a9=a1’; a10=a2’; a11=a3’<br />

<br />

<br />

T = <br />

<br />

<br />

<br />

3ˆ 9ˆ 0<br />

1<br />

ˆ 2<br />

3ˆ 1<br />

2ˆ 2<br />

5ˆ 1<br />

7ˆ 1<br />

4ˆ 1<br />

9ˆ 1<br />

<br />

<br />

<br />

<br />

<br />

9<br />

<br />

ˆ<br />

3<br />

1<br />

ˆ<br />

5ˆ corespunzătoare numărului serial UTCN*PROTECT.<br />

Transformările neliniare efectuate asupra numărului serial înaintea aplicării cheilor de criptare<br />

scad considerabil vulnerabilitatea acestui cifru. O posibilă îmbunătăţire care reiese din aplicaţiile practice<br />

asupra mai multor numere seriale este generalizarea celei de-a doua transformări neliniare astfel încât să<br />

nu depindă numai de elementele matricei de stare ci se vor insera în formulă termeni care sunt elemente<br />

ale unei matrice linie numită matrice sau vector de difuzie.<br />

Considerăm următoarea matrice linie, notată cu D, cu mn elemente, unde m şi n sunt numărul de<br />

linii respectiv de coloane ale matricei de stare T:<br />

d d d <br />

D ...<br />

şi modificăm formula (10), prin adunarea unui element de pe poziţia i, din D, la sfârşitul sumei:<br />

1<br />

2<br />

mn


a’i = ai a(i+k)mod(mn) a(i+k+1)mod(mn) a(i+k+2)mod(mn) ...a(i+k+l)mod(mn)di (12)<br />

unde pentru decriptare, avem<br />

ai = ai’ – (a(i+k)mod(mn) a(i+k+1)mod(mn) a(i+k+2)mod(mn) ...a(i+k+l)mod(mn)di). (13)<br />

O altă variantă care se poate utiliza la aplicarea cheilor prin produs de matrice este interpretarea<br />

coloanelor matricei de stare ca polinoame de gradul l şi înmulţirea cu un polinom cu coeficienţi aleşi<br />

astfel încât să formeze o matrice inversabilă.<br />

5.7 Utilitatea algoritmilor de criptare cu matrice<br />

Prezentăm în continuare punerea în practică a algoritmilor elaboraţi în paragrafele anterioare la<br />

protecţia cu număr serial a unui program de calculator.<br />

Programul de protecţie prezentat în capitolul 4 protejează automat fişierul executabil, la alegerea<br />

utilizatorului, cu un număr serial cu 25 de caractere, de forma :<br />

C1C2C3C4-C6C7C8C9C10C11C12C13C14-C15C16C17C18C19C20C21C22C23C24C25<br />

unde primul bloc de 4 caractere este verificat cu o matrice cheie pătratică de ordinul 2, al doilea bloc de 9<br />

caractere este verificat cu o matrice cheie pătratică de ordinul 3 şi al treilea bloc de 12 caractere este<br />

verificat cu 2 matrice cheie pătratice de ordinul 4. Acest lucru este realizat prin operaţiile:<br />

Se codifică prin program toate caracterele numărului serial cu un tablou de numere întregi;<br />

După codificare, se împarte textul introdus de utilizator în blocuri de 4, 9, respectiv 12 caractere;<br />

Se procesează primul bloc de 4 caractere cu transformările T1 – T4 şi se criptează conform<br />

algoritmului cu o singură cheie cu 4 caractere;<br />

Se procesează al doilea bloc de 9 caractere cu transformările T1 – T4 şi se criptează conform<br />

algoritmului cu o singură cheie cu 9 caractere;<br />

Se procesează ultimul bloc de 12 caractere şi se criptează cu două chei, fiecare de câte 16<br />

caractere.<br />

Am implementat aceste operaţii în limbajul C, într-un fişier librărie separat, care este încărcat dinamic<br />

în memorie la verificarea numerelor seriale introduse pentru înregistrarea programelor protejate.<br />

Complexitatea operaţiilor efectuate asupra caracterelor numerelor seriale duce la creşterea de linii de cod<br />

în limbaj de asamblare generate de compilatorul C.<br />

În afara operaţiilor utilizate asupra caracterelor numerelor seriale se mai pot efectua şi operaţii de<br />

verificare aritmetice sau logice, pentru a creşte timpul de debugging.<br />

Am inserat porţiuni de cod în limbaj de asamblare pentru criptarea liniilor de cod care efectuează<br />

operaţiile asupra caracterelor numerelor seriale.<br />

În final rezultă o schemă de protecţie eficientă, şi uşor de actualizat datorită implementării într-un<br />

fişier librărie separat.<br />

Modificări posibile care se pot efectua asupra schemei de protecţie cu număr serial:<br />

Creşterea sau scăderea numărului de caractere; evident o creştere duce la o securitate sporită şi<br />

creştere a fiabilităţii.<br />

Creşterea numărului de blocuri în care este separat şirul de caractere introdus la înregistrare;<br />

Aplicarea algoritmilor cu două chei de criptare fiecărui bloc din numărul serial;<br />

Utilizarea transformărilor neliniare T1 – T4 asupra fiecărei matrice de stare corespunzătoare<br />

fiecărui bloc din numărul serial;<br />

După implementarea algoritmului de protecţie cu număr serial se va face un debugging riguros al<br />

acestuia, urmărind atent conţinutul registrelor procesorului. Se va evita utilizarea funcţiilor standard de<br />

lucru cu şiruri de caractere şi se vor implementa propriile funcţii în fişierul librărie al întregii scheme de<br />

20


protecţie. Se va evita compararea a două şiruri de caractere, compararea efectuându-se asupra fiecărui<br />

caracter din serialul criptat cu rezultatul dorit. Porţiunile de cod care efectuează compararea se vor cripta<br />

cu metoda XOR şi nu se vor afişa mesaje de succes sau de eroare în urma validării numărului serial.<br />

În cadrul rutinei de verificare a numerelor seriale, în acelaşi fişier librărie, se vor implementa<br />

următoarele metode antidebugging:<br />

Ştergerea punctelor de întrerupere software din memorie prin căutarea şi ştergerea instrucţiunii Int<br />

3H cu codul CCh.<br />

Detectarea punctelor de întrerupere hardware din memorie şi oprirea execuţei programului.<br />

Detectarea debuggerului OllyDebugger din memorie şi oprirea execuţiei programului.<br />

6. Evaluarea performanţelor fişierelor executabile protejate cu<br />

programul prezentat în această teză<br />

Vom analiza rezultatele obţinute cu aplicaţia de protecţie a fişierelor executabile dezvoltată în această<br />

teză în funcţie de fiabilitatea, performanţa şi securitatea fişierelor protejate. Programul s-a testat asupra<br />

mai multor programe ţintă dezvoltate în medii de programare diferite, Microsoft Visual Studio (C++,<br />

Basic), Borland C++ şi Delphi. S-au obţinut rezultate foarte bune şi asupra fişierelor executabile generate<br />

de mediul Winasm Studio, scrise în limbaj de asamblare, compilate cu MASM32.<br />

Din punct de vedere al fiabilităţii, rezultă că:<br />

Fişierul protejat nu intră în conflict cu niciunul din sistemele de operare Windows enumerate în<br />

paragraful 4.2.7..<br />

Fişierul protejat nu intră în conflict cu niciunul din programele antivirus enumerate în paragraful<br />

4.2.7.<br />

Dimensiunea în octeţi a programului protejat creşte datorită injectării codului componentei<br />

depacker, dar aceasta nu contravine deloc funcţionării normale a acestuia în condiţiile menţionate<br />

mai sus. În funcţie de vectorul de transformări metamorfice şi compilatorul utilizat procentajul de<br />

creştere a fişierului protejat este prezentat în tabelul 8 de mai jos. Se va avea în vedere valoarea de<br />

prag în octeţi a secţiunii adăugate fişierului executabil, parte a componentei depacker pentru a nu<br />

încetini executarea fişierului protejat. Pentru o bună funcţionare şi un nivel de securitate optim am<br />

obţinut dimensiunea maximă a bufferului de criptare de 5Ko = 5120 octeţi. Se pot utiliza buffere<br />

de criptare/decriptare de dimensiuni mai mici declarate în diferite zone ale componentei depacker.<br />

În continuare măsurăm întârzierea execuţiei programelor protejate cu programul dezvoltat în<br />

cadrul acestei teze. Aceste măsurători determină intervalul optim în care trebuie să se situeze<br />

dimensiunea bufferului de criptare şi timpii necesari procesării acestuia.<br />

6.1 Teste de performanţă<br />

În testele efectuate am ales 10 fişiere executabile, de dimensiuni diferite, ale celor 400 de programe<br />

care au făcut obiectul studiului din paragraful 2.6, ale unor aplicaţii de interes larg, cum ar fi convertoare<br />

audio sau video, convertoare şi editoare de imagini, convertoare şi editoare de fişiere de diferite tipuri, etc.<br />

Dimensiunile fişierelor selectate sunt în intervalul 3ko – 2,1Mo. Am efectuat aceste teste şi datorită<br />

utilităţii lor la protecţia fişierelor executabile cu ajutorul programului de protecţie automată dezvoltat în<br />

cadrul acestei teze.<br />

21


Primul test compară dimensiunea fişierului protejat înainte de protecţie cu dimensiunea fişierului după<br />

protecţie. Se utilizează un buffer de criptare de 1Ko = 1024 octeţi. Rezultatele sunt trecute în tabelul 8,<br />

unde se observă procentul cu care creşte dimensiunea fişierului protejat. Programul protector nu<br />

împachetează resursele fişierului protejat. Din tabel se observă că procentul de creştere a dimensiunii<br />

fişierului protejat scade odată cu creşterea în dimensiune a acestuia. Pentru facilitarea completării<br />

tabelului am folosit notaţia E pentru fişier executabil, astfel notaţia En înseamnă al n-lea fişier executabil<br />

testat.<br />

Fisier EXE E1 E2 E3 E4 E5 E6 E7 E8 E9 E10<br />

Dimensiune înainte<br />

de protecţie (ko)<br />

3 40 243 433 644 700 848 1130 1333 2115<br />

Procent de creştere<br />

(%)<br />

1100 80 15 6 4 3 3 2 2 1<br />

Tabelul 8 – Rezultatele primului test de performanţă<br />

Al doilea test compară performanţa executării fişierului protejat înainte şi după protecţie prin<br />

compararea timpilor de încărcare în ambele cazuri. Deoarece fişierul protejat conţine codul componentei<br />

depacker, se creşte timpul necesar încărcării acestuia cu timpul necesar executării operaţiilor de decriptare<br />

şi redirecţionare a tabelei de importuri. Această diferenţă de timp o vom numi întârziere de decriptare.<br />

Testul de măsurare a întârzierii de decriptare constă în protejarea fiecărui fişier executabil selectat şi<br />

măsurarea timpului de încărcare consumat de componenta depacker. În tabelul 9 este prezentată<br />

întârzierea de decriptare a fiecăruia din cele 10 fişiere executabile testate. Menţionăm că nu există o<br />

întârziere de decriptare fixă pentru fiecare fişier executabil datorită dependenţei acestuia de resursele<br />

sistemului de operare, cum ar fi fişiere librărie .DLL şi registrele sistemului Windows. Întârzierea de<br />

decriptare depinde de complexitatea fiecărui program protejat. Prin urmare pentru fişiere executabile<br />

diferite se vor obţine rezultate diferite.<br />

Fisier EXE E1 E2 E3 E4 E5 E6 E7 E8 E9 E10<br />

Timp încărcare<br />

înainte de protecţie<br />

(milisecunde)<br />

100 102 180 240 260 265 272 305 320 540<br />

Timp încărcare după<br />

protecţie (ms)<br />

101 103 195 270 295 302 320 350 375 610<br />

Întârziere de<br />

decriptare (ms)<br />

1 1 15 30 35 37 38 45 55 70<br />

Tabelul 9 – Întârzierea de decriptare a fişierelor executabile protejate cu un singur buffer de<br />

criptare de 1024 octeţi<br />

Fisier EXE E1 E2 E3 E4 E5 E6 E7 E8 E9 E10<br />

Timp încărcare<br />

înainte de protecţie<br />

(milisecunde)<br />

100 102 180 240 260 265 272 305 320 540<br />

Timp încărcare după<br />

protecţie (ms)<br />

150 183 280 370 400 410 430 470 500 1500<br />

Întârziere de<br />

decriptare (ms)<br />

50 81 100 130 140 145 153 165 180 960<br />

22


Tabelul 10 – Întârzierea de decriptare a fişierelor executabile protejate cu un buffer de criptare 2048<br />

octeţi<br />

Fisier EXE E1 E2 E3 E4 E5 E6 E7 E8 E9 E10<br />

Timp încărcare<br />

înainte de protecţie<br />

(milisecunde)<br />

100 102 180 240 260 265 272 305 320 540<br />

Timp încărcare după<br />

protecţie (ms)<br />

250 280 380 470 500 540 552 600 650 1550<br />

Întârziere de<br />

decriptare (ms)<br />

100 178 200 230 240 275 280 255 330 1010<br />

Tabelul 11 – Întârzierea de decriptare a fişierelor executabile protejate cu un buffer de criptare 3072<br />

octeţi<br />

Fisier EXE E1 E2 E3 E4 E5 E6 E7 E8 E9 E10<br />

Timp încărcare<br />

înainte de protecţie<br />

(milisecunde)<br />

100 102 180 240 260 265 272 305 320 540<br />

Timp încărcare după<br />

protecţie (ms)<br />

400 475 580 670 700 750 800 870 900 1800<br />

Întârziere de<br />

decriptare (ms)<br />

300 373 400 430 440 485 528 565 580 1260<br />

Tabelul 12 – Întârzierea de decriptare a fişierelor executabile protejate cu un buffer de criptare 4096<br />

octeţi<br />

Din testele efectuate reiese o întârziere medie de decriptare de aproximativ 38 milisecunde pentru un<br />

buffer de criptare de 1Ko, 210 milisecunde pentru 2Ko, 310 milisecunde pentru 3Ko şi 536 pentru 4Ko.<br />

Întârzierea de decriptare este redusă pentru fişiere executabile cu dimensiuni mai mici datorită<br />

dimensiunii mici a secţiunii de cod. Tabelele 9-12 se vor utiliza la setarea dimensiunii bufferelor de<br />

criptare utilizate la protecţie şi la utilizarea multiplă a acestora asupra aceluiaşi program. Întârzierile de<br />

decriptare date în tabele se vor însuma la fiecare utilizare a bufferului de criptare, de dimensiunea<br />

respectivă. Nu se vor admite întârzieri de decriptare mai mari de 2-3 secunde pentru executarea<br />

componentei depacker. Bufferele de criptare pot avea orice dimensiuni intermediare cuprinse în intervalul<br />

[124-5120] octeţi. La utilizarea de buffere de criptare de dimensiuni mai mari creşte considerabil timpul<br />

de compilare al programului protector până la blocarea sistemului de operare<br />

.<br />

6.2 Test de securitate al metodelor de obfuscare<br />

Al doilea test efectuat asupra fişierelor executabile protejate constă în analiza motorului metamorfic al<br />

programului protector, responsabil de obfuscarea dinamică a componentei depacker. Am considerat<br />

primul vector de transformări cu dimensiunea 14. Am măsurat numărul instrucţiunilor generate de<br />

motorul metamorfic în funcţie de numărul de octeţi indicat de variabila DIMENSIUNE_BUFFER,<br />

declarată în paragraful 4.2.6. Rezultatele apar în graficul din figura 12. Testele s-au efectuat pentru<br />

dimensiuni ale bufferului de criptare de cod între 30h=48 octeţi şi 7Ch=124 octeţi. Valoarea minimă s-a<br />

ales convenabil pentru a asigura un nivel de protecţie bun al fişierului ţintă. Pentru un buffer de criptare<br />

corespunzător unui vector de transformări metamorfice, dedimensiune mai mare sau egală cu egal cu<br />

23


7Dh=125, octeţi, se obţin erori de salt datorită faptului că instrucţiunile de salt implementate sunt salturi<br />

scurte (JMP NEAR) sau LOOP, iar creşterea numărului de octeţi impune necesitatea implementării de<br />

salturi de tip JMP.<br />

Num ar instructiuni<br />

80<br />

70<br />

60<br />

50<br />

40<br />

30<br />

20<br />

10<br />

0<br />

N r. instructiuni in functie de nr. octeti<br />

0 20 40 60 80 100 120 140<br />

Num a r octe ti<br />

Figura 12 – Variaţia numărului de instrucţiuni în funcţie de numărul de octeţi<br />

din DIMENSIUNE_BUFFER<br />

De exemplu, salturile scurte implementate la o dimensiune a buffer-ului de criptare de 125, 126, 127,<br />

128 de octeţi nu pot fi luate cu o diferenţă de 1, 2, 3, respectiv 4 octeţi şi numărul de octeţi din diferenţa<br />

de salt creşte cu o unitate. Ca program debugger utilizat pentru teste am folosit Olly Debugger.<br />

Din figura 12 se observă că distribuţia instrucţiunilor în limbaj de asamblare poate fi aproximată<br />

foarte bine de o familie de funcţii liniare. Selectând coordonatele primului punct din grafic (48, 28) şi ale<br />

ultimului punct (124, 70) graficul poate fi aproximat de dreapta de ecuaţie<br />

12 28<br />

y x <br />

(6.2.1)<br />

19<br />

19<br />

Am măsurat frecvenţa de apariţie a fiecărei transformări din tabelele de seturi de instrucţiuni şi<br />

reprezentarea grafică a acestor frecvenţe pentru diferite valori ale variabilei DIMENSIUNE_BUFFER.<br />

Prezentăm frecvenţele de apariţie ale transformărilor din primul tabel pentru valorile<br />

DIMENSIUNE_BUFFER {48, 96, 124} (octeţi) ilustrând în acelaşi timp aceste transformări din cadrul<br />

funcţiei rutinaGenerarePoliMeta aşa cum apar ele la încărcarea în programul debugger Olly Debugger.<br />

Este important de menţionat faptul că am utilizat versiunea 2.0 a lui OllyDebugger. Pentru alte versiuni<br />

ale lui OllyDebugger sau pentru alte programe debugger se obţin rezultate diferite. Pentru frecvenţele de<br />

apariţie ale seturilor de instrucţiuni din tabel folosim notaţiile Ti, i{1, 2, …, 14} iar pentru numărul de<br />

octeţi din DIMENSIUNE_BUFFER nb, unde n{48, 96, 124}.<br />

T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14<br />

48b 0 3 1 7 1 1 2 0 0 2 2 5 2 2<br />

96b 3 3 2 8 5 0 0 5 3 2 2 10 4 4<br />

124b 6 3 2 7 4 4 3 4 3 4 4 11 7 8<br />

Tabelul 13 – Frecvenţele de apariţie ale instrucţiunilor inserate aleator<br />

24


Din tabelul de frecvenţe,cu numărul 10 , rezultă că transformările T4 şi T12 apar cel mai des pe când<br />

transformările T6, T7, T8 şi T9 au cele mai mici frecvenţe de apariţie. Frecvenţa de apariţie a fiecărui set de<br />

instrucţiuni depinde de tabelul cu aceste instrucţiuni şi de implementarea funcţiilor de inserare aleatoare.<br />

Utilizarea unei metode de obfuscare dinamică creşte nivelul de securitate al fişierelor executabile<br />

protejate şi face imposibilă urmărirea logică a programului cu un debugger, implicit face imposibilă<br />

atingerea punctului de intrare în programul executabil. Dacă se ajunge la punctul de intrare în program, şi<br />

se descarcă fişierul executabil din memorie pe hard-disk, redirecţionarea tabelei de importuri împiedică<br />

funcţionarea acestuia.<br />

Rezultatele obţinute în urma acestui studiu de performanţă se vor utiliza la determinarea caracterului<br />

dinamic al instrucţiunilor inserate în bufferul de criptare în etapa de testare a acestuia în debugger.<br />

Dinamica execuţiei instrucţiunilor inserate de motorul poli/metamorfic este asigurată de instrucţiunile de<br />

salt din vectorul de transformări. Dacă instrucţiunile de salt din vectorul de transformări lipsesc atunci<br />

rezultă un cod asamblare executat repetat într-o buclă de inducţie mare şi uşor de depaşit după<br />

identificarea ultimelor instrucţiuni inserate. Am testat protecţia cu şi fără instrucţiuni de salt, diferenţele<br />

de nivel de securitate fiind enorme, mai ales la selectarea opţiunii de colorare a instrucţiunilor de salt cu<br />

Olly Debugger. De asemenea, rezultatele obţinute se vor utiliza la elaborarea instrucţiunilor componente<br />

ale vectorilor de transformări unde în mod obligatoriu se vor utiliza instrucţiuni de forma PUSH imm,<br />

unde imm este un operand inserat aleator în scopul modificării stivei procesorului. Nivelul de securitate<br />

creşte la implementarea instrucţiunilor care admit ca operanzi atât registre pe 8 cât şi pe 16 octeţi<br />

distrugând complet liniaritatea codului inserat şi logica codului protejat.<br />

Urmând rezutatele din tabelul 10 şi ecuaţia (6.2.1) se pot elabora modele de apariţie a instrucţiunilor<br />

implementate în vectorii de transformare de diverse dimensiuni, din intervalul [14-44] seturi de<br />

instrucţiuni pe 1, 2, sau 3 octeţi.<br />

6.3 Performanţele implementării algoritmilor de criptare cu matrice<br />

Aşa cum am constatat la finalul paragrafului 5.4 o criptanaliză prin forţă brută a algoritmilor de<br />

criptare elaboraţi se exclude datorită numărului mare de chei de criptare. Analiza frecvenţei de apariţie a<br />

fiecărui caracter în textul criptat nu ajută deloc la spargerea cifrului datorită alegerii aleatoare a alfabetului<br />

şi eventual a lungimii mari a unor numere seriale care pot fi reţinute în interiorul unor fişiere de date.<br />

Vulnerablitatea algoritmilor de criptare elaboraţi în capitolul 5 constă în liniaritatea algoritmului de<br />

criptare cu două matrice. Pentru spargerea cifrului este suficient să se cunoască o bucată din textul iniţial<br />

al numărului serial şi una din numărul serial criptat, apoi prin rezolvarea unui sistem de ecuatii liniare se<br />

poate determina cheia de criptare.<br />

Problema liniarităţii am rezolvat-o utilizând transformările neliniare asupra liniilor si coloanelor<br />

matricei de stare, astfel încât chiar dacă se determină porţiuni de text iniţial şi criptat, o simplă rezolvare a<br />

unui sistem de ecuaţii nu ajută la găsirea cheii de criptare. Aceste transformări se pot aplica şi matricei de<br />

stare criptate cu două matrice de criptare.<br />

Algoritmii de criptare ai numerelor seriale au fost implementaţi în limbaj C. Deşi rezistenţi din punct<br />

de vedere criptanalitic, pot să apară vulnerabilităţi la implementarea acestora. Am testat algoritmul de<br />

criptare cu două matrice cheie şi algoritmul cu o singură matrice cheie dar cu transformări neliniare<br />

efectuate asupra matricei de stare. Am făcut testul asupra codului asamblare generat de compilator fără să<br />

utilizez programul de protecţie automată şi motorul metamorfic al acestuia, analizând efectiv codul<br />

corespunzător operaţiilor efectuate asupra numerelor seriale. Ca instrument de lucru am folosit<br />

OllyDebugger.<br />

25


Pentru fiecare algoritm am urmărit numărul de instrucţiuni de salt şi de test, precum şi conţinutul<br />

registrelor procesorului. Urmând instrucţiunile din ultimul paragraf al secţiunii 5.7, în urma unui<br />

debugging riguros, am obţinut următoarele rezultate:<br />

Nu este posibilă setarea de puncte de întrerupere pe mesaje de eroare sau de succes, acestea<br />

nefiind utilizate;<br />

Nu este posibilă determinarea codului corespunzător verificării numărului serial prin setarea de<br />

puncte de întrerupere pe operaţii cu şiruri de caractere sau afişare de mesaje, evitând utilizarea<br />

funcţiilor puse la dispoziţie de librăriile mediilor de programare şi implementând propriile funcţii;<br />

Porţiunea de cod corespunzătoare rutinei de verificare a numărului serial nu se poate găsi deoarece<br />

este implementată într-un fişier librărie separat şi porţiuni din acesta sunt încărcate dinamic în<br />

memorie, în timpul executării rutinei. Fişierul DLL nu este legat static de fişierul executabil.<br />

În eventualitatea determinării unei porţiuni de cod a rutinei de verificare a numărului serial,<br />

urmărirea logicii acesteia este îngreunată de eliberarea zonei de memorie în care a fost încărcată<br />

imediat după executare şi executarea unei alte porţiuni.<br />

În registrele procesorului nu se afişează întreg numărul serial deoarece rutinele care efectuează<br />

operaţii asupra lui se adresează fiecărui bloc sau caracter în parte din acesta.<br />

7. Concluzii<br />

7.1 Concluzii finale<br />

Activitatea de cercetare care a condus la elaborarea acestei teze s-a orientat spre studiul şi optimizarea<br />

unora dintre cele mai utilizate metode actuale de protecţie a programelor de calculator. Am continuat cu<br />

dezvoltarea unor metode originale de protecţie a programelor de calculator şi punerea la dispoziţie a unei<br />

infrastructuri de dezvoltare a unui program de protecţie automată a fişierelor executabile.<br />

Am ales un eşantion de 400 de programe de calculator comercializate azi pe piaţă prin intermediul<br />

unor websituri şi am analizat fişierul executabil al fiecărui program cu un debugger în scopul determinării<br />

metodelor de securitate şi al fiabilităţii. În urma analizei s-au obţinut rezultatele din paragraful 2.6 la care<br />

mai adăugăm următoarele concluzii referitor la vulnerabilitatea programelor examinate:<br />

Lipsa unei protecţii anti-debugging, care permite analiza fişierului executabil şi compromiterea<br />

acestuia în timp foarte scurt.<br />

Firmele de software utilizează acelaşi sistem de protecţie pentru fiecare program produs. Acest<br />

lucru se poate evita foarte uşor prin măsuri de protecţie diferite pentru fiecare program în parte.<br />

Fiecare schemă de protecţie, cu număr serial sau nu, trebuie supusă unui test cu un program<br />

debugger.<br />

Pentru protecţia programelor se poate opta pentru o simplă schemă cu număr serial sau pentru<br />

implementarea propriilor metode anti-debugging. În primul caz cele mai bune rezultate s-au<br />

obţinut cu scheme cu număr serial care utilizează o verificare cu un fişier cheie criptat, o<br />

verificare online, mai ales pentru aplicaţiile care necesită o conexiune deschisă permanent pentru<br />

funcţionare, sau o verificare a numărului serial implementată separat într-un fişier librărie .DLL<br />

cu rutine de verificare încărcate dinamic în memorie. Este foarte important să se evite încărcarea<br />

în memorie a întregului fişier librărie .DLL care conţine schema de protecţie. În al doilea caz,<br />

pentru implementarea de metode anti-debugging am propus realizarea unui program de protecţie<br />

automată a fişierelor executabile şi am pus la dispoziţie în anexa 3 codul sursă al celor mai<br />

importante funcţii din program.<br />

26


Am scris codul sursă al programului în limbaj de asamblare, utilizând mediul de programare Winasm<br />

Studio care utilizează sintaxa MASM (Microsoft Macro Assembler) evindeţiind astfel posibilitatea<br />

elaborării propriului mecanism de protecţie cu instrumente distribuite gratuit.<br />

La implementarea programului de protecţie automată am pornit de la algoritmi elementari pe care iam<br />

extins, elaborând algoritmi complecşi de securitate. Am ţinut cont de implementarea modulară care să<br />

permită actualizarea algoritmilor de oricâte ori este nevoie. Principala caracteristică a programului de<br />

protecţie este maleabilitatea, el permiţând o configurare şi o modificare a opţiunilor de protecţie, testate în<br />

capitolul 6. Datorită faptului ca performanţele programului protector sunt măsurabile, dimensiunea şi<br />

fiabilitatea acestuia se pot ajusta în funcţie de opţiunile de protecţie utilizate. Orice program nou de<br />

protecţie automată a fişierelor executabile se testează evaluând performanţele şi nivelul de securitate<br />

pentru a descoperi eventualele vulnerabilităţi şi a le elimina. Pe durata testului este foarte important să<br />

existe instrumente care să ofere informaţii despre performanţele şi comportamentul programului. Astfel<br />

de instrumente pot fi programele debugger iar în testele efectuate noi am utilizat Ollydebugger prezentat<br />

în paragraful 2.4.<br />

Capabilităţile programului protector cresc considerabil timpul de debugging datorită dimensiunii<br />

componentei depacker şi metodelor de criptare şi obfuscare a codului programului protejat.<br />

Am ţinut cont de etapele parcurse de crackeri la analiza unui program executabil, şi anume<br />

identificarea limbajului de programare utilizat, citirea resurselor text ale fişierului executabil, citirea<br />

numelor funcţiilor API importate, identificarea şi analiza rutinei de protecţie a programului, în interiorul<br />

secţiunii de cod a fişierului executabil.<br />

Astfel punctul iniţial în protecţia automată a fişierelor executabile a fost identificarea unui debugger<br />

activ în memorie şi eliminarea acestuia, metodă numită anti-debugging. Soluţia cea mai simplă în<br />

rezolvarea acestei probleme este apelarea, din componenta depacker, a funcţiei IsDebuggerPresent. Alte<br />

soluţii constau în identificarea numelui debuggerului în memorie şi împiedicarea încărcării fişierului<br />

executabil în acelaşi timp cu debuggerul.<br />

Am continuat cu criptarea tuturor resurselor text, adică mesaje afişate la execuţie, numele fişierelor<br />

librărie importate, ale funcţiilor API apelate, şi realocarea punctului de intrare în programul executabil.<br />

S-au dezvoltat metode anti-dumping precum cod care se automodifică la execuţie numit cod<br />

polimorfic şi s-au implementat metode de înlocuire a codului original cu porţiuni de cod echivalent<br />

numite transformări metamorfice. Tot ca metodă anti-debugging s-a implementat o rutină de<br />

redirecţionare a tabelei de importuri a fişierului protejat astfel încât, dacă în urma analizei cu un<br />

debugger, se atinge punctul de intrare original, versiunea descărcată a fişierului executabil din memorie să<br />

nu funcţioneze.<br />

Programul protector citeşte toţi parametrii de bază ai fişierului protejat, prezentaţi în capitolul 3, şi îi<br />

modifică sau îi realocă în spaţii de memorie rezervate. Înainte de efectuarea oricărei operaţii asupra<br />

fişierului executabil acesta se va salva într-o copie de siguranţă, pe hard-disk.<br />

Am dezvoltat un algoritm de protecţie a programelor executabile cu număr serial utilizând noţiuni de<br />

calcul matricial. Nu am folosit algoritmi existenţi deoarece aceştia sunt populari deja în comunităţile de<br />

crackeri de pe internet şi am dorit să implementez o schemă originală de protecţie a programelor.<br />

Prin urmare, am extins cifrul Hill de la criptarea cu o singură matrice inversabilă, la criptarea cu două<br />

matrice, cu ajutorul noţiunii de matrice aritmetic echivalente. Problema liniarităţii acestui algoritm s-a<br />

rezolvat prin implementarea unor transformări neliniare de tip pseudo-Hadamard, cifruri cu substituţie şi<br />

transformări ciclice asupra elementelor matricelor de stare. Acestea au ca rezultat difuzia criptografică şi<br />

eliminarea completă a liniarităţii algoritmului. Implementarea algoritmului de criptare am efectuat-o în<br />

limbaj C, în care am intercalat rutine de criptare în limbaj de asamblare, utilizând numeroase operaţii<br />

aritmetice şi logice, bucle de verificare, pentru aruncarea crackerilor pe piste false în scopul creşterii<br />

27


timpilor de debugging. Tot ca metodă de protecţie am implementat rutina de verificare a numărului serial<br />

într-un fişier .DLL separat, protejat automat cu programul protector, din care funcţiile apelate se încarcă<br />

dinamic în memorie. Acest fişier .DLL nu se va încărca în întregime în memorie pentru a nu putea fi<br />

decriptat şi citit cu un debugger.<br />

Datorită numărului de matrice de criptare, care depinde de mulţimea de matrice selectată, se verifică<br />

matematic că mulţimea respectivă este infinită, eliminând criptanaliza prin forţă brută a algoritmului de<br />

criptare.<br />

Utilitatea algoritmului de criptare reiese din implementarea acestuia într-un limbaj de programare şi<br />

utilizarea lui la verificarea numerelor seriale utilizate la protecţia de programe de calculator. Se<br />

recomandă verificarea de porţiuni ale numerelor seriale şi nu a întregului şir de caractere care compune<br />

numărul serial.<br />

Algoritmul de criptare a fost testat cu OllyDebugger obţinând rezulate foarte bune, generalizarea<br />

cifrului Hill propusă în acestă teză fiind o soluţie fiabilă la protecţia programnelor executabile.<br />

Ca şi concluzie finală, în urma testelor efectuate cu programul protector dezvoltat în cadrul acestei<br />

teze, al cărui cod sursă este pus la dispoziţia programatorilor, acesta oferă o soluţie fezabilă de protecţie a<br />

fişierelor executabile.<br />

7.2 Contribuţii<br />

Activitatea de cercetare desfăşurată pentru elaborarea acestei teze a necesitat cunoştinţe din<br />

domeniul electronicii, precum limbajul de asamblare al microprocesoarelor 8086, al programării<br />

calculatoarelor şi instrumente software. Munca depusă a adus câteva contribuţii originale în fiecare din<br />

aceste domenii, şi urmează a fi enumerate în continuare.<br />

Am efectuat un studiu al metodelor actuale de protecţie a programelor de calculator. La efectuarea<br />

studiului am exploatat părţile vulnerabile ale unui fişier executabil, prezentate în paragraful 2.2, cu<br />

ajutorul unor instrumente software prezentate la rândul lor în paragrafele 2.3 şi 2.4. Etapele acestui studiu<br />

au fost:<br />

Selectarea unui eşantion format din peste 400 de programe în versiune shareware, comercializate<br />

pe internet. Toate aceste programe au avut în comun faptul că aveau implementată o schemă cu<br />

număr serial pentru activare. Alegerea programelor s-a făcut aleator sau în funcţie de preţul şi<br />

popularitatea lor.<br />

Instalarea fiecărui program în parte şi apoi încărcarea fişierului executabil în Olly Debugger,<br />

prezentat în paragraful 2.4. Fişierul executabil analizat îl definim ca fişier ţintă.<br />

Rularea programului ţintă din contextul debuggerului şi urmărirea atentă a execuţiei acestuia. Am<br />

dedus faptul că toate programele fără protecţie antidebugging rulează perfect în contextul<br />

debuggerului şi logica programului în cod asamblare poate fi urmărită de la început până la sfârşit.<br />

Accesarea cu ajutorul debuggerului, în primul rând, a resurselor text şi a tabelei de importuri a<br />

fişierului ţintă si setarea unor puncte de întrerupere pentru oprirea execuţiei înainte de verificarea<br />

numărului serial.<br />

Analiza codului asamblare corespunzător rutinei de protecţie, şi notarea tuturor vulnerabilităţilor<br />

acesteia, în funcţie de logica implementată. Rezultatele sunt prezentate în paragraful 2.6.<br />

Am făcut un studiu al programelor de protecţie automată a fişierelor executabile şi am obţinut rezultate<br />

legate de fiabilitatea acestora anume: intrarea în conflict cu programe antivirus şi cu versiuni ale<br />

sistemului de operare Windows.<br />

28


După efectuarea acestor studii am continuat cu optimizarea şi elaborarea de soluţii originale de<br />

protecţie a programelor de calculator, unele rezultate fiind publicate şi în lucrările din [anexa 1] şi [anexa<br />

2]. Metodele originale elaborate în această teză sunt:<br />

Algoritmi noi de criptare şi validare a numerelor seriale în scopul încetinirii procesului de<br />

debugging. Aceşti algoritmi şi utilitatea lor sunt prezentate în capitolul 5 din teză. Am extins<br />

algoritmul de criptare Hill prin utilizarea noţiunii din agebra liniară, de matrice aritmetic<br />

echivalente, şi am distrus liniaritatea algoritmului Hill prin inserarea de transformări neliniare din<br />

algebra computaţională, asupra elementelor matricelor de stare corespunzătoare numerelor seriale<br />

sau blocurilor de număr serial criptate. Am implementat aceşti algoritmi în limbaj C într-un fişier<br />

librărie DLL separat şi am elaborat o soluţie a problemei încărcării întregului algoritm în memorie<br />

în acelaşi timp, prin alocarea dinamică de memorie numai blocurilor de cod utilizate la un<br />

moment dat, apelând funcţiile LoadLibrary şi GetProcAddress.<br />

Metode originale de distrugere a logicii codului asamblare protejat prin obfuscare statică şi<br />

dinamică, prezentate în paragrafele 4.2.5 şi 4.2.6. La obfuscarea statică [anexa 1] am elaborat<br />

bucle menite să creeze diversiuni în executarea codului protejat şi să arunce crackerii pe piste<br />

false. Am utilizat bucle simple cu constantă de inducţie mare incrementată sau decrementată şi<br />

bucle care comunică între ele prin modelul buclă principală-bucle secundare, cu constante de<br />

inducţie mari corespunzătoare fiecărei bucle. La obfuscarea dinamică [anexa 2] a codului protejat<br />

am elaborat un motor metamorfic în scopul inserări automate de blocuri de cod în codul protejat.<br />

Etapele proiectării motorului metamorfic sunt:<br />

1. Definirea variabilei care conţine întregul bloc de cod care se va insera;<br />

2. Definirea variabilei care conţine dimensiunea codului de bloc inserat;<br />

3. Implementarea unei funcţii de inserare a blocurilor de cod definite anterior.<br />

Am elaborat un set de reguli pentru buna funcţionare a motorului metamorfic:<br />

1. instrucţiunile în limbaj de asamblare inserate să nu utilizeze ca operanzi registre utilizate în<br />

prealabil ca operanzi ai instrucţiunilor de marcare a începutului de bloc inserat şi lungimii<br />

de cod inserat;<br />

2. inserarea blocurilor de cod să nu împiedice fluxul de execuţie a codului protejat. Astfel,<br />

vom evita inserarea în interiorul unor bucle sau porţiuni de program criptate polimorfic.<br />

3. codul inserat se va executa într-o buclă cu constantă de inducţie mare. Din acest motiv vom<br />

avea în vedere dimensiunea blocului inserat deoarece se pot obţine erori de execuţie a<br />

codului protejat, datorită intervalelor unor instrucţiuni de ciclare în limbaj de asamblare.<br />

De exemplu, în cazul utilizării instrucţiunii de ciclare LOOP se vor utiliza blocuri de cod<br />

cu dimensiunea în domeniul [-127, +127], noi am utilizat blocuri de cod cu dimensiunea -<br />

124 respectiv +124. Deoarece blocurile mici nu asigură un nivel optim de securitate am<br />

utilizat instrucţiuni de salt în bucla care conţine codul inserat de către motorul metamorfic.<br />

Astfel, am efectuat următoare înlocuire:<br />

start_bucla: cu start_bucla:<br />

corp bucla corp bucla<br />

LOOP start_bucla DEC ECX<br />

TEST ECX, ECX<br />

JZ sfarsit_bucla<br />

JMP start_bucla<br />

sfarsit_bucla: continuare program<br />

29


Cu ajutorul motorului metamorfic se pot insera blocuri de cod de dimensiuni diferite în codul protejat,<br />

respectând regulile de mai sus. Formula (1) pe care am elaborat-o şi conform căreia se generează întreg<br />

tabelul de instrucţiuni în limbaj de asamblare care urmează a fi inserate cu motorul metamorfic este,<br />

[anexa 4]:<br />

De exemplu,<br />

DD număr_octeţi<br />

DD octeţi instrucţiune în notaţie little endian (1)<br />

DD octeţi instrucţiune în notaţie little endian<br />

DD număr octet inserat aleator.<br />

DD 2<br />

DD 000EB80h ;add bl, 0<br />

DD 000EB80h ;add bl, 0<br />

DD 2<br />

înseamnă că instrucţiunea inserată este pe 2 octeţi din care al doilea este generat aleator. Pentru generarea<br />

aleatoare atât a octeţilor cât şi a blocurilor de cod am utilizat funcţiile srand şi GetTickCount. Am elaborat<br />

un tabel de 22 blocuri de instrucţiuni pe maximum 3 octeţi. Am inserat blocuri de cod cu lungimea de<br />

1024=1Ko, 2048=2Ko, 3072=3Ko, 4096=4Ko, 5120=5Ko, optimizând dimensiunea şi vi<strong>teza</strong> de execuţie<br />

a programului protejat cum a fost prezentat în capitolul 6. Pentru a oferi codului protejat un caracter<br />

dinamic am inclus în tabelul cu instrucţiunile asamblare inserate trei tipuri de instrucţiuni JMP-JMP,<br />

JMP-CALL, CALL-JMP, RET-JMP şi JMP-RET. Datorită limitării numărului de octeţi ai fiecărei<br />

instrucţiuni la 3 nu am putut utiliza instrucţiuni de tip CALL-CALL, CALL-RET sau RET-RET, fiecare<br />

din aceste instrucţiuni fiind reprezentată pe 8 octeţi. La inserarea instrucţiunilor de salt în codul protejat<br />

nu am introdus operand aleator pentru a nu întrerupe fluxul de execuţie al programului protejat.<br />

Am împiedicat analiza programului protejat prin metode de întrerupere a încărcării şi execuţiei<br />

acestuia în contextul unui debugger.<br />

Contribuţiile prezentate s-au fructificat într-un program de protecţie automată a programelor de<br />

calculator, respectiv a fişierelor de tip executabil, al cărui cod sursă este prezentat în anexa 3.<br />

La implementarea acestui program am elaborat o metodă originală de reconstruire şi redirecţionare a<br />

tabelei de importuri a programului protejat, aşa cum s-a prezentat în capitolul 4, fie prin ştergerea tuturor<br />

elementelor vectorului DataDirectory şi reconstruirea ulterioară acestora, fie prin criptarea tuturor<br />

numelor fişierelor librărie şi funcţiilor importate şi apoi apelarea acestora prin intermediul componentei<br />

depacker a programului protector utilizând funcţiile LoadLibrary şi GetProcAddress.<br />

În concluzie contribuţiile aduse în această teză se adresează cerinţelor de protecţie a programelor de<br />

calculator de pe piaţă, si anume:<br />

elaborarea de transformări metamorfice ale codului asamblare fără semnături constante în<br />

porţiunile de cod protejate;<br />

distrugerea totală a logicii codului asamblare protejat;<br />

detectarea şi împiedicarea executării programelor debugger, în special Olly Debugger;<br />

protecţia codului încărcat eventual in debugger;<br />

protecţia tebelei de importuri;<br />

schemă originală de protecţie cu număr serial.<br />

30


7.3 Direcţii de cercetare ulterioară<br />

Ca direcţii de cercetare ulterioară enumerăm:<br />

Dezvoltarea de noi algoritmi de obfuscare a codului în limbaj de asamblare a unui fişier<br />

executabil.<br />

Dezvoltarea unui model nou de motor metamorfic pentru înlocuirea porţiunilor de cod cu<br />

altele echivalente ca funcţionalitate.<br />

Dezvoltarea unei metode noi de realocare a tabelei de importuri a unui fişier executabil.<br />

Dezvoltarea de noi algoritmi de protecţie a numerelor seriale.<br />

Elaborarea de metode noi anti-debugging şi anti-dumping.<br />

Elaborarea unui nou model matematic pentru care să stea la baza unui algoritm de criptare a<br />

parolelor sau numerelor seriale.<br />

31


BIBLIOGRAFIE<br />

[1] Amoroso, E. G.: Fundamentals of Computer Security Technology, Prentice Hall PTR, 1994<br />

[2] Anderson R.: Security Engineering, John Wiley & Sons, 2001<br />

[3] Aucsmith D.: Tamper Resistant Software: an implementation, Proceedings of the First International<br />

Information Hiding Workshop, Lecture Notes in Computer Science 1174, Springer-Verlag, Cambridge,<br />

UK, pp. 317-334, 1996<br />

[4] Bishop M.: Computer Security: Art and Science, Addison Wesley, 2003<br />

[5] Blake I., Seroussi G., Smart N.: Elliptic Curves in Cryptography, Cambridge University Press, 2000<br />

[6] Brown K.: Programming Windows Security, Addison-Wesley, 2000<br />

[7] Cerven P.: Crackproof Your Software: Protect Your Software Against Crackers, No Starch Press,<br />

2002<br />

[8] Danehkar A.: Inject Code Inside Import Table, http://www.codeproject.com/KB/applications<br />

[9] Petrean L.: Software Security – Polymorphic and Metamorphic Code Applications, SIITME 2007<br />

International Symposium for Design and Technology of Electronic Packaging, pp. 212-217, Baia Mare,<br />

Romania, ISSN 1843-5122<br />

[10] Petrean L.: Software Security – General Method of Literal Strings Obfuscation, IWCIT 2007<br />

International Workshop Control and Information Technology, pp. 41-46, Ostrava, Czech Republic, ISBN<br />

978-248-1567-1<br />

[11] Petrean L., Toderean G.: Portable Executable Format Security Patterns, IWCIT 2008 International<br />

Workshop Control and Information Technology, pp. 170-174, Gliwice, Polonia, EAN-9788390474380<br />

[12] Petrean L., Toderean G.: Portable Executable File Format – Import Address Table Redirection and<br />

Reconstruction, microCAD 2008 International Scientific Conference 20-21 March 2008, pp. 49-54,<br />

Miskolc, Ungaria, ISBN 978-963-661-812-4<br />

[13] Petrean L., Toderean G.: Assembly Metamorphic Code Transformations as a Protection Method Of<br />

Portable Executable Files, microCAD 2009 International Scientific Conference 19-20 March 2009, Vol.<br />

XXIII, pp. 35-40, Miskolc, Ungaria, ISBN 978-963-661-866-7<br />

[14] Pirogov V.: The Assembly Programming Master Book, A-LIST Publishing, 2005<br />

[15] Pirogov V.: Disassembling Code: IDA Pro and SoftIce, A-List Publishing 2006<br />

[16] Stamp M.: Information Security Principles and Practice, John Wiley & Sons, 2006<br />

32


Curriculum Vitae<br />

Liviu Petrean<br />

Profesor de matematica la Liceul Teoretic “Emil Racovita”<br />

56, Bd Republicii Apt. 43, Baia Mare 430231 email: liviupetrean@yahoo.com<br />

Tel. +4 0362 417 045<br />

DATE PERSONALE : Născut la 04 August 1972, în Baia Mare<br />

LIMBI STRAINE : Engleza, franceza<br />

STUDII:<br />

- 1990-1995, <strong>Universitatea</strong> Baia Mare, Facultatea de Litere si Ştiinţe, specializarea matematicăfizică<br />

cu durata studiilor de 5 ani;<br />

- 1998-2001, <strong>Universitatea</strong> “Politehnica” din Timişoara, profilul Ştiinta Sistemelor şi a<br />

Calculatoarelor, specializarea Informatică <strong>Tehnic</strong>ă, cu durata studiilor de 3 ani, şcolarizare la<br />

<strong>Universitatea</strong> de Nord din Baia Mare;<br />

- 2001-2003, <strong>Universitatea</strong> <strong>Tehnic</strong>ă din Cluj-Napoca, Studii Academice Postuniversitare,<br />

specializarea: Informatică Aplicată si Programare.<br />

ACTIVITATE PROFESIONALA:<br />

- 1995-1997, Profesor de informatică la Grupul Şcolar “Aurel Vlaicu” din Baia Mare, str Gh<br />

Marinescu nr. 1;<br />

- 1997-2003, Profesor de matematică la Liceul Teoretic “Emil Racoviţă” din Baia Mare, str. V<br />

Alecsandri nr. 56;<br />

- 2003-2006, Profesor de matematică la Lake Marion High School, 3653 Tee Vee Road,<br />

Santee, SC 29142, USA, Director: Rose Pelzer-Brower.<br />

- 2006-2007, Profesor de matematică la Cathedral Hall Academy, 803 Howard Pkwy, Myrtle<br />

Beach, SC 29577, USA, Director: Sue O’Hearn, Dr. Reginald Wayne Miller;<br />

- In prezent sunt profesor titular de matematică la Liceul Teoretic “Emil Racoviţă” din Baia<br />

Mare.<br />

TEME DE INTERES:<br />

- Detectarea şi contracararea programelor de dezasamblare şi a punctelor de întrerupere în<br />

execuţia unui program;<br />

- Creşterea gradului de dificultate al analizei programelor executabile dezasamblate;<br />

- <strong>Tehnic</strong>i de protecţie a programelor executabile.<br />

PREMII, DISTINCTII :<br />

ETS Recognition of Excellence (top 15% of all testers who took this assessment in previous<br />

years), Mathematics: Content Knowledge, on September 13, 2003.<br />

33

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!