Off by one overflow

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 का समर्थन करें

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

सिर्फ़ 1B overflow तक पहुँच होने पर हमलावर अगले chunk के size फील्ड को बदल सकता है। इससे यह तय किया जा सकता है कि वास्तव में कौन से chunks free किए जाते हैं, और संभावित रूप से एक ऐसा chunk बन सकता है जिसमें कोई और legit chunk मौजूद हो। इसका exploitation double free या overlapping chunks जैसा होता है।

There are 2 types of off by one vulnerabilities:

  • Arbitrary byte: इस प्रकार से उस byte को किसी भी मान से overwrite किया जा सकता है
  • Null byte (off-by-null): यह प्रकार उस byte को केवल 0x00 से ही overwrite करने की अनुमति देता है
  • A common example of this vulnerability can be seen in the following code where the behavior of strlen and strcpy is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
  • This can be expoited with the House of Einherjar.
  • If using Tcache, this can be leveraged to a double free situation.
Off-by-null ```c // From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/ int main(void) { char buffer[40]=""; void *chunk1; chunk1 = malloc(24); puts("Get Input"); gets(buffer); if(strlen(buffer)==24) { strcpy(chunk1,buffer); } return 0; } ```

अन्य चेक्स के अलावा, अब जब भी कोई chunk free होता है तो पिछली size की तुलना metadata के chunk में कॉन्फ़िगर size के साथ की जाती है, जिससे यह attack version 2.28 से काफी जटिल हो गया है।

Code example:

Goal

  • किसी chunk को दूसरे chunk के भीतर रखा जाना ताकि उस दूसरे chunk पर लिखने से contained chunk को overwrite किया जा सके

Requirements

  • size metadata जानकारी को बदलने के लिए Off by one overflow

General off-by-one attack

  • तीन chunks A, B और C allocate करें (मान लें sizes 0x20), और top-chunk के साथ consolidation रोकने के लिए एक और allocate करें।
  • C को free करें (यह 0x20 Tcache free-list में डाला जाएगा)।
  • A का उपयोग करके B पर overflow करें। Off-by-one का दुरुपयोग करके B के size फ़ील्ड को 0x21 से 0x41 में बदलें।
  • अब हमारे पास B के अंदर free chunk C कंटेन होता है
  • B को free करें और एक 0x40 chunk allocate करें (यहाँ फिर से रखा जाएगा)
  • हम अभी भी free होने वाले C से fd pointer को modify कर सकते हैं (Tcache poisoning)

Off-by-null attack

  • 3 memory chunks (a, b, c) एक के बाद एक reserve किये जाते हैं। फिर बीच वाला chunk free किया जाता है। पहला chunk एक off by one overflow vulnerability रखता है और attacker इसे 0x00 के साथ दुरुपयोग करता है (यदि पिछला बाइट 0x10 होता तो यह middle chunk को असल आकार से 0x10 छोटा दिखाता)।
  • फिर, बीच में free हुए chunk (b) में 2 और छोटे chunks allocate किये जाते हैं, हालांकि, क्योंकि b + b->size कभी c chunk को अपडेट नहीं करता क्योंकि पॉइंट किए गए पते की तुलना में यह छोटा है जितना होना चाहिए।
  • फिर, b1 और c को free कर दिया जाता है। चूँकि c - c->prev_size अब भी b (अब b1) की ओर संकेत करता है, दोनों एक chunk में consolidate हो जाते हैं। हालाँकि, b2 अब भी b1 और c के बीच अंदर ही रहता है।
  • अंत में, एक नया malloc किया जाता है जो इस memory क्षेत्र को पुनः प्राप्त करता है जो वास्तव में b2 को contain करने वाला है, जिससे नए malloc के मालिक को b2 की सामग्री नियंत्रित करने की अनुमति मिलती है।

यह इमेज इस attack को पूरी तरह समझाती है:

https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks

