House of Roman

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

बुनियादी जानकारी

यह एक बहुत ही दिलचस्प टेक्नीक थी जो fake fastbins, the unsorted_bin attack और relative overwrites के माध्यम से RCE बिना leaks के देने की अनुमति देती थी। हालांकि इसे पैच किया गया है।

2026 में प्रासंगिकता

  • glibc window: Works reliably on 2.23–2.27 (the how2heap PoC tested 2.23–2.25). Starting 2.28, the “additional checks for unsorted bin integrity” patch makes the unsorted‑bin write unreliable, so success drops sharply. From 2.34 onward __malloc_hook/__free_hook were removed, making the original target unavailable. Use it only on old libc’s (or custom builds that keep the hooks) or for CTF challenges that ship an old libc.
  • Tcache era (≥2.26): Tcache आपके 0x70 allocations को खा जाएगा और fastbin/unsorted primitives को रोक देगा। इसे डिसेबल करें (setenv("GLIBC_TUNABLES","glibc.malloc.tcache_count=0",1);) किसी भी allocation से पहले या हर 0x70 tcache bin को 7 frees से भरकर उसे ड्रेन करें।
  • Safe-linking: यह ≥2.32 में tcache/fastbin पर लागू होता है, लेकिन House of Roman को केवल partial pointer overwrite of a libc address already present in fd/bk की आवश्यकता होती है, इसलिए safe-linking यहाँ defender की मदद नहीं करता (attacker कभी भी एक fresh pointer फोर्ज नहीं करता)। असली रोकने वाला तत्व hooks का हटना और unsorted-bin checks हैं।

कोड

लक्ष्य

  • relative pointers का दुरुपयोग करके RCE

आवश्यकताएँ

  • fastbin और unsorted bin pointers को संपादित करने में सक्षम होना
  • 12 बिट रैंडमनेस को ब्रूट‑फोर्स करना होगा (0.02% काम करने की संभावना)

हमला के चरण

भाग 1: Fastbin Chunk points to __malloc_hook

कई chunks बनाएँ:

  • fastbin_victim (0x60, offset 0): UAF chunk, बाद में heap pointer को LibC value की ओर इशारा करने के लिए edit किया जाएगा।
  • chunk2 (0x80, offset 0x70): अच्छे alignment के लिए
  • main_arena_use (0x80, offset 0x100)
  • relative_offset_heap (0x60, offset 0x190): ‘main_arena_use’ chunk पर relative offset

फिर free(main_arena_use) करें जो इस chunk को unsorted list में रखेगा और fd और bk दोनों pointers में main_arena + 0x68 का pointer प्राप्त करेगा।

अब एक नया chunk fake_libc_chunk(0x60) allocate किया जाता है क्योंकि यह fd और bk में main_arena + 0x68 के pointers रखेगा।

फिर relative_offset_heap और fastbin_victim को free कर दिया जाता है।

/*
Current heap layout:
0x0:   fastbin_victim       - size 0x70
0x70:  alignment_filler     - size 0x90
0x100: fake_libc_chunk      - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main        - size 0x20
0x190: relative_offset_heap - size 0x70

bin layout:
fastbin:  fastbin_victim -> relative_offset_heap
unsorted: leftover_main
*/
  • fastbin_victim का fd relative_offset_heap की ओर इशारा करता है
  • relative_offset_heap fake_libc_chunk से दूरी का एक offset है, जिसमें main_arena + 0x68 का pointer होता है
  • fastbin_victim.fd के अंतिम बाइट को बदलने से fastbin_victim main_arena + 0x68 की ओर इशारा करने लगता है।

किए गए पिछले कार्यों के लिए, attacker को fastbin_victim के fd pointer को बदलने में सक्षम होना चाहिए।

फिर, main_arena + 0x68 उतना रोचक नहीं है, इसलिए इसे बदलकर pointer को __malloc_hook की ओर कर दिया जाता है।

