Șiruri criptate la runtime

Astăzi vom parcurge bazele șirurilor criptate la runtime, de ce trebuie să ne criptăm șirurile și vom învăța cum să ne creăm propriile noastre.

În acest articol vei înțelege și vei învăța:

  • Ce este criptarea și decriptarea la runtime
  • De ce trebuie să îți criptezi șirurile
  • Să vezi cum oricine poate vizualiza datele tale sensibile
  • Să îți creezi propria criptare personalizată

Ce este criptarea și decriptarea la runtime

Se referă la datele criptate și/sau decriptate în timpul execuției unui program (software, aplicație). Datele pot fi de orice tip: blocuri de memorie, trafic de rețea, șiruri etc.

Una dintre cele mai comune metode utilizate în acest scop este ofuscarea (de bază). Celelalte mecanisme (avansate) implică mutația/virtualizarea codului compilat.

Astăzi ne vom concentra pe un mecanism care utilizează ofuscarea XOR .

De ce să criptăm șirurile?

Din momentul în care rulezi software-ul tău, totul este vizibil în memorie. Acest lucru se aplică și utilizatorilor finali, ceea ce înseamnă că pot vedea totul.

Unul dintre primele lucruri pe care un atacator le va face este să caute șiruri în interiorul software-ului tău. Acest lucru îi va permite să înțeleagă totul despre software-ul tău cu un efort minim.

Dacă stochezi date sensibile (cum ar fi parole sau licențe), este crucial să nu le stochezi în text simplu. Stocarea lor în text simplu va ușura viața unui atacator.

Există mai multe moduri de a analiza software-ul tău. Cele mai cunoscute și comune metode sunt analiza statică și analiza la runtime.

Să aruncăm o privire la un exemplu simplu folosind o aplicație consolă:

Sample non-encrypted 1

Să compilăm în modul Release (pentru a evita informațiile de debug). Să continuăm și să testăm analiza statică și cea la runtime.

Test de analiză statică

În analiza statică, software-ul nu trebuie să ruleze. Acestea fiind spuse, să deschidem eșantionul în Ghidra .

Din captura de ecran de mai jos poți vedea că eșantionul este compilat fără informații de debug:

Sample non-encrypted 1-1

Dacă căutăm șirurile, poți vedea că toate informațiile noastre sensibile sunt vizibile:

Sample non-encrypted 1-2

Odată ce evidențiezi șirul, poți deschide vizualizarea decompilatorului și vedea tot codul relevant:

Sample non-encrypted 1-3

Destul de trist, nu-i așa? 😕 Imaginează-ți că ai lucrat la software-ul tău minunat timp de luni de zile și ești gata să-l vinzi.

Cred că restul este autoexplicativ, dar sunt sigur că ai înțeles ideea.

Ce este și mai trist este că acest lucru este atât de simplu încât și un copil de doisprezece ani o poate face. (și unii chiar o fac)

Test de analiză la runtime

În analiza la runtime, software-ul trebuie să ruleze. Aceasta înseamnă că trebuie să folosim un software pentru a deschide procesul și a-l citi (în mod normal un debugger).

Cu toate acestea, un debugger nu este neapărat necesar pentru acest scop. Putem pur și simplu să descărcăm un instrument gratuit precum Process Hacker și să deschidem procesul:

Sample non-encrypted 2

A fost destul de simplu, nu? Și reține că nici măcar nu am atașat un debugger. O persoană pricepută și determinată va folosi un debugger.

Când atașezi un debugger vezi mult mai multe, dar discuția aceea este pentru altă zi.

Crearea șirurilor criptate la runtime

Există numeroase moduri de a realiza acest lucru:

  • Folosirea software-ului terță parte precum VMProtect , Themida .
  • Criptarea șirurilor la compilare precum xorstr .
  • Folosirea metodelor personalizate

Primele 2 opțiuni s-ar putea să nu corespundă nevoilor tale. Există multe argumente pro și contra pentru fiecare, pe care nu le vom discuta acum.

Un lucru pe care trebuie să-l înțelegi este că popularitatea înseamnă risc. Când folosești lucruri găsite aleatoriu pe Google, cineva le știe deja.

Majoritatea oamenilor au dezvoltat un instrument împotriva instrumentului tău. Așa stau lucrurile. O fac pentru provocare, sau pentru a-ți fura munca, dar o fac.

