HTCinside
Când publicăm produsele noastre software, cu toții obișnuim să scriem în EULA-uri „Nu aveți voie să faceți inginerie inversă, să decompilați sau să dezasamblați Software-ul”. Dar, în multe situații, cuvintele nu sunt cea mai bună protecție și chiar trebuie să introduceți câteva instrumente tehnice pentru a preveni inversarea software-ului și pentru a vă proteja know-how-ul împotriva dezvăluirii.
Există mai multe abordări tehnologice de prevenire a ingineriei inverse a software-ului: anti-debug, anti-dump și altele. În această postare, ne vom concentra asupra unor metode anti-depanare, deoarece acestea sunt în nucleul protecției anti-inginerie inversă. Atașarea unui depanator la procesul cercetat pentru a-l executa pas cu pas este o etapă foarte importantă a oricărei lucrări de inversare - așa că haideți să aruncăm o privire la ce instrumente putem folosi pentru a îngreuna viața inversoarelor.
Sunt câteva lucruri pe care aș dori să le menționez chiar de la început. Primul este că nu există o protecție universală sau 100% antiglonț împotriva ingineriei inverse a software-ului. Există întotdeauna o cale ca reverser să intre, singura strategie pe care o avem este să-i facem munca cât mai grea și consumatoare de efort posibil.
În continuare, există destul de multe tehnici anti inginerie inversă și în special metode anti-depanare, inclusiv protecție bazată pe timp sau chiar tehnologii specifice încorporate în cod, cum ar fi nanomiții. În acest post, vom lua în considerare doar câteva abordări standard specifice sistemelor bazate pe Windows, cele mai populare.
Abordările reprezentate mai jos sunt descrise în general.
Cuprins
Sistemele Windows ne oferă câteva instrumente pregătite pentru a construi protecție anti-depanare simplă. Una dintre cele mai simple tehnici anti depanare se bazează pe apelarea funcției IsDebuggerPresent. Această funcție returnează TRUE dacă un depanator în modul utilizator depanează în prezent procesul.
Această funcție se referă la PEB (Process Environment Block, o structură de sistem închisă) și în special la câmpul său BeingDebugged. Inversoarele atunci când ocolesc o astfel de tehnică de protecție folosesc acest fapt: de ex. aplicând injecția DLL, ei setează valoarea BeingDebugged la 0 chiar înainte ca această verificare să fie efectuată în codul protejat.
Câteva cuvinte despre unde să efectuați o astfel de verificare. Funcția principală nu este cea mai bună opțiune: inversoarele o verifică de obicei mai întâi în lista dezasamblată. Este mai bine să efectuați verificarea anti-depanare în TLS Callback, deoarece este apelată înainte de punctul de apel de intrare al modulului executabil principal.
O altă opțiune de verificare funcțională este CheckRemoteDebuggerPresent. Spre deosebire de funcția descrisă mai sus, verifică dacă un alt proces paralel depanează în prezent un proces. Se bazează pe funcția NtQueryInformationProcess și în special pe valoarea ProcessDebugPort.
În timp ce grupul anterior de metode a fost construit pe verificarea prezenței depanatorului, acesta va oferi protecție activă împotriva acestuia.
Începând cu Windows 2000, funcția NtSetInformationThread primește noul steag numit ThreadHideFromDebugger. Aceasta este o tehnică anti depanare foarte eficientă furnizată în sistemul de operare Windows. Un fir cu acest indicator setat se oprește pentru a trimite notificări de evenimente de depanare, inclusiv puncte de întrerupere și altele, ascunzându-se astfel de orice depanator. Configurarea ThreadHideFromDebugger pentru firul principal va complica semnificativ procesul de atașare a depanatorului la un fir.
Continuarea logică a fost introdusă în Windows Vista cu funcția NtCreateThreadEx. Are parametrul CreateFlags, care setează, printre altele, steag-ul THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER. Procesul cu acest flag set va fi ascuns de depanator.
Rularea depanării poate fi detectată de valorile modificate ale diferitelor steaguri din diferite structuri de sistem și proces.
Windows NT include o variabilă globală numită NtGlobalFlag cu un set de steaguri, utilizate pentru urmărirea și depanarea sistemului. Structura PEB menționată mai sus include propriul câmp NtGlobalFlag. În timpul remedierii, această valoare a câmpului este modificată cu mai multe semnalizatoare specifice setate. Verificarea acestor semnalizatoare poate produce declanșatoare pentru protecția anti-depanare.
Un executabil poate reseta steaguri NtGlobalFlag ale structurii PEB prin intermediul unei structuri specifice numită IMAGE_LOAD_CONFIG_DIRECTORY, care conține parametrii de configurare specifici pentru încărcătorul de sistem. Are câmpul GlobalFlagsClear, care resetează steagurile NtGlobalFlag ale PEB. În mod implicit, această structură nu este adăugată la un executabil, dar poate fi adăugată ulterior. Faptul că un executabil nu are această structură sau valoarea GlobalFlagsClear este egală cu 0, în timp ce câmpul corespunzător stocat pe disc sau în memoria procesului care rulează nu este zero, indică prezența unui depanator ascuns. Această verificare poate fi implementată în codul executabil.
Un alt grup de steaguri este cel al heap-ului de proces. Există două câmpuri în structura _HEAP corespunzătoare: Flags și ForceFlags. Ambele își schimbă valorile atunci când procesul corespunzător este depanat și astfel pot fi baza verificării și protecției anti-depanare.
O altă verificare a semnalizării, care poate fi utilizată pentru a detecta depanatorul, este verificarea semnalizatorului de capcană (TF). Este în registrul EFLAGS. Când TF este egal cu 1, CPU generează INT 01h (excepție „Single Step”) după fiecare execuție a instrucțiunii care sprijină procesul de depanare.
Punctele de întrerupere sunt partea esențială a oricărui proces de depanare și astfel detectându-le, putem detecta și neutraliza un depanator. Tacticile anti depanare bazate pe detectarea punctului de întrerupere sunt una dintre cele mai puternice și greu de ocolit.
Există două tipuri de puncte de întrerupere: cele software și cele hardware.
Punctele de întrerupere software sunt setate de depanator prin injectarea instrucțiunii int 3h în cod. Astfel, metodele de detectare a depanatorului se bazează pe calcularea și controlul sumei de control a funcției corespunzătoare.
Nu există o metodă universală de a lupta împotriva acestei protecții – un hacker va trebui să găsească fragmentul de cod care calculează sumele de control și să înlocuiască valorile returnate ale tuturor variabilelor corespunzătoare.
Punctele de întrerupere hardware sunt setate folosind registre de depanare specifice: DR0-DR7. Folosindu-le, dezvoltatorii pot întrerupe execuția unui program și pot transfera controlul către un depanator. Protecția anti-depanare poate fi construită pe verificarea valorilor acestor registre sau poate fi mai proactivă și resetează forțat valorile acestora pentru a opri depanarea folosind funcția SetThreadContext.
Structured Exception Handling sau SEH este un mecanism care permite unei aplicații să primească notificări despre situații excepționale și să le gestioneze în locul sistemului de operare. Pointerii către handlere SEH sunt denumite cadre SEH și plasați în stivă. Când este generată o excepție, aceasta este gestionată de primul cadru SEH din stivă. Dacă nu știe ce să facă cu el, se trece următorului din stivă și așa mai departe până la handler-ul de sistem.
Când aplicația este depanată, un depanator ar trebui să intercepteze controlul după generarea int 3h, sau un handler SHE îl va prelua. Acest lucru poate fi folosit pentru a organiza protecția anti-depanare: putem crea propriul nostru handler SEH și îl putem pune în partea de sus a stivei și apoi forțam generarea int 3h. Dacă handlerul nostru primește controlul, procesul nu este depanat - altfel putem forța măsuri anti-depanare pe măsură ce am detectat un depanator.
Acestea sunt doar câteva tehnici anti-depanare dintr-o mare varietate de ele.
O bună practică este să combinați diferite tehnici anti-revers, ceea ce face mult mai dificilă ocolirea protecției. Verificările suplimentare pot încetini execuția unei aplicații, de aceea cele mai puternice tehnici de protecție sunt de obicei aplicate modulelor de bază care conțin tehnologii și know-how brevetate. În cele din urmă, este un compromis între nivelul de siguranță a codului și performanța aplicației.
Aș dori să menționez că ingineria inversă a software-ului nu este întotdeauna ilegală și, uneori, poate fi aplicată în timpul procesului de cercetare pentru sarcini precum îmbunătățirea compatibilității, corecția, utilizarea nedocumentată a interfeței sistemului etc. Servicii juridice de inginerie inversă livrate de profesioniști se ocupă și de protecția anti-depanare, dar din altă parte – ocolind-o.