$ cat writeup.md…
$ cat writeup.md…
hackthebox
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.
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
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:
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.
Downloaded and analyzed the malicious library libc.hook.so.6:
scp -P 42400 [email protected]:/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:
strings libc.hook.so.6
Revealed:
readdir
pr3l04d_
ld.so.preload
readdir64
fopen
Symbol analysis:
nm -D libc.hook.so.6
Showed hooked functions:
readdir (T at 0x1139)readdir64 (T at 0x11e0)fopen (T at 0x1287)The rootkit hides any files/directories containing:
pr3l04d_ - hidden prefix pattern for malicious filesld.so.preload - hides itself from detectionBy hooking readdir and readdir64, standard tools like ls, find, and even tree cannot see hidden files.
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:
#!/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
Running the script revealed a hidden directory:
/var/pr3l04d_
cat /var/pr3l04d_/flag.txt
| Technique | Description |
|---|---|
| LD_PRELOAD Rootkit Detection | Check /etc/ld.so.preload for malicious libraries |
| Binary Analysis | Use strings, nm, objdump to analyze suspicious binaries |
| Syscall-level Bypass | Direct syscalls bypass userland hooks |
| Linux Internals | Understanding getdents64 syscall and linux_dirent64 structure |
getdents64 syscall goes directly to kernelpr3l04d_ prefix revealed the hiding mechanism$ cat /etc/motd
Liked this one?
Pro unlocks every complete writeup and expanded API access. $9/mo.
$ cat pricing.md$ grep --similar