Intel CET Shadow Stack Bypass via Counterfeit Objects¶
Counterfeit Object-Oriented Programming (COOP): mevcut tüm C++ virtual fonksiyonlarını meşru vtable call site'ları üzerinden chain'le; böylece hiçbir return address bozulmaz ve CET shadow stack tamamen atlatılır.
Mechanism¶
Neden çalışır
CET shadow stack'i tam olarak tek bir şeyi korur:
backward edge'i. Bir RET, korumalı return-address kopyasına karşı kontrol
edilir. COOP, attacker-controlled bir RET'i hiç çalıştırmayarak kazanır —
hesaplamasını tamamen, programın zaten meşru biçimde aldığı forward edge'lerden
inşa eder.
- Attacker counterfeit C++ object'leri forge eder: seçilmiş bir
vptrartı birkaç seçilmiş data alanı, attacker-controlled bellekte (örn. heap overflow veya use-after-free yoluyla) yerleştirilir. Her sahte nesneninvptr'si gerçek bir vtable'ı gösterir, böylece mevcut bir virtual call gerçek bir virtual fonksiyona dispatch eder. - Chain, bir main-loop gadget (ML-G) tarafından sürülür: object pointer'ların bir container/array'i üzerinde iterate eden ve her birinde bir virtual method çağıran gerçek bir virtual fonksiyon — örneğin bir loop veya bir container destructor'ı. Attacker, o container'ı counterfeit object'lerden oluşan bir array'e işaret ettirerek tek bir meşru call site'ının attacker'ın seçtiği bir virtual fonksiyon dizisini (vfgadget'leri) çağırmasını sağlar.
- Destekleyici vfgadget'ler işi yapar:
ARITH-G/W-G, counterfeit object alanlarını örtüştürerek aritmetik ve memory write yapar; böylece bir gadget'ın output alanı sonraki gadget'ın input'una alias olur;LOAD-R64-Gx64'te argument register'larını set eder;ML-ARG-Gx86'da argument'ları member değişkenleri üzerinden geçirir;REC-Grecursion sağlar. - Kritik olarak, her transfer gerçek bir vtable slot'u üzerinden gerçek bir
virtual-function girişine yapılan bir indirect
CALL'dur. Bozuk bir return address yoktur (shadow stack her callee içinde eşleşmişCALL/RETçiftleri görür) ve off-pad iniş yoktur (her virtual fonksiyon girişi geçerli birENDBR'dır, dolayısıyla kaba IBT da geçer).
Bypass invariant'ı: backward edge'e dayalı bir savunma, tamamen meşru forward virtual call'lar olarak ifade edilmiş bir hesaplamayı göremez. Shadow stack'in eşleşmiş-çift garantisi sağlanırken attacker yine de Turing-complete kontrol elde eder.
Walkthrough¶
Bu, yayımlanmış COOP yapısı üzerine kavramsal bir akıl yürütmedir; onu turnkey bir exploit olarak değil, bir attacker'ın izlediği tarif olarak değerlendir.
1. Hedef call site (bir ML-G) zaten mevcuttur — object pointer'ların bir container'ı üzerindeki bir loop içindeki bir virtual call:
// existing program code (simplified)
for (auto *o : objects) // attacker controls 'objects' storage
o->vfunc(); // indirect CALL [vtable+slot] -> real virtual fn
2. Attacker counterfeit object'leri yerleştirir, böylece loop seçilmiş bir vfgadget dizisini dispatch eder ve alanlar data flow için örtüşecek şekilde düzenlenir:
objects[0] -> {vptr=&Vtbl_A, f0=...} // ARITH-G: writes into objects[1].f0
objects[1] -> {vptr=&Vtbl_B, f0=...} // W-G: stores to attacker target
objects[2] -> {vptr=&Vtbl_C, ...} // LOAD-R64-G: load arg regs, then call
...
3. Loop'u tetikle. Her iterasyon normal bir virtual dispatch'tir:
CALL qword ptr [rax] ; rax = counterfeit vptr -> real virtual function
... function executes, RET matches its own CALL (shadow stack: OK) ...
; loop advances to next counterfeit object, repeat
Hiçbir RET attacker-injected koda return etmez; shadow stack hiçbir uyuşmazlık
görmez.
Backward-edge savunmaları bunu neden kaçırır
Shadow Stack yalnızca her RET'in korumalı kopyayla eşleştiğini doğrular —
burada doğrudur, çünkü attacker kendi caller'larına return eden bütün
fonksiyonları yeniden kullanır. Düz IBT de geçer: virtual-function girişleri
COOP'un kullandığı tek hedef tipi olan ENDBR'ı taşır. COOP'un Turing-complete
olduğu gösterildi ve gerçek hedeflere (IE10, Firefox 36) karşı demonstre edildi;
döneminin birkaç C++-aware CFI savunmasını yendi.
Mitigation¶
(Artık risk / onu gerçekte ne durdurur.) COOP, shadow stack veya kaba IBT
tarafından durdurulmaz. Çıtayı yükselten şey, belirli bir indirect/virtual call
site'ının hangi fonksiyona ulaşabileceğini sınırlayan forward-edge type
checking'dir: FineIBT ve Clang CFI'nin vcall/type-id
kontrolleri, hedef tipi call site'la eşleşmeyen bir counterfeit vptr'yi reddeder
ve vfgadget kümesini çökertir. Object-type-integrity / vtable-protection şemaları
benzer biçimde dispatch'ten önce runtime tipini doğrular. CET'e karşı ilgili
whole-function reuse için ayrıca daha geniş
COOP-for-CET-bypass ve
block-oriented programming ailelerine bak.
References¶
- Schuster, Tendyck, Liebchen, Davi, Sadeghi, Holz. Counterfeit Object-oriented Programming: On the Difficulty of Preventing Code Reuse Attacks in C++ Applications. IEEE S&P 2015. — https://www.ieee-security.org/TC/SP2015/papers-archived/6949a745.pdf
- dangokyo. Counterfeit Object-oriented Programming (COOP) — notes. — https://dangokyo.wordpress.com/2018/06/28/counterfeit-object-oriented-programming/
- Malvica, Matteo. Bypassing Intel CET with Counterfeit Objects. OffSec. — https://www.offsec.com/blog/bypassing-intel-cet-with-counterfeit-objects/