VirtualBox Slirp NAT Packet Heap Exploitation
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
TL;DR
- VirtualBox, yoğun şekilde değiştirilmiş bir Slirp fork’u içerir; paket tamponları (mbufs) inline metadata ve function-pointer callbacks (
pfFini,pfDtor) içeren özel bir zone allocator içinde yaşar. - Misafir, güvenilen
m->m_lendeğerini saldırgan kontrollü bir IP header length ile yeniden yazabilir; bu sonraki tüm bounds kontrollerini yok eder ve hem infoleak hem de overwrite primitives sağlar. - checksum
0ve aşırı büyükip_leniçeren UDP paketlerini suistimal ederek, misafir mbuf tails’lerini ve komşu chunk’ların metadata’sını exfiltrate edip heap ve zone adreslerini öğrenebilir. - Özenle hazırlanmış IP options sağlamak,
ip_stripoptions()’un yerinde çok fazla veriyimemcpy()yapmaya zorlar; böylece saldırgan sonraki mbuf’unstruct itembaşlığını overwrite edipzonealanını tamamen kontrol edilen verilere işaret ettirebilir. - Bozulmuş mbuf’un free edilmesi, saldırgan tarafından sağlanan argümanlarla
zone->pfFini()’yi tetikler; bunumemcpy@plt’e işaret ettirmek, non-PIE VirtualBox binary içindeki GOT girdilerine veya diğer kontrol verilerine yönlendirilebilecek arbitrary copy/write primitive sağlar.
Paket ayırıcı yapısı
VirtualBox, her gelen Ethernet frame’ini zone_clust adlı arayüz-başı bir zone’dan ayırır. Her 0x800-byte’lık veri chunk’ının önünde bir inline header bulunur:
struct item {
uint32_t magic; // 0xdead0001
void *zone; // uma_zone_t pointer with callbacks
uint32_t ref_count;
LIST_ENTRY(item) list; // freelist / used list links
};
When an mbuf is freed the call stack m_freem -> ... -> slirp_uma_free() trusts the inline header:
uma_zfree_arg()recomputesitem = (struct item *)mem - 1and should validateitem->zone, butAssert()is compiled out in release builds.slirp_uma_free()loadszone = item->zoneand unconditionally executeszone->pfFini(zone->pData, data_ptr, zone->size)followed byzone->pfDtor(...).
Therefore, any write-what-where into the mbuf header translates into a controlled indirect call during free().
Infoleak via m->m_len override
At the top of ip_input() VirtualBox added:
if (m->m_len != RT_N2H_U16(ip->ip_len))
m->m_len = RT_N2H_U16(ip->ip_len);
Because the assignment happens before verifying the IP header, a guest can advertise any length up to 0xffff. The rest of the stack (ICMP, UDP, fragmentation handlers, etc.) assumes m->m_len is trustworthy and uses it to decide how many bytes to copy off the mbuf.
IP başlığını doğrulamadan önce atama yapıldığı için guest 0xffff’e kadar herhangi bir uzunluk beyan edebilir. Yığının geri kalanı (ICMP, UDP, fragmentation handlers, vb.) m->m_len’in güvenilir olduğunu varsayar ve mbuf’tan kaç bayt kopyalanacağına buna göre karar verir.
Use UDP packets with checksum 0 (meaning “no checksum”). The NAT fast-path forwards m->m_len bytes without inspecting payload integrity, so inflating ip_len causes Slirp to read past the real buffer and return heap residues to the guest or to a cooperating external helper beyond the NAT. Because the chunk size is 2048 bytes, the leak can include:
Checksum’u 0 olan UDP paketleri kullanın (“no checksum” anlamına gelir). NAT fast-path, payload bütünlüğünü incelemeden m->m_len baytını ilettiği için ip_len’i şişirmek Slirp’in gerçek buffer’ın ötesini okumasına ve heap residues’ı guest’e veya NAT ötesinde işbirlikçi bir yardımcıya geri vermesine neden olur. Chunk boyutu 2048 bayt olduğu için leak şunları içerebilir:
-
The next mbuf’s inline
struct item, revealing the freelist order and the realzonepointer. -
Heap cookies such as
magicfields, helping to craft valid-looking headers when performing corruptions later. -
Bir sonraki mbuf’un inline
struct item’i; freelist sırasını ve gerçekzoneişaretçisini açığa çıkarır. -
magicalanları gibi heap cookies; daha sonra yapılacak bozulmalarda geçerli görünümlü başlıklar hazırlamaya yardımcı olur.
Overwriting neighbouring chunk headers with IP options
The same bogus length can be turned into an overwrite primitive by forcing the packet through ip_stripoptions() (triggered when the IP header has options and the payload is UDP/TCP). The helper computes a copy length from m->m_len and then calls memcpy() to slide the transport header over the stripped options:
Aynı sahte uzunluk, paketi ip_stripoptions() üzerinden geçirmekle (IP başlığı seçenek içerdiğinde ve payload UDP/TCP olduğunda tetiklenir) bir overwrite primitive’ine dönüştürülebilir. Helper, m->m_len’den bir kopyalama uzunluğu hesaplar ve ardından transport header’ı temizlenen seçeneklerin üzerine kaydırmak için memcpy() çağırır:
-
Supply a long
ip_lenso the computed move length extends past the current mbuf. -
Include a small number of IP options so Slirp enters the stripping path.
-
When
memcpy()runs, it reads from the following mbuf and writes over the current mbuf’s payload and inline header, corruptingmagic,zone,ref_count, etc. -
Hesaplanan taşıma uzunluğunun mevcut mbuf’un ötesine uzanmasını sağlamak için uzun bir
ip_lenverin. -
Slirp’in stripping path’ine girmesi için az sayıda IP option ekleyin.
-
memcpy()çalıştığında, bir sonraki mbuf’dan okur ve mevcut mbuf’un payload’u ile inline header’ı üzerine yazar; böylecemagic,zone,ref_countvb. bozulur.
Because the allocator keeps packets from the same interface contiguous on the freelist, this overflow deterministically hits the next chunk after modest heap grooming.
Allocator, aynı arayüze ait paketleri freelist üzerinde bitişik tuttuğundan, bu overflow mütevazı bir heap grooming’den sonra deterministik olarak bir sonraki chunka isabet eder.
Forging uma_zone_t to hijack pfFini
Once the adjacent struct item is corruptible, the exploit proceeds as follows:
Komşu struct item bozulabilir hale gelince, exploit şu şekilde ilerler:
- Use leaked heap addresses to build a fake
uma_zonestructure inside a mbuf fully controlled by the guest. Populate:
pfFiniwith the PLT entry ofmemcpy().pDatawith the desired destination pointer (e.g. GOT entry, vtable slot, function pointer array).sizewith the number of bytes to copy.- Optional:
pfDtoras a second stage call (e.g. to invoke the newly-written function pointer).
-
Overwrite the target mbuf’s
zonefield with the pointer to the fake structure; adjustlistpointers so freelist bookkeeping remains consistent enough to avoid crashes. -
Free the mbuf.
slirp_uma_free()now executesmemcpy(dest=pData, src=item_data, n=size)while the mbuf still contains guest-controlled data, yielding an arbitrary write. -
Leaked heap adreslerini kullanarak guest tarafından tamamen kontrol edilen bir mbuf içinde sahte bir
uma_zoneyapısı oluşturun. Şunları doldurun:
pfFini’yimemcpy()’nin PLT girdisi ile ayarlayın.pData’yı istenen hedef pointer ile ayarlayın (ör. GOT girdisi, vtable slotu, fonksiyon pointer dizisi).size’ı kopyalanacak bayt sayısı ile ayarlayın.- Opsiyonel: ikinci aşama çağrısı için
pfDtor(ör. yeni yazılan fonksiyon pointer’ını çalıştırmak için).
- Hedef mbuf’un
zonealanını sahte yapıya işaret eden pointer ile overwrite edin; freelist bookkeeping çöküşleri önleyecek kadar tutarlı kalacak şekildelistpointer’larını ayarlayın. - Mbuf’u free edin.
slirp_uma_free()artık mbuf hala guest-kontrollü veri içerirkenmemcpy(dest=pData, src=item_data, n=size)çalıştırır ve bu da arbitrary write sağlar.
Because the Linux VirtualBox binary is non-PIE, PLT addresses for memcpy and system are fixed and can be used directly. The guest can also stash strings such as /bin/sh inside another mbuf that remains referenced when the hijacked call executes.
Linux VirtualBox binary’si non-PIE olduğu için memcpy ve system için PLT adresleri sabittir ve doğrudan kullanılabilir. Guest ayrıca /bin/sh gibi stringleri, kaçırılmış çağrı çalıştırıldığında referanslı kalan başka bir mbuf içine de saklayabilir.
Heap grooming via fragmentation
Slirp’s per-interface zone is 3072 chunks deep and initially carved as a contiguous array whose freelist is traversed from high addresses downward. Deterministic adjacency can be achieved by:
Slirp’in arayüz başına zone’u 3072 chunk derinliğindedir ve başlangıçta freelist’in yüksek adreslerden aşağı doğru dolaştığı bitişik bir dizi olarak ayrılmıştır. Deterministik adjacency şu yollarla sağlanabilir:
-
Flooding the NAT with many
IP_MFfragments of constant size so the reassembly code allocates predictable mbuf sequences. -
Recycling specific chunks by sending fragments that time out, forcing frees back into the freelist in LIFO order.
-
Using knowledge of the freelist walk to place the future victim mbuf right after the mbuf that will carry the IP options overflow.
-
Yeniden birleştirme kodunun öngörülebilir mbuf dizileri ayırması için sabit boyutlu çok sayıda
IP_MFfragmanı ile NAT’ı flood etmek. -
Süresi dolan fragmentler göndererek belirli chunk’ları recycle etmek; bu, frees’ların LIFO sırayla freelist’e dönmesine zorlar.
-
Freelists yürüyüşü bilgisini kullanarak, ilerideki hedef mbuf’u IP options overflow’unu taşıyacak mbuf’un hemen sonrasına yerleştirmek.
This grooming ensures the overflow hits the targeted struct item and that the fake uma_zone remains in-bounds of the leak primitive.
Bu grooming, overflow’un hedeflenen struct item’e isabet etmesini ve sahte uma_zone’un leak primitive sınırları içinde kalmasını garanti eder.
From arbitrary write to host code execution
With the memcpy-on-free primitive:
- Copy an attacker-controlled
/bin/shstring and command buffer into a stable mbuf. - Use the primitive to overwrite a GOT entry or indirect callsite (e.g. a function pointer inside the NAT device state) with the PLT entry of
system(). - Trigger the overwritten call. Because VirtualBox runs the NAT device inside the host process, the payload executes with the privileges of the user running VirtualBox, allowing a guest-to-host escape.
Alternative payloads include planting a miniature ROP chain in heap memory and copying its address into a frequently-invoked callback, or repointing pfFini/pfDtor themselves to chained gadgets for repeated writes.
memcpy-on-free primitive’i ile:
- Saldırgan-kontrollü bir
/bin/shstringini ve komut buffer’ını kararlı bir mbuf içine kopyalayın. - Primitive’i kullanarak bir GOT girdisini veya dolaylı çağrı noktasını (ör. NAT device state içindeki bir fonksiyon pointer’ı)
system()’ın PLT girdisi ile overwrite edin. - Overwrite edilmiş çağrıyı tetikleyin. VirtualBox NAT cihazını host süreci içinde çalıştırdığı için payload, VirtualBox’ı çalıştıran kullanıcının ayrıcalıklarıyla yürütülür ve bu da guest-to-host escape sağlar.
Alternatif payload’lar arasında heap belleğe küçük bir ROP zinciri yerleştirmek ve adresini sıkça çağrılan bir callback’e kopyalamak veya yinelemeli yazmalar için pfFini/pfDtor’u zincirlenmiş gadget’lara yönlendirmek bulunur.
References
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


