Win10 2004 EPROCESS offset changes for token payloads¶
Windows 10 2004 (20H1),
_EPROCESSfield offset'lerini yeniden düzenledi veUniqueProcessId/ActiveProcessLinks/Token'ı hard-code eden her token-stealing payload'unu sessizce bozdu — bir güvenlik açığı değil, bir taşınabilirlik ve güvenilirlik dersi; ama hem saldırganların hem savunmacıların kernel-shellcode versiyonlama mantığını şekillendiren bir ders.
Mechanism¶
Note
Bir token-stealing payload, SYSTEM process'inin access token'ını mevcut
process'e kopyalamak için kernel'in process list'ini gezer. Bunu _EPROCESS
içindeki üç offset'i hard-code ederek yapar: UniqueProcessId (SYSTEM'i, PID 4'ü
tanımak için), ActiveProcessLinks (tüm process'leri çift yönlü bağlı listeye
dizen _LIST_ENTRY) ve Token (security token'a giden _EX_FAST_REF). Payload'un
varsaydığı invariant, bu offset'lerin sabit olduğudur. Ama değiller:
_EPROCESS, Microsoft'un build'ler arasında yeniden yerleşime soktuğu internal,
dokümante edilmemiş bir structure'dır. Eski Windows 10 ile 2004/20H1 arasında, üç
offset de ciddi şekilde kaydı. Yanlış build için derlenmiş bir payload, list'i
gezerken yanlış field'ı dereference eder — "tek bir byte farkı bile kötü bir
dereference'a yol açar" — ve escalate etmek yerine makineyi bug-check'e (BSOD)
sokar.
Çıkarım yapısaldır: hard-code edilmiş offset'ler bir exploit/payload'u tam olarak tek bir kernel build'ine bağlar, dolayısıyla payload'lar ya build'i detect edip offset'leri seçmeli ya da runtime'da offset'leri dinamik olarak resolve etmelidir.
Walkthrough¶
Token-steal'in kavramsal akışı ve 20H1'in onu neden bozduğu (public keramas ve Connor McGarr write-up'larından — burada canlı offset'ler yeniden verilmiyor):
currentüzerine anchor at. Payload, mevcut_KTHREAD/_EPROCESS'i (klasik olarak_KPCR/gsbase üzerinden) elde eder ve başlangıç_EPROCESS'ini alır.ActiveProcessLinks'i gez._LIST_ENTRY'yi ileri doğru takip et, her node'da list-offset'i çıkararak_EPROCESSbase'ini geri kazan.- SYSTEM'i eşle.
UniqueProcessId'yi4ile karşılaştır; SYSTEM, maksimum ayrıcalıklı bir token'ın kaynağıdır. Token'ı kopyala. SYSTEM'inTokenfast-ref'ini oku ve mevcut process'inToken'ı üzerine yaz, sonra temizce return et. Tam primitive için eprocess-token-stealing, bunun bir code-exec/SMEP-bypass adımının üzerine nasıl bindiği için ise token-stealing-shellcode-smep-bypass'a bakın.- 20H1 neyi değiştirdi. 2-4 adımlarındaki üç offset'in her biri taşındı. 1909'a
ayarlanmış bir payload artık
UniqueProcessId'yi yanlış slot'tan okur, asla PID 4 ile eşleşmez (ya da yanlışlıkla eşleşir) veActiveProcessLinks'i bir non-list field üzerinden gezer — anlık birBSOD.
Warning
Yayımlanmış hiçbir offset üçlüsünü kalıcı/evrensel olarak görmeyin. Doğru
mühendislik yanıtı (public kod'da da kullanılan), sabitleri içine gömmek yerine
OS build'ini detect etmek (örn. NtBuildNumber / KUSER_SHARED_DATA) ve
build-başına bir offset table'ını index'lemek, ya da offset'leri runtime'da
sembollerden resolve etmektir.
Savunmacılar/araştırmacılar offset'leri nasıl yeniden hesaplar
- Tam hedef build üzerinde WinDbg:
dt nt!_EPROCESSileUniqueProcessId,ActiveProcessLinks,Token'ı inceleyin. - Canlı bir kernel olmadan cross-version diffing için, Windows build başına parse
edilmiş
_EPROCESSlayout'larını yayımlayan Vergilius Project. - Bu, bir savunmacının meşru bir
Token'ın nerede değişmesi gerektiğini ve gerekmediğini bilen, build-aware bir detection yazmak için kullandığı aynı prosedürdür.
Detection¶
- Davranışsal (build-agnostic): başarılı bir token steal'in etkisi, offset'ler
kaysa bile invariant'tır — bir non-SYSTEM process aniden SYSTEM token'ı sunar
(
Token/_EX_FAST_REF'i artık SYSTEM'inkine eşittir). Bir process'in token'ını beklenen token'ıyla karşılaştıran EDR/kernel callback'leri (PsSetCreateProcessNotifyRoutine, object-callback veya periyodik integrity scan'ler), hangi build'in offset'leri kullanılmış olursa olsun sonucu yakalar. - Walk'ın telemetry'si:
ActiveProcessLinks'i beklenmedik bir context'ten (non-image, RWX ya da yakın zamanda allocate edilmiş executable kernel memory) gezen kernel shellcode güçlü bir sinyaldir; CFG/HVCI/kCET violation event'leriyle eşleştirin. - Crash forensics: bir kernel write primitive'inin hemen ardından gelen bir bug-check dalgası (örn. attacker context'inde invalid pointer dereference) çoğu zaman, patch'lenmiş/ yükseltilmiş bir build'e karşı bayatlamış offset'ler kullanan bir payload'dur — crash-dump triyajında işe yarayan bir "failed exploit" göstergesi.
Mitigation¶
- Patch'lenebilir bir CVE değil — bu bir offset drift'idir, dolayısıyla uygulanacak bir fix yoktur; bunun yerine ilgili kernel mitigation'ları, payload'un dayandığı tekniği sertleştirir:
- HVCI / Hypervisor-Protected Code Integrity ve kCET/shadow stack'ler, hangi offset'leri kullanacağından bağımsız olarak, imzasız token-stealing shellcode'unu en baştan execute etmeyi zorlaştırır.
- VBS / Credential Guard ve KASLR, process list'i ve SYSTEM
_EPROCESS'ini güvenilir şekilde bulmanın maliyetini yükseltir. - Build'leri güncel tut: payload'lar build'e bağlı olduğundan, desteklenen, patch'li build'lerde kalmak; eski layout'lara ayarlanmış in-the-wild kit'lerin sessizce escalate etmek yerine yanlış ateşlemesi (ve gürültülü şekilde crash etmesi) anlamına gelir.