Skip to content

House of Apple 2

Forge edilmiş bir FILE'ın vtable'ını aralık içindeki _IO_wfile_jumps'a ayarla ve _IO_wfile_overflow'u tetikle ki _IO_wdoallocbuf, attacker-controlled bir _wide_data->_wide_vtable'ı dereference etsin; bu da hook olmadan kontrollü bir call verir.

Mechanism

Note

_IO_wfile_jumps, __libc_IO_vtables içindeki meşru bir libc vtable'ıdır, dolayısıyla ona işaret eden forge edilmiş bir FILE, glibc 2.24+ _IO_vtable_check aralık testini geçer. _IO_OVERFLOW'u sürmek ardından _IO_wfile_overflow'u dispatch eder, o da _IO_wdoallocbuf'ı çağırır, o da _IO_WDOALLOCATE(fp)'yi → fp->_wide_data->_wide_vtable->__doallocate(fp) olarak açar. Kritik nokta: ikincil _wide_data pointer'ı ve onun _wide_vtable'ı attacker-controlled heap data'sıdır ve vtable range check'ine tabi değildir. __doallocate slot'u system olan bir _wide_vtable (FILE öyle düzenlenir ki argüman "/bin/sh" olur) kontrollü bir call verir — baskın modern FSOP tekniğidir, hiçbir __malloc_hook/__free_hook gerektirmez.

Walkthrough

Ulaşılabilir yol (glibc libio/wfileops.c, wgenops.c):

wint_t _IO_wfile_overflow (FILE *f, wint_t wch) {
  if (f->_wide_data->_IO_write_base == NULL) _IO_wdoallocbuf (f);
}
void _IO_wdoallocbuf (FILE *fp) {
  if (fp->_wide_data->_IO_buf_base) return;
  if (!(fp->_flags & _IO_UNBUFFERED))
    if ((wint_t) _IO_WDOALLOCATE (fp) != WEOF) return;  /* _wide_vtable->__doallocate */
}

Kavramsal reçete:

  1. libc'yi leak'le (genelde bir heap adresi de).
  2. Bir FILE forge et: _flags'ta _IO_UNBUFFERED temiz (ve genelde bir shell-string ile başlar), buffer field'ları overflow yolu çalışacak şekilde set, vtable = &_IO_wfile_jumps (io-vtable-check-bypass.md).
  3. _wide_data'yı kontrollü belleğe yönelt (_IO_buf_base/_IO_write_base == NULL).
  4. _wide_data->_wide_vtable__doallocate slot'u system/one_gadget olan sahte bir tabloya ayarla.
  5. IO chain'e ekle (_IO_list_all üzerinde largebin attack ya da stdout/stderr ezmek) ve flush'ı exit/__malloc_assert/fflush üzerinden tetikle (fsop-via-io-list-all-io-flush-all-lockp.md).

Warning

_wide_data field offset'leri ve _wide_vtable slot index'i glibc'ye göre değişir; bazı 2.36+ hardening'leri wide yolun parçalarını korur. Her target libc için doğrula.

Detection

  • Flush list'inde, heap'e işaret eden bir _wide_vtable ile _IO_wfile_jumps kullanan bir FILE.
  • _IO_wdoallocbuf/_IO_WDOALLOCATE'ten allocator olmayan bir adrese yapılan indirect call.
  • Process teardown'undan önce gelen largebin/_IO_list_all write'ları.

Mitigation

  • vtable validation'ını ikincil _wide_vtable'a genişlet (tarihsel boşluk); wide-data call üzerinde CFI.
  • _IO_list_all write'ını reddetmek için safe-linking / bin-integrity hardening.
  • ASLR ve info-leak önleme.

References