HTB Sherlock: PhantomRing
On this page
- Task 1: What is the SHA256 hash of the malicious binary?
- Task 2: What is the IP address hardcoded in the binary for C2 communication?
- Task 3: What port does the agent connect to on the C2 server?
- Task 4: How many seconds does the agent wait before attempting to reconnect after a failed connection?
- Task 5: How many different commands does the agent support? (excluding invalid commands)
- Task 6: What Linux kernel interface does this malware abuse to evade EDR syscall monitoring?
- Task 7: What file does the agent read to enumerate logged-in users?
- Task 8: What directory does the agent scan when searching for SUID binaries for privilege escalation?
- Task 9: What string does the agent search for in /proc/[pid]/maps to identify security tools using eBPF?
- Task 10: What is the full path of the first tracing file the agent attempts to disable?
- Task 11: What procfs path does the agent read to find its own executable location before self-destruction?
- Task 12: What command string is compared by the agent to trigger deletion of its own binary?
- Command summary
- Detection notes
PhantomRing
HackTheBox Sherlock, rated Easy. A Linux ELF agent sample to reverse: C2 config, a small command protocol, and some anti-EDR tricks.
Task 1: What is the SHA256 hash of the malicious binary?
Loaded the sample in FLARE-VM and ran it through HashMyFiles for the hash.

Answer: 2d7b1b2178f76c26893b2a56cbf9b36700235259e76b893d53817d5b66b634a5
Task 2: What is the IP address hardcoded in the binary for C2 communication?
Ran strings on the binary. Only one IPv4 came out of the output.
Answer: 192.168.56.1
Task 3: What port does the agent connect to on the C2 server?
Disassembled in Ghidra and traced the IP string reference. Got the connect log line, port wr itten in as a hex:
printf("[+] Connected to %s:%d\n","192.168.56.1",0x115d);0x115d = 4445.
Answer: 4445
Task 4: How many seconds does the agent wait before attempting to reconnect after a failed connection?
Same main function, right after the failure path:
fwrite("connect() failed: trying to reconnect\n",1,0x26,stderr);
...
sleep(0x78);0x78 = 120.
Answer: 120
Task 5: How many different commands does the agent support? (excluding invalid commands)
process_cmd function is a straight chain of strncmp/strcmp checks, one per command, falling through to a “404 Command not found” if nothing matches:
strncmp(param_3,"get ",4) -> cmd_get
strncmp(param_3,"recv ",5) -> cmd_recv
strncmp(param_3,"users",5) -> cmd_users
strncmp(param_3,"ss",2) -> cmd_ss
strcmp(param_3,"netstat") -> cmd_ss
strncmp(param_3,"ps",2) -> cmd_ps
strncmp(param_3,"me",2) -> cmd_me
strncmp(param_3,"kick",4) -> cmd_kick
strncmp(param_3,"privesc",7) -> cmd_privesc
strcmp(param_3,"sdestruct") -> cmd_selfdestruct
strncmp(param_3,"killbpf",7) -> cmd_killbpf
strncmp(param_3,"exit",4) -> cmd_exitThat’s 12 checks, but ss and netstat both route to cmd_ss, so it’s 11 distinct commands.
Answer: 11
Task 6: What Linux kernel interface does this malware abuse to evade EDR syscall monitoring?
Every command handler goes through the same pattern instead of a plain syscall. Deleting a file, for instance:
local_2a0 = io_uring_get_sqe(param_1);
io_uring_prep_unlinkat(local_2a0,0xffffff9c,local_218,0);
io_uring_submit(param_1);
io_uring_wait_cqe(param_1,&local_2b8);File reads, unlinks, everything routed through io_uring submission and completion queues instead of open/read/unlink. EDR hooking on classic syscalls won’t be able to see those actions being performed.
Answer: io_uring
Task 7: What file does the agent read to enumerate logged-in users?
cmd_users reads it from disk with a uring read:
iVar2 = read_file_uring(param_1,"/var/run/utmp",local_4018,0x2000);Answer: /var/run/utmp
Task 8: What directory does the agent scan when searching for SUID binaries for privilege escalation?
cmd_privesc opens the directory and builds a “Potential SUID binaries” report from what it goes through:
local_4330 = opendir("/usr/bin");
...
iVar2 = snprintf(local_4018,0x4000,"Potential SUID binaries:\n");Answer: /usr/bin
Task 9: What string does the agent search for in /proc/[pid]/maps to identify security tools using eBPF?
cmd_killbpf walks /proc/[pid]/maps looking for a loaded BPF map, the signature of an eBPF-based monitor attached to the process:
pcVar4 = strstr(local_4018,"anon_inode:bpf-map");Answer: anon_inode:bpf-map
Task 10: What is the full path of the first tracing file the agent attempts to disable?
Same cmd_killbpf, before the eBPF map scan it goes after ftrace directly. Array of three paths at the function start:
local_6138[0] = "/sys/kernel/debug/tracing/tracing_on";
local_6138[1] = "/sys/kernel/debug/tracing/set_event";
local_6138[2] = "/sys/kernel/debug/tracing/current_tracer";Answer: /sys/kernel/debug/tracing/tracing_on
Task 11: What procfs path does the agent read to find its own executable location before self-destruction?
cmd_selfdestruct resolves its own binary path via the symlink every process has to itself:
sVar1 = strlen("Agent will self-destruct\n");
send_all(param_1,param_2,local_2b0,sVar1);
local_2a8 = readlink("/proc/self/exe",local_218,0x1ff);Answer: /proc/self/exe
Task 12: What command string is compared by the agent to trigger deletion of its own binary?
Back in process_cmd, the branch that routes to cmd_selfdestruct:
iVar1 = strcmp(param_3,"sdestruct");
if (iVar1 == 0) {
cmd_selfdestruct(param_1,param_2);Answer: sdestruct
Command summary
process_cmd (Task 5) in full:
| Command | Handler | Does |
|---|---|---|
get <file> | cmd_get | Exfiltrate a file to the operator |
recv <file> | cmd_recv | Receive a file from the operator |
users | cmd_users | List logged-in users (Task 7) |
ss / netstat | cmd_ss | List network connections |
ps | cmd_ps | List processes |
me | cmd_me | Report agent’s own identity/context |
kick <target> | cmd_kick | Disconnect a client/session |
privesc | cmd_privesc | Scan /usr/bin for SUID binaries (Task 8) |
sdestruct | cmd_selfdestruct | Delete own binary via /proc/self/exe (Tasks 11, 12) |
killbpf | cmd_killbpf | Disable ftrace and hunt eBPF-based monitors (Tasks 9, 10) |
exit | cmd_exit | Close the session |
Detection notes
- Static hash match:
2d7b1b2178f76c26893b2a56cbf9b36700235259e76b893d53817d5b66b634a5. - Outbound to
192.168.56.1:4445, reconnect loop on failure every 120s. - Heavy
io_uringusage for file and process I/O instead of standard syscalls is itself a signal.