Obfuscation ve Packing Teknikleri: Kodun Gizlenmesi
Zararlı yazılımların kendilerini analiz araçlarından ve imza tabanlı tespitten gizleme yöntemleri.
Zararlı yazılım yazarları, statik analiz ve imza tabanlı antivirüs tespitini zorlaştırmak için kodlarını çeşitli tekniklerle gizler. Bu makale, en yaygın obfuscation ve packing yöntemlerine ve bunların analiz sürecine etkisine odaklanır.
Packing Nedir?
Packing (paketleme), orijinal çalıştırılabilir kodun sıkıştırılıp/şifrelenip, çalışma zamanında kendini bellekte açan (unpack eden) küçük bir "stub" (açıcı kod) ile sarılmasıdır. Program çalıştırıldığında:
- Önce stub çalışır, şifreli/sıkıştırılmış orijinal kodu bellekte çözer.
- Kontrol, çözülmüş orijinal koda (Original Entry Point - OEP) devredilir.
Bu sayede, dosyanın disk üzerindeki hâli (statik analiz açısından) anlamsız, rastgele görünen veriden ibarettir — gerçek kod sadece çalışma anında, bellekte, geçici olarak "açık" hâlde bulunur.
UPX: Yaygın Bir Örnek
UPX (Ultimate Packer for eXecutables), hem meşru yazılımlarda (dosya boyutunu küçültmek için) hem de zararlı yazılımlarda (basit imza tespitini atlatmak için) sıkça kullanılan açık kaynaklı bir packer'dır. UPX ile paketlenmiş bir dosya, upx -d komutuyla nispeten kolay bir şekilde geri açılabilir (unpack edilebilir) çünkü format iyi bilinir ve dokümante edilmiştir — ancak zararlı yazılım yazarları genelde UPX'in header'ını manuel olarak bozarak (standart unpacker'ların tanımasını engelleyerek) bu kolaylığı da zorlaştırmaya çalışır.
Manuel Unpacking: OEP Bulma Stratejisi
Özel (custom) packer'larla paketlenmiş, otomatik araçların açamadığı örnekler için analistler manuel unpacking yapar. Genel strateji:
- Bir debugger (x64dbg gibi) ile programı çalıştırıp, stub'ın kod çözme işlemini bitirip orijinal koda atlayacağı ana (Original Entry Point) kadar ilerlemek.
- Bu noktaya bir breakpoint koymanın yaygın bir yöntemi: bellek yazma breakpoint'i koyup, stub'ın kod çözdüğü bellek bölgesinin DIŞINA (orijinal koda) atlayan ilk
jmp/callkomutunu yakalamak. - OEP'e ulaşıldığında, bellek o anki hâliyle diske dump edilir (örneğin Scylla gibi bir araçla) ve import table'ı yeniden inşa edilerek (import table genelde packer tarafından da bozulmuş/gizlenmiş olur) çalıştırılabilir, analiz edilebilir bir dosya elde edilir.
Kod Seviyesinde Obfuscation Teknikleri
Packing'in ötesinde, kodun mantığının kendisini karmaşıklaştıran teknikler de yaygındır:
- String encryption: Metin dizilerinin (C2 adresleri, hata mesajları) her biri ayrı ayrı şifrelenip, sadece kullanılacakları anda çözülür — statik string taramasını etkisiz kılar.
- Control flow flattening: Normal, okunabilir if/else ve döngü yapıları, tek bir devasa switch-case yapısına dönüştürülür; bu, kodun mantıksal akışını insan gözüyle takip etmeyi ciddi şekilde zorlaştırır.
- API hashing: Programın hangi Windows API fonksiyonlarını çağırdığı, fonksiyon isimleri yerine bu isimlerin hash değerleri üzerinden çözümlenir — bu, statik import table analizini (yukarıdaki makalede anlatılan) tamamen etkisiz hâle getirir çünkü import table'da anlamlı fonksiyon isimleri görünmez.
Pratik Senaryo
Bir analist, statik analizde import table'ının neredeyse boş olduğunu ve tüm string'lerin anlamsız göründüğünü fark ediyor — bu, güçlü bir packing/obfuscation göstergesi. Dosyayı bir debugger'da çalıştırıp OEP'e ulaşana kadar ilerliyor, bu noktada belleği dump ediyor. Dump edilen kod artık okunabilir string'ler ve normal bir import table içeriyor — meğer orijinal kod paketlenmeden önce tamamen standart, hatta nispeten basit bir bilgi çalma (info-stealer) zararlı yazılımıymış. Packing, kodun kendisini karmaşıklaştırmamış, sadece analiz sürecini bir adım geciktirmiş.
Bu makale, obfuscation ve packing tekniklerinin orta-ileri seviye teknik bir özetidir; SiberCrew ekibi tarafından hazırlanmış özgün içeriktir.