İçeriğe atla
Yazılar

🦅 gokdogan

Statik PE Malware Triyaj Motoru

7 dk okuma
İçindekiler
  1. gokdogan’ın Anatomisi
  2. Neden “triyaj”?
  3. Tek bakışta gokdogan
  4. Tasarım ilkeleri
  5. Mimari ve pipeline
  6. 31 modül, beş katman
  7. Kimlik & kümeleme
  8. Yapı
  9. İçerik
  10. Davranış
  11. İstihbarat
  12. Karar modeli
  13. Raporlama ve çıktılar
  14. Mühendislik detayları
  15. Yanlış pozitifi kalibrasyonla yok etmek
  16. Anahtar-değişmez komşuluk araması
  17. İmzalı-enjektör maskesi: bir denge
  18. Çevrimdışı çekirdek, opt-in egress
  19. Windows’a özgü zorluklar
  20. Test stratejisi
  21. Kurulum ve kullanım
  22. Sınırlar ve kapanış

gokdogan’ın Anatomisi

Bir Windows çalıştırılabilirini hiç çalıştırmadan analiz eden, şeffaf ve gerekçeli bir triyaj kararı üreten bir motor. Bu sayfa; mimarisini, 31 modülünü, karar modelini ve arkasındaki mühendislik kararlarını baştan sona anlatır.

PowerShell terminalinde gokdogan’ın bir örnek dosyayı analiz edip çözülmüş string’leri, YARA eşleşmelerini ve 140 puanlık HIGH RISK kararını listelediği animasyonlu terminal kaydı.

01 · Problem

Neden “triyaj”?

Bir malware analistinin masasına günde yüzlerce, bazen binlerce örnek düşer. Her birini tersine mühendislikle, dinamik analizle incelemek imkânsızdır. İhtiyaç duyulan şey önceliklendirme: “Bu örneğe önce mi bakmalıyım?” sorusuna saniyeler içinde, güvenilir bir cevap.

gokdogan bir Windows PE dosyası alır, onu çalıştırmadan statik özelliklerini çıkarır ve şeffaf, gerekçeli bir karar üretir: LIKELY_CLEAN, SUSPICIOUS veya HIGH_RISK.

İsim, Türkçede peregrine falcon (gök doğanı) anlamına gelir — gökyüzünün en hızlı avcısı. Triyaj da hız işidir. (Paket, komut ve repo her yerde ASCII gokdogan’dır; çünkü ö/ğ Python paket adlarını ve URL’leri bozar.)

02 · Özet

Tek bakışta gokdogan

  • Ne yapar — Statik PE malware triyajı; örneği asla çalıştırmaz
  • Kod — ~4.500 satır Python · 31 modül · 173 test
  • Sabit bağımlılık — pefile · ppdeep (saf-Python ssdeep)
  • Opsiyonel — yara-python · py-tlsh
  • Karar — LIKELY_CLEAN / SUSPICIOUS / HIGH_RISK (eşik 30 / 60)
  • Çıkış kodları — 0 temiz · 2 şüpheli · 3 yüksek risk
  • Çıktılar — konsol · JSON · HTML · CSV/JSONL · ATT&CK Navigator · MISP
  • Kurulum — pip install gokdogan-triage

03 · İlkeler

Tasarım ilkeleri

Motorun tamamı, onu bir analist için doğru ve güvenilir kılan beş karar etrafında örgütlenir:

  • Saf fonksiyonlar → dataclass’lar — Her analizör, bytes/PE alıp dataclass döndüren saf bir fonksiyondur. Yeni aşama = bir modül + engine.py’de bir satır.
  • Varsayılan çevrimdışı — triage() çekirdeği asla ağa dokunmaz, örneği asla çalıştırmaz. Tek ağ özelliği (itibar) opt-in ve hash-only.
  • Denetlenebilir karar — Skor raporun kendisidir: her puanın insan-okur bir gerekçesi var. Gizli model yok.
  • FP’ye karşı kalibre — Eşikler tahminle değil, stok imzalı Windows ikililerine karşı ölçülerek ayarlandı.
  • Zarif çökme — Eksik YARA, bozuk kaynak ağacı, çözülemeyen import — her biri raporda bir nota dönüşür, çökmeye değil.

04 · Mimari

Mimari ve pipeline

Motor tek bir orkestratör fonksiyonun etrafında döner: engine.triage(). Her aşama, paylaşılan bir TriageReport yapısının tek bir dilimini doldurur; reporter’lar ve karar motoru yalnızca bu yapıyı okur. Böylece analiz ve sunum tümüyle ayrıktır — yeni bir yetenek eklemek, mevcut hiçbir şeyi bozmadan bir modül + bir satır yazmaktır.

Bir örneğin engine.triage() içindeki analiz modüllerinden geçip verdict aşamasında birleştiğini ve konsol, JSON, HTML, CSV/JSONL, ATT&CK Navigator ve MISP çıktılarına ulaştığını gösteren statik pipeline şeması.

05 · Analiz yüzeyi

31 modül, beş katman

