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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
基本信息
仅凭对 1B overflow 的访问,攻击者就能修改下一个 chunk 的 size 字段。这允许篡改实际被 free 的 chunk,可能生成一个包含另一个合法 chunk 的 chunk。利用方式类似于 double free 或 overlapping chunks。
There are 2 types of off by one vulnerabilities:
- Arbitrary byte: 这种情况允许将该字节覆盖为任意值
- Null byte (off-by-null): 这种情况只允许将该字节覆盖为 0x00
- 一个常见的示例可以在下面的代码中看到,其中
strlen和strcpy的行为不一致,从而可以在下一个 chunk 的开头设置一个 0x00 字节。 - 这可以通过 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; } ```Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata’s chunk, making this attack fairly complex from version 2.28.
代码示例:
- 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)
Goal
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
Requirements
- Off by one overflow to modify the size metadata information
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
现代 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年1月,Qualys 详细披露了 CVE-2023-6779,这是一个发生在
__vsyslog_internal()内的 off-by-one,当syslog()/vsyslog()的格式字符串超过INT_MAX时触发,因此终止的\0会破坏相邻 chunk 的最低有效size字节,在 glibc 2.37–2.39 系统上会发生(Qualys advisory)。 - 他们的 Fedora 38 exploit pipeline:
- 构造一个超长的
openlog()ident,使得vasprintf返回一个位于攻击者控制数据旁边的堆缓冲区。 - 调用
syslog()覆写相邻 chunk 的size | prev_inuse字节,free 它,并强制合并以重叠攻击者数据。 - 利用重叠视图破坏
tcache_perthread_struct元数据,使下一次分配指向__free_hook,并用system或 one_gadget 覆盖以获得 root。
- 要在测试环境中重现该破坏写入,可用一个巨大的
argv[0]fork,调用openlog(NULL, LOG_PID, LOG_USER),然后syslog(LOG_INFO, "%s", payload),其中payload = b"A" * 0x7fffffff;pwndbg的heap bins会立即显示那个单字节覆盖。 - Ubuntu 将此漏洞登记为 CVE-2023-6779,记录了相同的 INT 截断,使其成为一个可靠的 off-by-one 原语。
其他示例与参考
- https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
- Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
- Off-by-one 是因为
strlen将下一个 chunk 的size字段计入。 - Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.
- Asis CTF 2016 b00ks
- 可以滥用 off-by-one 来 leak 堆地址,因为字符串末端的 0x00 字节会被下一个字段覆盖。
- 通过滥用 off-by-one 写入,使指针指向另一处以构造包含伪指针的伪结构体,从而获得任意写。然后可通过跟随该结构体的指针实现任意写。
- libc 地址会被 leak,因为如果 heap 使用 mmap 扩展,mmap 分配的内存与 libc 具有固定偏移。
- 最后滥用任意写把一个 one_gadget 地址写入
__free_hook。 - plaidctf 2015 plaiddb
- 在读取用户输入行的
getline函数中存在一个 NULL off-by-one 漏洞。该函数用来读取内容的 “key”,而不是内容本身。 - In the writeup 5 initial chunks are created:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) to avoid consolidating with top chunk
- 然后释放 chunk 1、5 和 3,所以:
-
[ 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`。
- 注意最初分配的 chunks1, 2, 5 和 3 的大小加上这 4 个 chunk 的头部等于 `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- 然后,释放 chunk 4,生成一个占据直到开头的合并 chunk:
- ```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` 字节填满原来的 chunk 1
- 然后又分配了 0x200 字节,chunk2 被销毁,因此就没有 leak 了,这样不行?也许不该这么做
- 然后分配另一个包含 0x58 个 "a" 的 chunk(覆盖 chunk2 并到达 chunk5),并修改 chunk5 的 fast bin chunk 的 `fd` 指向 `__malloc_hook`
- 然后分配一个 0x68 的 chunk,这样 `__malloc_hook` 中的伪 fast bin chunk 就成为下一个 fast bin chunk
- 最后,再次分配一个 0x68 的 fast bin chunk,并用一个 one_gadget 地址覆盖 `__malloc_hook`
## 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) 或 [**Telegram 群组**](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) GitHub 仓库提交 PR 来分享黑客技巧。
>
> </details>
HackTricks

