Narkoman
Narkoman
Platform: sbpctf | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-03-31 | Status: Solved Techniques: integer_equation_solving, parameter_reconstruction, static_analysis
Summary
Task: a Linux ELF binary asks us to pass all checks before it connects to a remote service. Solution: statically recover the required TASK_PORT argument, solve the quadratic check to get hexadecimal port 15b3, and query the server to receive the flag.
Narkoman — sbpctf
Description
Pass all checks, and app will give you the flag.
Download: https://rev-kids20.forkbomb.ru/files/rev/re3/narkoman.elf
We are given a 64-bit Linux ELF binary. The goal is to understand its checks, supply the expected argument, and recover the server response.
Analysis
Basic triage shows:
- ELF64, dynamically linked, not stripped
- NX enabled, stack canary present, no PIE
- the binary could not be executed locally on macOS, so the task was solved by static analysis
Strings and disassembly reveal that main() does not read the port from standard input. Instead, it scans argv entries with a helper usually decompiled as get_var_val() and searches for a key named TASK_PORT.
The relevant logic is:
c read-only • copy allowedval = get_var_val(argv, "TASK_PORT"); if (val == NULL) fail(); x = strtol(val, NULL, 16); if (!ok(x)) fail(); connect("forkbomb.ru", x);
The important detail is the third argument of strtol: base 16. So the program expects the port value in hexadecimal form, for example TASK_PORT=15b3, not decimal 5555.
The validator is also simple. In pseudocode it becomes:
c read-only • copy allowedbool ok(int x) { return 0 <= x && x <= 0xffff && x * (x + 7) == 0x1d7730e; }
So we need to solve:
text read-only • copy allowedx(x + 7) = 0x1d7730e
Convert the constant to decimal:
text read-only • copy allowed0x1d7730e = 30831374
Then:
text read-only • copy allowedx^2 + 7x - 30831374 = 0
Checking the candidate 5555 gives:
text read-only • copy allowed5562 * 5555 = 5562 * (5000 + 500 + 50 + 5) = 27810000 + 2781000 + 278100 + 27810 = 30831374
So:
text read-only • copy allowedx = 5555
and in hexadecimal:
text read-only • copy allowed5555 = 0x15b3
That exactly matches the input format required by strtol(..., 16).
After passing the local check, the binary connects to forkbomb.ru on port 5555 and prints the remote response. Querying that service returns the flag string directly.
Solution
- Inspect the ELF with static analysis tools.
- Recover that
main()expects anargventry of the formTASK_PORT=<value>. - Notice that the value is parsed with
strtol(..., 16), so the argument must be hexadecimal. - Decompile
ok(int x)and extract the conditionx * (x + 7) == 0x1d7730ewith0 <= x <= 0xffff. - Solve the equation to get
x = 5555 = 0x15b3. - Use
TASK_PORT=15b3as the expected argument value. - Connect to
forkbomb.ru:5555and read the printed response, which is the flag.
A minimal reproduction script is:
python read-only • copy allowed#!/usr/bin/env python3 import socket TARGET = 0x1D7730E HOST = "forkbomb.ru" def solve_port(): for x in range(0x10000): if x * (x + 7) == TARGET: return x raise ValueError("no valid port found") def main(): port = solve_port() print(f"decimal port: {port}") print(f"hex argument: TASK_PORT={port:x}") with socket.create_connection((HOST, port), timeout=5) as sock: data = sock.recv(4096) print(data.decode(errors="replace").strip()) if __name__ == "__main__": main()
Expected output:
text read-only • copy alloweddecimal port: 5555 hex argument: TASK_PORT=15b3 REDACTED