Kimlik, yapı, içerik, davranış ve istihbarat olmak üzere beş analiz katmanını ve her birini besleyen modülleri sütunlar halinde gösteren tablo.

Kimlik & kümeleme

loader (PE parse, MD5/SHA1/SHA256, imphash, yapısal anomaliler, delay-load import’lar), rich (Rich header hash + checksum doğrulaması), fuzzy (ssdeep + opsiyonel TLSH; --compare), hashes (authentihash + impfuzzy), cluster (--cluster union-find), baseline (--baseline diff).

Yapı

entropy (bölüm + genel Shannon entropisi), packers (bilinen adlar + sezgiseller), blobs (yazılabilir bölümlerdeki entropi adaları → embedded-config), resources (.rsrc yürüyücüsü, gömülü PE + PNG ikon beyaz listesi), overlay, signature (Authenticode / WinVerifyTrust, çevrimdışı — geçerli imzayı kurcalanmıştan ayırır), dotnet (.NET CLR + obfuscator parmak izleri).

İçerik

strings_ext (ASCII/UTF-16 + IOC sınıflandırma), decoded (FLOSS-lite: XOR/ADD/ROL + Base64/hex kurtarma), stackstrings (desen tabanlı x86 stack-string, emülatörsüz), extractors (Discord/Telegram/stager aile config’i).

Davranış

exports (başlatma-mekanizması export’ları: ReflectiveLoader, DllRegisterServer, ServiceMain), capabilities (import + delay-import + export → davranış etiketleri; her kural minimum sayıda farklı API isabeti ister — yanlış pozitife karşı).

İstihbarat

attack (yetenekler/YARA → MITRE ATT&CK, taktiğe göre gruplu; Navigator layer export), yara_scan (opsiyonel; meta.weight doğrudan skoru besler), reputation (opt-in VirusTotal / MalwareBazaar hash-only sorgusu).

06 · Karar

Karar modeli

Puanlama kasıtlı olarak şeffaf ve toplamsaldır. Her sinyal bir puan ekler ve raporda o puanın gerekçesi yazılır — YARA kuralları kendi ağırlıklarını enjekte ederek sezgisellere üstün gelebilir.

LIKELY_CLEAN, SUSPICIOUS ve HIGH_RISK bantlarını 30 ve 60 eşikleriyle gösteren skor çubuğu ve sinyal başına temsili puan ağırlıkları.

Örnek bir gerekçe dökümü (demo örneği):

── Verdict ───────────────────────────────────────────────
  +  6  anomaly: PE header checksum does not match computed checksum
  + 18  capability: anti-recovery
  + 18  capability: persistence-registry
  + 30  YARA match: Shadow_Copy_Deletion
  + 15  YARA match: Injection_API_Cluster
  + 16  2 encoded IOC/payload string(s) recovered
  + 15  extracted config: Discord webhook
  ...
  HIGH RISK  (score 140, thresholds: suspicious ≥ 30, high risk ≥ 60)

Nüans: geçerli bir Authenticode imzası (−15) ciddi (sev-3) bir yeteneği maskeleyemez — o durumda karar SUSPICIOUS eşiğinin altına inemez (taban). Bu, imzalı-enjektör maskesini kırar ama kernel32’ü yanlış pozitif yapmaz.

07 · Raporlama

Raporlama ve çıktılar

Tek motor, birçok çıktı — terminal triyaj için, HTML vaka dosyası için, CSV dropzone için, JSON pipeline için, MISP paylaşımı için. HTML rapor tek dosyadır, gömülü CSS’lidir ve hiç dış istek yapmaz.

demo_suspicious.exe için 140 puanla HIGH RISK kararı veren HTML raporun karar gerekçesi, dosya bilgileri ve yetenekler bölümleri.

Aracın kendi güvenliği: malware string’leri markup içerebilir. HTML rapor her örnek-türevi değeri html.escape’ten geçirir — bir raporu açmak gömülü bir <script>’i asla çalıştıramaz (testle doğrulandı).

08 · Derin dalışlar

Mühendislik detayları

Yanlış pozitifi kalibrasyonla yok etmek

Bir triyaj aracını işe yaramaz yapan şey, temiz dosyaya kurt demesidir. Şifreli-config tespiti 150 stok imzalı sistem ikilisine karşı süpürüldü. İki ders: (1) 256 baytlık pencere entropi ölçmek için fazla küçük — gerçekten rastgele veri bile orada ortalama ~7.17 bit/byte verir (küçük örneklem yanlılığı), eşik sessizce ulaşılamazdı → 512 bayt pencere, 7.4 eşik. (2) Salt-okunur .rdata sertifika verisiyle meşru yüksek entropi taşır → tarama yalnızca yazılabilir bölümlerle sınırlandı → 0 yanlış pozitif.

Anahtar-değişmez komşuluk araması

Naif yaklaşım (255 anahtar × çıpa × tüm dosya) 800 KB’lık bir DLL’de ~2.440 ms sürüyordu. İçgörü: tek-baytlık XOR/ADD altında encoded[i] ⊕ encoded[i-1] anahtardan bağımsızdır.

