$ cat writeup.md…
$ cat writeup.md…
hackthebox
Task: a forked Linux TCP service with PIE, NX, canary, Full RELRO, an off-by-one admin bypass, a reservation format string, and a staged stack overflow. Solution: use the NUL overwrite to reach manager functions, leak libc and stack via fprintf, brute-force the shared canary across forked children, recover the randomized flag filename with getdents64, then finish with an ORW ROP chain.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Welcome to the Forks & Knives restaurant!
This was a forked TCP pwn service, not a web task. The binary exposed a restaurant menu over the network and kept per-client state such as the user name, reservations, and order data.
Remote target: 154.57.164.78:30845.
Files:
serverlibc.so.6DockerfileThe first useful strings immediately showed the challenge shape:
Welcome to the Forks & Knives restaurant!Can I have your name please?Reserve a tablePlace an orderLogin as managerView reservationsClear reservationsThat made it clear this was a classic menu-driven Linux service. There was no HTTP parsing anywhere, and the target itself behaved like a forked TCP daemon: every incoming connection got a fresh child process.
checksec on the binary:
| Protection | Status |
|---|---|
| PIE | Enabled |
| NX | Enabled |
| Canary | Enabled |
| RELRO | Full |
So the exploitation plan had to avoid GOT overwrites and needed either a canary leak or a reliable canary bypass. Because the service forks, the stack canary is inherited by children, which turned brute force into a viable primitive.
The early input handler stores the customer name in a global buffer:
name at 0x4030admin flag at 0x4040The name logic reads up to 16 bytes and then writes a trailing \0 at name[len].
That is safe for lengths 0..15, but exactly 16 bytes makes the terminator land one byte past the buffer, on top of the neighboring auth state.
...
$ grep --similar