Modern glibc hardening & bypass notes (>=2.32)

  • Safe-Linking अब हर singly linked bin pointer की रक्षा करता है और fd = ptr ^ (chunk_addr >> 12) स्टोर करता है, इसलिए एक off-by-one जो आमतौर पर size के लो-बाइट को ही फ्लिप करता है उसे आम तौर पर Tcache poisoning काम करने से पहले XOR mask को फिर से गणना करने के लिए एक heap leak की आवश्यकता होती है।
  • एक व्यावहारिक leakless ट्रिक यह है कि एक pointer को “double-protect” किया जाए: पहले एक pointer जिसे आप पहले से नियंत्रित करते हैं को PROTECT_PTR से encode करें, फिर वही gadget दोबारा इस्तेमाल करके अपने forged pointer को encode करें ताकि alignment चेक पास हो बिना नए addresses उजागर किये।
  • safe-linking + single-byte corruptions के लिए workflow:
  1. victim chunk को बढ़ाएँ जब तक वह पूरी तरह से एक freed chunk जिसे आप पहले से नियंत्रित करते हैं को कवर न कर ले (overlapping-chunk setup)।
  2. किसी भी heap pointer को leak करें (stdout, UAF, partially controlled struct) और key heap_base >> 12 निकाले।
  3. free-list pointers को लिखने से पहले फिर से encode करें—encoded value को user data के अंदर stage करें और बाद में memcpy करें यदि आपके पास केवल single-byte writes हैं।
  4. इसे Tcache bin attacks के साथ मिलाएँ ताकि allocations को __free_hook या tcache_perthread_struct entries की ओर redirect किया जा सके जब forged pointer सही तरीके से encode हो।

A minimal helper to rehearse the encode/decode step while debugging modern exploits:

def protect(ptr, chunk_addr):
return ptr ^ (chunk_addr >> 12)

def reveal(encoded, chunk_addr):
return encoded ^ (chunk_addr >> 12)

chunk = 0x55555555c2c0
encoded_fd = protect(0xdeadbeefcaf0, chunk)
print(hex(reveal(encoded_fd, chunk)))  # 0xdeadbeefcaf0

Recent real-world target: glibc __vsyslog_internal off-by-one (CVE-2023-6779)

  • जनवरी 2024 में Qualys ने CVE-2023-6779 का विवरण दिया, जो __vsyslog_internal() के अंदर एक off-by-one है जो तब ट्रिगर होता है जब syslog()/vsyslog() के format strings INT_MAX से अधिक होते हैं, इसलिए terminating \0 glibc 2.37–2.39 सिस्टम्स पर अगले chunk के least-significant size बाइट को कर्रप्ट कर देता है (Qualys advisory).
  • उनका Fedora 38 exploit pipeline:
  1. एक बहुत लंबा openlog() ident तैयार करें ताकि vasprintf एक heap buffer लौटाए जो attacker-controlled डेटा के पास हो।
  2. syslog() कॉल करके पड़ोसी chunk के size | prev_inuse बाइट को स्मैश करें, उसे free करें, और consolidation मजबूर करें जो attacker डेटा को overlap कर दे।
  3. overlapped view का उपयोग करके tcache_perthread_struct metadata को करप्ट करें और अगली allocation को __free_hook की ओर निर्देशित करें, इसे system/एक one_gadget से overwrite करने के लिए।
  • एक harness में corrupting write को reproduce करने के लिए, एक gigantic argv[0] के साथ fork करें, openlog(NULL, LOG_PID, LOG_USER) कॉल करें और फिर syslog(LOG_INFO, "%s", payload) जहां payload = b"A" * 0x7fffffff; pwndbg’s heap bins तुरंत single-byte overwrite दिखाता है।
  • Ubuntu इस बग को CVE-2023-6779 के रूप में ट्रैक करता है, और वही INT truncation document करता है जो इसे एक भरोसेमंद off-by-one primitive बनाता है।

