Loop Gadget / Main-Loop Gauge (COOP control)¶
Counterfeit Object-Oriented Programming (COOP)'in kalbindeki dispatcher vfgadget: saldırganın düzenlediği counterfeit object container'ını dolaşan ve her birinde bir virtual function çağıran gerçek bir loop — return address forge etmeden bütün method'ları zincirler.
Mechanism¶
Note
COOP (Schuster et al., IEEE S&P 2015), legitimate virtual call site'lar
üzerinden ulaşılan var olan bütün virtual function'ları ("vfgadget")
yeniden kullanarak coarse CFI'yı atlatır. Main-loop gadget (ML-G, namıdiğer
"Looper") burada kilit taşıdır: binary içinde, object pointer'lardan oluşan
bir container üzerinde iterate eden ve her element için bir virtual call
dispatch eden gerçek bir loop'tur. Defender'ın anlaması gereken invariant
şu: yalnızca "indirect target geçerli bir function entry mi / herhangi bir
vtable'daki bir method mu?" diye kontrol eden bir CFI policy, COOP'in her
adımı tarafından sağlanır, çünkü her call gerçek bir call site üzerinden
gerçek bir virtual-function entry'ye iner. Hiçbir return address bozulmadığı
için shadow-stack / return-edge savunmaları hiçbir şey görmez. Saldırgan
counterfeit C++ object'leri sağlar (sahte vptr → sahte vtable); ML-G'nin
kendi loop'u control-flow motoru haline gelir, argument-loader ve invoker
vfgadget'lar veriyi örtüşen object field'ları üzerinden geçirir.
Bir defender için çıkarım: forward-edge koruması precise olmalı (type/signature-checked target'lar, sadece "herhangi bir vtable method" değil) ve object integrity (vptr provenance) önemlidir. Coarse-grained CFI tek başına ML-G dispatch'ini kısıtlamaz.
Walkthrough¶
Kavramsal olarak ML-G, bir container'dan object pointer'ları okuyan ve her iteration'da bir virtual call dispatch eden bir loop'tur. Açıklayıcı bir şekil (çalışan bir exploit değil):
mov rbx, [rcx+0x40] ; load array base from a counterfeit object field
loop:
mov rax, [rbx] ; rax = next object pointer
mov rdx, [rax] ; rdx = its (fake) vtable
call [rdx+OFF] ; legitimate virtual call -> a vfgadget
mov rbx, [rbx+0x20] ; advance to next element
test rbx, rbx
jnz loop
Her call [rdx+OFF], coarse bir CFI target set'inin izin verdiği tam da o tür
indirect call'dur. COOP "program"ı, tıpkı bir ROP chain'in return address
dizisi olması gibi, counterfeit object'lerin önceden düzenlenmiş dizisidir.
Warning
Bu, defansif boşluğu anlamaya yönelik kavramsal bir control-flow taslağıdır, silahlandırılmış bir chain değil. Gerçek COOP, counterfeit object'leri yerleştirmek için bir memory-write primitive'i ve target binary'de somut bir ML-G/vfgadget set'i gerektirir; offset'ler tamamen target'a özgüdür.
COOP vfgadget taksonomisi (Schuster et al.)
Paper, yeniden kullanılabilir küçük bir gadget rolleri set'i adlandırır. Takip eden analizlerde atıf yapılan temsili tipler:
ML-G main-loop gadget (the Looper / dispatcher)
ML-ARG-G main loop that also forwards arguments to callees
ARG-G argument loader (populate a register/field for the next call)
INV-G invoker (call an arbitrary API function pointer)
W-SA-G write gadget (store-to-attacker-address)
W-COND-G conditional / loop-counter write
Geri kalanı birbirine composable yapan şey ML-G'dir: virtual dispatch'e yeniden giren bir loop olmadan, tek tek vfgadget'lar zincirlenemez.
Mitigation¶
Precise forward-edge CFI, gelişigüzel COOP dispatch'ini bozar: Clang CFI ve FineIBT yalnızca "bir function mu" değil, call-target'ın type'ını ya da tag'ini kontrol eder. COOP, COOP against Intel CET için motive edici bypass'tır: COOP hiçbir zaman return address'leri manipüle etmediğinden, tek başına bir shadow stack onu durduramaz — önemli olan özellik forward-edge precision'dır. Daha geniş expressivity tartışması için control-flow bending'i karşılaştır.