Având acest lucru în minte, trebuie să mergi pe personalizat. Poți crea propria ta criptare a șirurilor de la nivel de bază la avansat.

Planul

  • Crearea unei soluții ușor de utilizat
  • Păstrarea șirurilor întotdeauna criptate
  • Decriptare doar când ai nevoie
  • Plasarea șirurilor în poziție aleatorie (opțional - neacoperit)
  • Distrugerea șirurilor după utilizare (opțional - neacoperit)

Soluția

Începe prin definirea șirurilor noastre una câte una ca array:

Step 1

Array-ul poate conține un număr nelimitat de șiruri cu o limită de lungime de 256.

Știu că aceasta este o sarcină dificilă, mai ales dacă șirurile tale sunt lungi. Aceasta este doar în scop demonstrativ și mai târziu vom crea o soluție mai practică.

Ideea este de a cripta fiecare caracter al șirului. Voi folosi o criptare XOR simplă pentru aceasta.

Mai jos poți vedea un exemplu de cum ar funcționa:

Step 2

Cel de mai sus nu are nimic complicat, este simplu și direct, dar destul de puternic. Îl poți folosi în cadrul unei aplicații consolă.

După compilare și rulare, rezultatul sunt octeți ilizibili pentru ochiul uman:

Step 3

Gata, al tău mic software pentru crearea de șiruri criptate la runtime. 😏

Rezultatul

Este timpul să punem soluția noastră în practică. Să creăm un alt eșantion în acest scop și să adăugăm codul nostru:

Step 4

Notează 2 lucruri importante:

  • Am lăsat intenționat câteva șiruri în text simplu pentru a arăta diferența
  • Funcția de decriptare are nevoie de lungime (vom discuta mai târziu)

Să compilăm cele de mai sus în modul Release și să rulăm. Noul eșantion funcționează normal:

Step 5

Dacă deschidem noul eșantion în IDA (sau Ghidra), șirurile criptate nu sunt vizibile:

Step 6

Am menționat că există câteva șiruri lăsate intenționat în text simplu în acest eșantion. Motivul este că le putem urma pentru a vedea codul:

Step 7

A trebuit să derulam în jos pentru a ajunge la textul din imaginea de mai sus. Poți vedea cât de diferit este codul compilat.

Am rezolvat problema analizei statice, să trecem la runtime.

Să-l deschidem în Process Hacker:

Step 8

Voilà! Am rezolvat și problema analizei la runtime 😎

Mai multe despre șirurile criptate

Exemplul de mai sus nu este foarte practic. Definirea fiecărui șir manual este o sarcină obositoare, la fel și specificarea lungimii șirului de fiecare dată.

În mod ideal am avea nevoie de:

  • Citirea unui fișier text pentru șiruri
  • Scrierea șirurilor rezultante într-un fișier text
  • Adăugarea secvențelor de escape la șiruri pentru a evita specificarea lungimii de fiecare dată.
  • Adăugarea XOR mai complex sau oricărei alte metode (opțional)
  • Plasarea șirurilor în poziții aleatorii (opțional)

Am pregătit o soluție drăguță cu care poți experimenta. Poți testa tot ce este scris în acest articol și de asemenea să ai propriul instrument gata de utilizare pentru crearea de șiruri criptate la runtime.

Include 4 proiecte:

  • RuntimeStringEcryptor care citește șirurile dintr-un fișier text, le criptează și apoi le scrie în alt fișier text.
  • Sample este consola simplă folosită pentru a demonstra cu IDA.
  • SampleEncryptedStrings este consola simplă cu șiruri criptate pentru a demonstra cu IDA.
  • SimpleRuntimeStringEncryption este locul de joacă inițial unde poți testa această metodă.

Note:

  • Dacă nu adaugi o secvență de escape, decriptarea nu va ști când să „se oprească". Rezultatul vor fi date ilizibile/nule până la atingerea dimensiunii array-ului definit.
  • Asigură-te că schimbi cheile XOR pe care le-am folosit în exemplul meu.
  • Evită folosirea acelorași cuvinte de mai multe ori. Vor genera aceiași octeți și există riscul de a fi detectate.

Descărcare

Pentru a descărca soluția gata de utilizare, ia în considerare susținerea acestui blog 😘

Become a Patron