ReplaceMe
hackthebox
Task: sed-like string replacement utility with read() not adding null terminator and contiguous BSS buffers. Solution: 3-pass ret2libc exploiting strlen inflation across buffer boundary, partial return address overwrite for PIE leak, GOT read for libc leak.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
ReplaceMe — HackTheBox
Description
"This useful interactive SED-like utility was shared with me to use, can you make sure it is safe?"
64-bit ELF PIE binary, dynamically linked, not stripped. Implements an interactive string replacement utility in sed format (s/old/new/). Takes an input string and a replacement pattern, performs substitution, and outputs the result.
Remote target: 154.57.164.68:32476.
Files: replaceme (binary), libc.so.6 (Ubuntu GLIBC 2.31-0ubuntu9.14), Dockerfile (Ubuntu 20.04, socat), flag.txt.
Protections
| Protection | Status |
|---|---|
| PIE | Enabled |
| NX | Enabled |
| Canary | No |
| RELRO | Full (GOT not writable, but readable) |
Analysis
Key Functions
main()
Sequentially reads two inputs into BSS:
input(BSS 0x4040, 128 bytes) — string to processreplacement(BSS 0x40c0, 128 bytes) — replacement pattern ins/old/new/format
Then calls do_replacement().
ask_input(prompt, buffer, size)
Uses read(0, buffer, size) — does not add null terminator. This is critical: if all 128 bytes of input are filled, strlen() will continue reading into replacement.
do_replacement() — vulnerable function
Parses s/old/new/, finds old in input, builds result: prefix + new + suffix into stack buffer result[128] via memcpy without bounds checking.
rbp-0xc0: result[128] ← buffer start
rbp-0x40: padding
rbp-0x3c: after_len ← suffix length (int)
rbp-0x38: wp ← write pointer
rbp-0x30: match ← match pointer
rbp-0x24: new_len
rbp-0x20: end_slash
rbp-0x14: old_len
rbp-0x10: mid_slash
rbp-0x08: old_start
rbp+0x00: saved RBP
rbp+0x08: return address ← result + 0xc8 = result[200]
BSS Layout
input (0x4040) and replacement (0x40c0) are located contiguously in BSS. When input is filled with all 128 bytes without null terminator, strlen() continues counting bytes from replacement, inflating after_len.
Vulnerability
...
$ grep --similar
Similar writeups
- [pwn][free]Void— hackthebox
- [pwn][Pro]Говори - и будет исполнено (ask_and_you_shall_receive)— hackerlab
- [pwn][free]Portaloo— hackthebox
- [reverse][Pro]Basic— spbctf
- [pwn][Pro]iz_heap_lv1 — BSS-pointer overlap + tcache poisoning— spbctf