Other Examples & References

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • strlen के कारण होने वाला off-by-one जो अगले chunk के size फील्ड को ध्यान में रखता है।
  • Tcache इस्तेमाल हो रहा है, इसलिए सामान्य off-by-one attacks Tcache poisoning के साथ arbitrary write primitive पाने के लिए काम करते हैं।
  • Asis CTF 2016 b00ks
  • एक off-by-one का दुरुपयोग करके heap से एक address leak करना संभव है क्योंकि string के अंत का 0x00 बाइट अगले फील्ड द्वारा overwrite हो जाता है।
  • Arbitrary write उस off-by-one write का दुरुपयोग करके प्राप्त किया जाता है ताकि pointer किसी और जगह की ओर इशारा करे जहाँ एक fake struct fake pointers के साथ बनाया जाएगा। फिर, इस struct के pointer का पालन करके arbitrary write हासिल करना संभव होता है।
  • libc address leak हो जाता है क्योंकि अगर heap mmap का उपयोग करके बढ़ाई जाती है, तो mmap द्वारा allocate की गई memory का libc से एक fixed offset होता है।
  • अंत में arbitrary write का दुरुपयोग करके __free_hook के पते में एक one gadget लिखा जाता है।
  • plaidctf 2015 plaiddb
  • getline फंक्शन में NULL off by one vulnerability है जो user input lines पढ़ता है। यह फ़ंक्शन content की “key” पढ़ने के लिए उपयोग किया जाता है न कि content के लिए।
  • writeup में शुरू में 5 chunks बनाए गए थे:
  • chunk1 (0x200)
  • chunk2 (0x50)
  • chunk5 (0x68)
  • chunk3 (0x1f8)
  • chunk4 (0xf0)
  • chunk defense (0x400) ताकि top chunk के साथ consolidating से बचा जा सके
  • फिर chunk 1, 5 और 3 को free किया गया, तो:

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]

- फिर, chunk3 (0x1f8) का दुरुपयोग करके null off-by-one का उपयोग कर prev_size को `0x4e0` पर लिखा गया।
- ध्यान दें कि शुरू में allocate किए गए chunks1, 2, 5 और 3 के sizes प्लस उन chunks के 4 headers का योग `0x4e0` के बराबर है: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- फिर, chunk 4 को free किया गया, जिससे एक ऐसा chunk बना जो शुरुआत तक के सभी chunks को consume कर लेता है:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]

- फिर, मूल chunk 1 को भरने के लिए `0x200` bytes allocate किए गए
- और एक और `0x200` bytes allocate किए गए और chunk2 नष्ट हो गया और इसलिए कोई लीकेज नहीं हुआ और यह काम नहीं करता? शायद यह नहीं करना चाहिए था
- फिर, यह 0x58 "a"s के साथ एक और chunk allocate करता है (chunk2 को overwrite करके chunk5 तक पहुँचते हुए) और chunk5 के fast bin chunk के `fd` को modify करके इसे `__malloc_hook` की ओर इंगित कर देता है
- फिर, 0x68 का एक chunk allocate किया जाता है ताकि `__malloc_hook` में fake fast bin chunk अगला fast bin chunk हो
- अंत में, 0x68 का नया fast bin chunk allocate किया जाता है और `__malloc_hook` को एक `one_gadget` पते से overwrite कर दिया जाता है

## References

- [Qualys Security Advisory – CVE-2023-6246/6779/6780](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt)
- [Ubuntu Security – CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779)
- [Breaking Safe-Linking in Modern Glibc – Google CTF 2022 "saas" analysis](https://blog.csdn.net/2402_86373248/article/details/148717274)

> [!TIP]
> AWS हैकिंग सीखें और अभ्यास करें:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> GCP हैकिंग सीखें और अभ्यास करें: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Azure हैकिंग सीखें और अभ्यास करें: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>HackTricks का समर्थन करें</summary>
>
> - [**सदस्यता योजनाओं**](https://github.com/sponsors/carlospolop) की जांच करें!
> - **हमारे** 💬 [**Discord समूह**](https://discord.gg/hRep4RUj7f) या [**टेलीग्राम समूह**](https://t.me/peass) में शामिल हों या **हमें** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)** पर फॉलो करें।**
> - **हैकिंग ट्रिक्स साझा करें और** [**HackTricks**](https://github.com/carlospolop/hacktricks) और [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) गिटहब रिपोजिटरी में PRs सबमिट करें।
>
> </details>