ध्यान दें कि __memalign_hook आमतौर पर 0x7f से शुरू होता है और उसके पहले zeros होते हैं, इसलिए इसे 0x70 fast bin के एक वैल्यू के रूप में fake करना संभव है। क्योंकि address के अंतिम 4 बिट्स random होते हैं, इसलिए उस वैल्यू के हमारे इच्छित स्थान की ओर इंगित करने की 2^4=16 संभावनाएँ हैं। इसलिए यहाँ एक BF attack किया जाता है ताकि chunk इस तरह समाप्त हो: 0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23).

(बाकी बाइट्स के बारे में अधिक जानकारी के लिए how2heap example में व्याख्या देखें). यदि brute force विफल होता है तो प्रोग्राम बस crash कर जाता है (काम करने तक restart करें)।

फिर, 2 mallocs किए जाते हैं ताकि शुरू के 2 fast bin chunks हट जाएँ और तीसरा allocate करके __malloc_hook में एक chunk प्राप्त किया जाता है।

malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);

Part 2: Unsorted_bin attack

अधिक जानकारी के लिए आप देख सकते हैं:

Unsorted Bin Attack

लेकिन मूल रूप से यह main_arena + 0x68 को chunk->bk में निर्दिष्ट किसी भी स्थान पर लिखने की अनुमति देता है। हम इस attack के लिए __malloc_hook चुनते हैं। फिर, उसे overwrite करने के बाद हम एक relative overwrite का उपयोग कर उसे one_gadget की ओर इंगित करेंगे।

इसके लिए हम एक chunk लेते हैं और उसे unsorted bin में डालते हैं:

uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate

puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);

Use an UAF in this chunk to point unsorted_bin_ptr->bk to the address of __malloc_hook (we brute forced this previously).

Caution

ध्यान दें कि यह attack unsorted bin को corrupt कर देता है (इसलिए small और large भी प्रभावित होते हैं)। इसलिए अब हम केवल fast bin से ही allocations का उपयोग कर सकते हैं (एक अधिक complex प्रोग्राम अन्य allocations कर सकता है और crash कर सकता है), और इसे trigger करने के लिए हमें वही size alloc करना होगा वरना प्रोग्राम crash करेगा।

So, to trigger the write of main_arena + 0x68 in __malloc_hook we perform after setting __malloc_hook in unsorted_bin_ptr->bk we just need to do: malloc(0x80)

Step 3: Set __malloc_hook to system

In step one we controlled a chunk containing __malloc_hook (in the variable malloc_hook_chunk) and in the second step we managed to write main_arena + 0x68 there.

Now, we abuse a partial overwrite in malloc_hook_chunk to use the libc address we wrote there (main_arena + 0x68) to point to a one_gadget address.

Here is where it’s needed to bruteforce 12 bits of randomness (more info in the how2heap example).

Finally, once the correct address is overwritten, call malloc and trigger the one_gadget.

Modern tips & variants

  • Unsorted-bin hardening (2.28+): unsorted chunks पर जो extra integrity checks (size sanity + list linkage) लगे हैं वे classic unsorted‑bin write को fragile बनाते हैं। _int_malloc से बचने के लिए आपको fd/bk लिंक consistent और sizes plausible रखने होंगे, जो आम तौर पर एक साधारण partial overwrite से अधिक मजबूत primitives माँगता है।
  • Hook removal (2.34+): __malloc_hook हट जाने पर primitive को किसी writable GOT/global पर land करने के लिए adapt करें जिसे आप बाद में reuse कर सकें (उदा., non-PIE binaries में exit@GOT को overwrite करना) या pivot करके House of Pie स्टाइल top‑chunk hijack में जाएँ ताकि hook की बजाय top को control कर सकें।
  • Any‑address fastbin alloc (romanking98 writeup): दूसरा भाग 0x71 freelist को repair करने और unsorted‑bin write का उपयोग करके __free_hook के ऊपर fastbin allocation लैंड करने को दिखाता है, फिर system("/bin/sh") रखकर और libc‑2.24 (pre-hook removal) पर इसे free() के ज़रिये trigger किया जाता है।

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें