← Back to Writeups
HTBMediumForensics

Suspicious Threat Challenge

D3v0o0Nu119/2/20265 min read
#forensics#htb#medium#binary_analysis#getdents64#ld_preload_detection#syscall_bypass#linux

Suspicious Threat Challenge

Platform: HackTheBox | Category: Forensics | Type: Challenge | Difficulty: Medium | OS: Linux | Author: D3v0o0Nu11 | Date: 2026-02-03 | Status: Solved Techniques: binary_analysis, getdents64, ld_preload_detection, syscall_bypass

Summary

Task: Linux server s userland rootkit cherez LD_PRELOAD, skryvayushchim fajly/direktorii. Solution: Analiz malicious library (libc.hook.so.6), obnaruzhenie hooked funkcij readdir/readdir64, bypass cherez pryamoj syscall getdents64 dlya poiska skrytoj direktorii s flagom.

Recon

Port scan

bash
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: hackthebox | ID: 20260203_htb_suspicious_threat
  • Tags: linux, forensics, rootkit, ld_preload, userland_rootkit
  • Indicators: /etc/ld.so.preload exists, library linking errors, missing directories, hooked readdir/readdir64, hidden files with prefix pattern
  • Source: 20260203_htb_suspicious_threat.md

Foothold

Vulnerability / Misconfiguration

  1. binary_analysis
  2. getdents64
  3. ld_preload_detection
  4. syscall_bypass
bash
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

bash
sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
bash
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • binary_analysis
  • getdents64
  • ld_preload_detection
  • syscall_bypass
  • Tags: linux, forensics, rootkit, ld_preload, userland_rootkit

Original Writeup

<details><summary>Click to expand original content</summary>

Description

Our SSH server is showing strange library linking errors, and critical folders seem to be missing despite their confirmed existence. Investigate the anomalies in the library loading process and filesystem. Look for hidden manipulations that could indicate a userland rootkit.

Credentials provided: root:hackthebox on 94.237.120.137:42400

Analysis

Step 1: Initial Reconnaissance

Connected to the SSH server and checked for rootkit indicators. The first thing to check when investigating potential userland rootkits is /etc/ld.so.preload:

bash
cat /etc/ld.so.preload

Found suspicious entry:

/lib/x86_64-linux-gnu/libc.hook.so.6

This file forces the dynamic linker to load a malicious shared library before any other library, allowing function hooking.

Step 2: Rootkit Library Analysis

Downloaded and analyzed the malicious library libc.hook.so.6:

bash
scp -P 42400 root@94.237.120.137:/lib/x86_64-linux-gnu/libc.hook.so.6 .
file libc.hook.so.6

Output:

libc.hook.so.6: ELF 64-bit LSB shared object, x86-64

Source file was hider.c (found via strings analysis).

Strings analysis:

bash
strings libc.hook.so.6

Revealed:

readdir
pr3l04d_
ld.so.preload
readdir64
fopen

Symbol analysis:

bash
nm -D libc.hook.so.6

Showed hooked functions:

  • readdir (T at 0x1139)
  • readdir64 (T at 0x11e0)
  • fopen (T at 0x1287)

Rootkit Behavior

The rootkit hides any files/directories containing:

  1. pr3l04d_ - hidden prefix pattern for malicious files
  2. ld.so.preload - hides itself from detection

By hooking readdir and readdir64, standard tools like ls, find, and even tree cannot see hidden files.

Solution

Step 3: Bypassing the Rootkit

Since the rootkit hooks userland libc functions, we need to bypass them by using direct syscalls to the kernel. The getdents64 syscall (syscall 217 on x86_64) reads directory entries directly without going through libc.

Created a Python script using ctypes to invoke the syscall directly:

python
#!/usr/bin/env python3
"""
Bypass LD_PRELOAD rootkit by using direct syscalls.
The rootkit hooks readdir/readdir64 in libc, but cannot intercept
direct syscalls to the kernel.
"""
import os
import ctypes
import struct

SYS_getdents64 = 217  # x86_64 syscall number for getdents64
libc = ctypes.CDLL(None)
syscall = libc.syscall

def getdents(path):
    """
    Read directory entries using direct syscall.
    Bypasses any userland hooks on readdir/readdir64.
    """
    fd = os.open(path, os.O_RDONLY | os.O_DIRECTORY)
    buf = ctypes.create_string_buffer(32768)
    
    entries = []
    while True:
        nread = syscall(SYS_getdents64, fd, buf, 32768)
        if nread <= 0:
            break
        
        offset = 0
        while offset < nread:
            # Parse linux_dirent64 structure
            d_ino, d_off, d_reclen, d_type = struct.unpack_from('QQHb', buf.raw, offset)
            name_start = offset + 19
            name_end = buf.raw.find(b'\x00', name_start)
            name = buf.raw[name_start:name_end].decode('utf-8', errors='replace')
            entries.append(name)
            offset += d_reclen
    
    os.close(fd)
    return entries

# Search common directories for hidden files
for d in ['/', '/root', '/tmp', '/home', '/var', '/etc', '/lib/x86_64-linux-gnu']:
    try:
        entries = getdents(d)
        for e in entries:
            if 'pr3l04d' in e or 'flag' in e.lower():
                print(f"{d}/{e}")
    except:
        pass

Step 4: Finding the Hidden Directory

Running the script revealed a hidden directory:

/var/pr3l04d_

Step 5: Retrieving the Flag

bash
cat /var/pr3l04d_/flag.txt

Key Techniques

TechniqueDescription
LD_PRELOAD Rootkit DetectionCheck /etc/ld.so.preload for malicious libraries
Binary AnalysisUse strings, nm, objdump to analyze suspicious binaries
Syscall-level BypassDirect syscalls bypass userland hooks
Linux InternalsUnderstanding getdents64 syscall and linux_dirent64 structure

Tools Used

  • SSH/SCP - Remote access and file transfer
  • strings - Extract readable strings from binaries
  • nm - List symbols from object files
  • objdump - Display information from object files
  • Python3 + ctypes - Direct syscall execution

Lessons Learned

  1. Userland rootkits are limited - They can only hook userland functions, not kernel syscalls
  2. Always check ld.so.preload - First thing to verify when investigating Linux rootkits
  3. Direct syscalls bypass hooks - getdents64 syscall goes directly to kernel
  4. Binary analysis reveals intent - Strings and symbols show what functions are hooked
  5. Hidden patterns are clues - The pr3l04d_ prefix revealed the hiding mechanism

References

</details>

signed by XESXOR