Greetings
tjctf
Task: 64-bit PIE ELF with executable stack and no canary; user controls fgets size causing stack buffer overflow. Solution: inject shellcode in buffer, skip printf to preserve RAX (buffer pointer from fgets), partial-overwrite return address to jmp rax gadget with 1/16 PIE brute force.
$ 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.
Greetings — TJCTF 2026
Description
Greetings from TJ to you. Find the exploit, yes please do. Remote:
nc tjc.tf 31373
We are given a 64-bit PIE ELF binary with source code. The program asks for a username size and a username, then greets the user if the name starts with @. The binary has an executable stack, no canary, and partial RELRO. A provided libc (Ubuntu GLIBC 2.42) and loader are included.
Analysis
Source Code
void greetUser() { int uname_size; char uname[64]; printf("Enter the size of your username: "); scanf("%d", &uname_size); getchar(); uname_size += 2; printf("Enter username (start with @): "); fgets(uname, uname_size, stdin); if (*(char *) uname == '@') { printf("Greetings to you: %s!", uname); } }
Vulnerability
The user controls uname_size via scanf("%d"). After +2 is added, this value is passed directly to fgets(uname, uname_size, stdin). Since uname is only 64 bytes on the stack, providing a large size causes a classic stack buffer overflow past saved registers and the return address. No stack canary protects the function.
Binary Protections
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
The executable stack (RWX) is the critical enabler — shellcode injection is viable.
Stack Layout
From disassembly of greetUser:
greetUser:
pushq %rbx ; save RBX
subq $0x50, %rsp ; allocate 0x50 = 80 bytes
rsp+0x0c: uname_size (4 bytes, int)
rsp+0x10: uname[64] (64-byte buffer)
rsp+0x50: saved RBX (8 bytes)
rsp+0x58: return address (8 bytes) -> main+9 = PIE_base + 0x1089
Offsets from uname buffer start:
- Saved RBX: offset 64 (0x40)
- Return address: offset 72 (0x48)
Key Gadgets
...
$ grep --similar
Similar writeups
- [pwn][free]ipv8— umdctf
- [pwn][free]Regularity— hackthebox
- [pwn][Pro]Taste— grodno_new_year_2026
- [pwn][Pro]Говори - и будет исполнено (ask_and_you_shall_receive)— hackerlab
- [pwn][free]Getting Started— hackthebox