Off by one overflow
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
Η πρόσβαση μόνο σε ένα 1B overflow επιτρέπει σε έναν επιτιθέμενο να τροποποιήσει το πεδίο size του επόμενου chunk. Αυτό επιτρέπει να χειραγωγηθεί ποια chunks απελευθερώνονται πραγματικά, ενδεχομένως δημιουργώντας ένα chunk που περιέχει ένα άλλο legit chunk. Η εκμετάλλευση είναι παρόμοια με double free ή overlapping chunks.
Υπάρχουν 2 τύποι ευπαθειών off by one:
- Arbitrary byte: Αυτός ο τύπος επιτρέπει να αντικατασταθεί το byte με οποιαδήποτε τιμή
- Null byte (off-by-null): Αυτός ο τύπος επιτρέπει την αντικατάσταση αυτού του byte μόνο με 0x00
- Ένα συνηθισμένο παράδειγμα αυτής της ευπάθειας φαίνεται στον παρακάτω κώδικα όπου η συμπεριφορά των
strlenκαιstrcpyείναι ασυνεπής, γεγονός που επιτρέπει την τοποθέτηση ενός byte 0x00 στην αρχή του επόμενου chunk. - Αυτό μπορεί να αξιοποιηθεί με το House of Einherjar.
- Αν χρησιμοποιείται Tcache, αυτό μπορεί να αξιοποιηθεί σε κατάσταση double free.
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, κάνοντας αυτή την επίθεση αρκετά πιο περίπλοκη από την έκδοση 2.28.
Code example:
- https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c
- This attack is no longer working due to the use of Tcaches.
- Moreover, if you try to abuse it using larger chunks (so tcaches aren’t involved), you will get the error:
malloc(): invalid next size (unsorted)
Στόχος
- Να κάνουμε ένα chunk να βρίσκεται μέσα σε ένα άλλο chunk ώστε η εγγραφή πάνω στο δεύτερο chunk να επιτρέπει την υπεργραφή του περιεχόμενου του contained chunk
Απαιτήσεις
- Off by one overflow για να τροποποιηθεί η πληροφορία του size στο metadata
General off-by-one attack
- Allocate three chunks
A,BandC(say sizes 0x20), and another one to prevent consolidation with the top-chunk. - Free
C(inserted into 0x20 Tcache free-list). - Use chunk
Ato overflow onB. Abuse off-by-one to modify thesizefield ofBfrom 0x21 to 0x41. - Now we have
Bcontaining the free chunkC - Free
Band allocate a 0x40 chunk (it will be placed here again) - We can modify the
fdpointer fromC, which is still free (Tcache poisoning)
Off-by-null attack
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that it’s 0x10 smaller than it really is).
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as
b + b->sizenever updates the c chunk because the pointed address is smaller than it should. - Then, b1 and c gets freed. As
c - c->prev_sizestill points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c. - Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
This image explains perfectly the attack:
.png)
https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
Σημειώσεις hardening & bypass για modern glibc (>=2.32)
- Safe-Linking now protects every singly linked bin pointer by storing
fd = ptr ^ (chunk_addr >> 12), so an off-by-one that only flips the low byte ofsizeusually also needs a heap leak to recompute the XOR mask before Tcache poisoning works. - A practical leakless trick is to “double-protect” a pointer: encode a pointer you already control with
PROTECT_PTR, then reuse the same gadget to encode your forged pointer so the alignment check passes without revealing new addresses. - Workflow for safe-linking + single-byte corruptions:
- Grow the victim chunk until it fully covers a freed chunk you already control (overlapping-chunk setup).
- Leak any heap pointer (stdout, UAF, partially controlled struct) and derive the key
heap_base >> 12. - Re-encode free-list pointers before writing them—stage the encoded value inside user data and memcpy it later if you only own single-byte writes.
- Combine with Tcache bin attacks to redirect allocations into
__free_hookortcache_perthread_structentries once the forged pointer is properly encoded.
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
Πρόσφαστος πραγματικός στόχος: glibc __vsyslog_internal off-by-one (CVE-2023-6779)
- Τον Ιανουάριο του 2024 η Qualys περιέγραψε το CVE-2023-6779, ένα off-by-one μέσα στο
__vsyslog_internal()που ενεργοποιείται όταν τα format strings τωνsyslog()/vsyslog()υπερβαίνουν τοINT_MAX, οπότε το τερματικό\0καταστρέφει το λιγότερο σημαντικό byte τουsizeτου επόμενου chunk σε συστήματα glibc 2.37–2.39 (Qualys advisory). - Η αλυσίδα exploit τους στο Fedora 38:
- Κατασκευάζουν ένα υπερβολικά μεγάλο ident για
openlog()ώστεvasprintfνα επιστρέψει ένα heap buffer δίπλα σε δεδομένα που ελέγχονται από τον attacker. - Καλούν
syslog()για να συντρίψουν το bytesize | prev_inuseτου διπλανού chunk, το κάνουν free, και εξαναγκάζουν consolidation που επικαλύπτει τα δεδομένα του attacker. - Χρησιμοποιούν την επικαλυμμένη προβολή για να καταστρέψουν metadata του
tcache_perthread_structκαι στοχεύουν την επόμενη allocation στο__free_hook, αντικαθιστώντας το μεsystem/ένα one_gadget για root.
- Για να αναπαραγάγεις το καταστρεπτικό write σε ένα harness, κάνε fork με ένα γιγαντιαίο
argv[0], κάλεσεopenlog(NULL, LOG_PID, LOG_USER)και μετάsyslog(LOG_INFO, "%s", payload)όπουpayload = b"A" * 0x7fffffff; τοpwndbg’sheap binsδείχνει αμέσως το single-byte overwrite. - Η Ubuntu παρακολουθεί το bug ως CVE-2023-6779, τεκμηριώνοντας την ίδια INT truncation που κάνει αυτό ένα αξιόπιστο off-by-one primitive.
Άλλα Παραδείγματα & Αναφορές
- https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
- Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
- Off-by-one λόγω του ότι
strlenλαμβάνει υπόψη το πεδίοsizeτου επόμενου chunk. - Χρησιμοποιείται tcache, οπότε μια γενική off-by-one επίθεση δουλεύει για να αποκτήσει ένα arbitrary write primitive με Tcache poisoning.
- Asis CTF 2016 b00ks
- Είναι δυνατόν να εκμεταλλευτείς ένα off by one για να leakάρεις μια διεύθυνση από το heap επειδή το byte
0x00στο τέλος ενός string αντικαθίσταται από το επόμενο πεδίο. - Το arbitrary write αποκτάται εκμεταλλευόμενος το off by one write ώστε ο pointer να δείχνει σε άλλη θέση όπου θα κατασκευαστεί ένα ψεύτικο struct με ψεύτικους pointers. Μετά, είναι δυνατόν να ακολουθήσεις τον pointer αυτού του struct για να πετύχεις arbitrary write.
- Η διεύθυνση της libc leakάρεται επειδή αν το heap επεκταθεί χρησιμοποιώντας mmap, η μνήμη που δεσμεύει το mmap έχει σταθερή απόσταση από την libc.
- Τελικά το arbitrary write εκμεταλλεύεται για να γράψει στη διεύθυνση του
__free_hookμε ένα one_gadget. - plaidctf 2015 plaiddb
- Υπάρχει μια NULL off by one ευπάθεια στη συνάρτηση
getlineπου διαβάζει γραμμές εισόδου χρήστη. Αυτή η συνάρτηση χρησιμοποιείται για να διαβάσει το “key” του περιεχομένου και όχι το περιεχόμενο. - Στο writeup δημιουργούνται αρχικά 5 chunks:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) για να αποφευχθεί το consolidation με το top chunk
- Έπειτα τα 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`.
- Σημείωσε πως τα μεγέθη των αρχικά allocated chunks1, 2, 5 και 3 συν το headers τεσσάρων από αυτά τα chunks ισούνται με `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Έπειτα, το chunk 4 γίνεται free, δημιουργώντας ένα chunk που καταναλώνει όλα τα chunks μέχρι την αρχή:
- ```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 ]
- Έπειτα, δεσμεύονται `0x200` bytes γεμίζοντας το αρχικό chunk 1
- Και ακόμα 0x200 bytes δεσμεύονται και το chunk2 καταστρέφεται και επομένως δεν υπάρχει no fucking leak και αυτό δεν δουλεύει; Ίσως αυτό δεν έπρεπε να γίνει
- Έπειτα, δεσμεύει άλλο chunk με 0x58 "a"s (επαναγράφοντας το chunk2 και φτάνοντας στο chunk5) και τροποποιεί το `fd` του fast bin chunk του chunk5 δείχνοντάς το στο `__malloc_hook`
- Έπειτα, δεσμεύεται ένα chunk 0x68 έτσι ώστε το ψεύτικο fast bin chunk στο `__malloc_hook` να είναι το επόμενο fast bin chunk
- Τέλος, δεσμεύεται ένα νέο fast bin chunk 0x68 και το `__malloc_hook` αντικαθίσταται με μια διεύθυνση `one_gadget`
## Αναφορές
- [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 Hacking:<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 Hacking: <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 Hacking: <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) ή στην [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
>
> </details>
HackTricks

