$ cat writeup.md…
$ cat writeup.md…
hackthebox
Task: 64-bit PIE binary with heap UAF, mprotect making heap RWX, and stack buffer overflow with canary. Solution: Write shellcode to RWX heap, leak heap address via tcache safe-linking UAF, leak canary via null byte overwrite, stack smash to jump to shellcode.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
"Portals... A gateway to other dimensions, where chaos meets creativity and the void greets you."
64-bit ELF PIE binary with full protections (Full RELRO, NX, Canary, PIE). Custom glibc 2.35 (Ubuntu GLIBC 2.35-0ubuntu3.8) provided. Remote target: 154.57.164.78:32357.
The binary is a portal management system with 5 menu options:
malloc(0x20), stores pointer in slots[0] or slots[1]. On first allocation, calls mprotect() on the heap page with flags PROT_READ|PROT_WRITE|PROT_EXEC (7) — makes the heap RWX.free(slots[n]), but does NOT NULL the pointer (UAF).read(0, slots[n], 0x15) — writes 21 bytes to the portal.printf("Coordinate: %d ---- Data: %.*s", 0x15, i, slots[i]) — reads portal data.read() for 0x50 bytes (8-byte overflow past buffer into canary). Second read() for 0x68 bytes (0x20-byte overflow — overwrites canary, saved rbp, return address). After this function, main calls exit(0).slots[2] at address 0x4060 — array of 2 heap pointersmprotect_called at address 0x4050 — flag ensuring mprotect is called only once| Protection | Status |
|---|---|
| PIE | ✅ Enabled |
| NX | ✅ Enabled (but heap is made RWX via mprotect!) |
| Canary | ✅ Enabled |
| RELRO | Full |
In create_portal(), the first allocation triggers:
page_aligned = slots[n] & ~(page_size - 1); mprotect(page_aligned, page_size, PROT_READ|PROT_WRITE|PROT_EXEC);
This makes the entire heap page executable — perfect for shellcode.
...
$ grep --similar