Arms Roped
hackthebox
Task: ARM 32-bit binary exploitation under QEMU user-mode with PIE, Canary, and NX enabled. Solution: Multi-stage ROP chain — leak canary via partial overwrite, leak PIE base from saved LR, use ARM ret2csu to leak libc via GOT, then ret2libc with system("/bin/sh").
$ 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.
Arms Roped — HackTheBox
Description
ARM binary exploitation challenge running under QEMU user-mode emulation with a custom ASLR patch.
ARM 32-bit ELF binary (little-endian, EABI5), dynamically linked, not stripped. Runs via qemu-arm with a custom ASLR patch. Contains a string_storer() function that reads strings in a loop, copies them to a stack buffer, and outputs them back via puts().
Remote target: 154.57.164.72:31410.
Files: arms_roped (ARM ELF binary), libc.so.6 (ARM 32-bit libc), Dockerfile (socat + qemu-arm), patch.diff (QEMU ASLR patch), build_docker.sh.
Protections
| Protection | Status |
|---|---|
| PIE | Enabled |
| NX | Enabled |
| Canary | Enabled |
| RELRO | Partial |
Infrastructure
socat tcp-l:1337,reuseaddr,fork EXEC:./qemu_arm -L /usr/arm-linux-gnueabihf/ ./arms_roped
QEMU user-mode typically doesn't support ASLR. The organizers added a custom patch (patch.diff) that randomizes addresses via srand(time(NULL)) — a weak entropy source, but this doesn't matter for exploitation since we obtain address leaks directly.
Analysis
Key Functions
main() (0x8dc)
Sets up stdout/stderr buffering via setvbuf, then calls string_storer().
string_storer() (0x790) — Vulnerable Function
Loop:
scanf("%m[^\n]%n", &tmp, &n)—%mallocates a heap buffer for input,%nwrites the number of bytes read to a global variablenmemcpy(stack_buf, tmp, n)— copiesnbytes to a 32-byte stack buffer without bounds checkingfree(tmp)— frees the heap buffermemcmp(stack_buf, "quit", 4)— if it starts with "quit", exit the loopputs(stack_buf)— otherwise outputs the buffer contents- Return to step 1
Stack Layout of string_storer()
fp-0x30: buffer[32] ← memcpy destination (32 bytes)
fp-0x10: stack canary ← 4 bytes
fp-0x0c: padding ← 4 bytes
fp-0x08: saved r4 ← 4 bytes
fp-0x04: saved fp ← 4 bytes
fp+0x00: saved lr ← 4 bytes (return address)
...
$ grep --similar
Similar writeups
- [pwn][free]Void— hackthebox
- [reverse][Pro]Aros-25— kalmarctf
- [pwn][Pro]Easy ROP— hackerlab
- [pwn][free]Forks and Knives— hackthebox
- [pwn][Pro]Military System— tamuctf