plaintext[i] ⊕ plaintext[i-1]  ==  encoded[i] ⊕ encoded[i-1]

Tamponu bir kez “komşuluk dönüşümü”nden geçir (koca bir tamsayı kaydırmasıyla, C hızında), sonra anahtar bulmak her çıpa için tek bir alt-dize aramasına dönüşür — 2.440 ms → 133 ms, tam kapsama korunarak.

İmzalı-enjektör maskesi: bir denge

Geçerli bir imza güven verir (−15). Ama CreateRemoteThread + VirtualAllocEx + WriteProcessMemory üçlüsü olan, geçerli imzalı (çalınmış sertifika) bir enjektör bu krediyle temiz görünebiliyordu. İlk çözümüm (krediyi kısmak) kernel32’ü FP yaptı. Oturan denge: kredi düz −15 kalır, ama sev-3 yetenek varken imza kararı SUSPICIOUS eşiğinin altına itemez (taban). Ders: güvenlikte çoğu karar bir dengedir; “doğru” cevap iki uç senaryoyu da bozmayandır.

Çevrimdışı çekirdek, opt-in egress

İtibar tek ağ özelliğidir. Varsayılan kapalıdır, yalnızca SHA-256 gönderir (dosyayı asla), anahtar olmadan çalışmayı reddeder ve CLI katmanında iliştirilir — böylece triage() motoru kanıtlanabilir biçimde çevrimdışı kalır. Opsiyonel web servisi gövdeyi parça parça okur ve 64 MB sınır koyar (aşımda HTTP 413).

09 · Platform

Windows’a özgü zorluklar

  • ASCII olmayan yollar. yara-python, C tarafında “Masaüstü” gibi yolları sindiremiyordu → kuralları dosya yolu yerine içerik (sources=) olarak derledim.
  • PyInstaller sessiz modül düşürme. ASCII olmayan yol + editable kurulum bazı modülleri atlıyordu → --paths . şart.
  • Legacy kod sayfası (cp1254). Kutu-çizim karakterleri dosyaya yönlendirilince UnicodeEncodeError fırlatıyordu → çıktı akışını saran, gerektiğinde ASCII’ye çeviren bir katman.
  • 64-bit ctypes. Authenticode’da işaretçi döndüren crypt32 fonksiyonlarında restype ayarlamayı unutursanız adresler kırpılır.

10 · Test

Test stratejisi

173 test / ~1.900 satır. Birim testleri her analizörü sentetik girdilerle izole eder (XOR/base64 payload’lar, sahte PE tamponları, ekilmiş entropi adaları). Entegrasyon süiti tüm pipeline’ı gerçek sistem ikililerine (notepad.exe, kernel32.dll, mmc.exe) karşı çalıştırır ve stok Microsoft ikililerinin asla HIGH_RISK çıkmadığını doğrular. Ağ kodu enjekte edilmiş HTTP mock’larıyla test edilir — gerçek dış çağrı yok.

11 · Kullanım

Kurulum ve kullanım

PyPI’dan:

# kur
pip install gokdogan-triage
# tek örnek için tam rapor
gokdogan sample.exe
# vaka dosyası için kendine yeten HTML
gokdogan sample.exe --html report.html
# bir dropzone'u tek sıralanabilir tabloya
gokdogan C:\dropzone --csv triage.csv
# aileye göre kümele / bilinen-iyi ile diff'le
gokdogan C:\dropzone --cluster
gokdogan suspect_svchost.exe --baseline C:\Windows\System32\svchost.exe
# opt-in itibar: yalnızca SHA-256 gönderir (dosyayı asla)
gokdogan sample.exe --reputation --vt-key $VT_API_KEY

Web servisi (tarayıcıdan yükle, HTML rapor al):

pip install "gokdogan-triage[web]"
uvicorn gokdogan.web:app --host 127.0.0.1 --port 8000

Python gerektirmeden: Releases sayfasından gokdogan-setup.exe (per-user kurucu) veya tek-dosya gokdogan.exe.

12 · Kapanış

Sınırlar ve kapanış

gokdogan yalnızca statik triyaj yapar. Örneği asla çalıştırmaz ve verdiği karar bir önceliklendirme sinyalidir, kesin bir sınıflandırma değil. Gerçek malware’i her zaman izole bir analiz VM’inde ele alın.

Bu proje bana “kod yazmak” ile “güvenilir bir araç yapmak” arasındaki farkı öğretti: asıl iş, temiz dosyaya yanlışlıkla kurt dememek; doğru soruyu sorup 2.440 ms’yi 133’e indirmek; ve “çalışan kod”u başkasının tek komutla kurabileceği bir şeye dönüştürmek.

gokdogan — açık kaynak (MIT). Geri bildirime ve önerilere açığım.

github.com/IlkerUnver00/gokdogan-triage · pip install gokdogan-triage · canlı mimari sayfası

⚠ Triaj, mahkûmiyet değil. Örnek asla çalıştırılmaz; karar bir önceliklendirme sinyalidir.