Detection and Removal of the Syslogk Rootkit in a Linux Environment
1. Overview
The AhnLab SEcurity intelligence Center (ASEC) continuously monitors various threats targeting Linux environments. Techniques that modify the Linux kernel to conceal malware and signs of compromise have been used for a long time, and Syslogk is one such rootkit that operates in this manner. This document provides an analysis of the key features and operational mechanisms of the Syslogk rootkit, along with detection and remediation strategies for our products developed based on this analysis.
2. Rootkit Features
The Syslogk rootkit uses inline hooking and VFS table hooking to conceal processes, network communications, and files, and it modifies the execution flow of specific kernel API functions through these methods. Below is a description of these two hooking methods, along with the API functions targeted by each method and their intended purposes.
2.1. Concealment of Processes and TCP Communication (Inline Hooking)
The inline hooking technique directly patches the prologue (OP code section) of an API function to intercept the call to the original API function and ensure that a function defined by the threat actor is executed first.
The address of a specific function is identified through the kernel symbol table (/proc/kallsyms) and stored in a predefined structure for later use.

[Figure 1] Code for finding the address of a specific API function using kallsyms
To disable memory write protection, the Write Protect bit in the CR0 register (a global configuration register that controls the processor’s operating policies, such as protected mode and write protection) is set to 0. Next, the PTE (Page Table Entry) for the memory page containing the API function’s address is retrieved, and write permissions are set. After this process, the data in that page can be modified.

[Figure 2] Code for setting write permissions and tampering with the prologue of a specific API function
Next, the prologue section of the API function is tampered with using the following assembly code. This patched prologue ensures that a threat actor-defined
function is executed when the API is called.
| MOV RAX, [Address of the threat actor’s intended function] PUSH RAX RET |
[Table 1] Example of executing a threat actor-defined function
The two kernel functions subject to inline hooking are `proc_root_readdir` (for process obfuscation) and `tcp4_seq_show` (for TCP socket obfuscation); the purpose of hooking each function is as follows.
2.1.1. Process Concealment (proc_root_readdir)
The `proc_root_readdir` function iterates through process entries in the `/proc` directory and calls registered callback functions. It is called when process-related utilities such as `ps`, `
top`, and `pstree` output a list of processes.
If this function is called while hooked, the function defined by the threat actor will execute, as shown in the image below. The address of the originally passed legitimate callback function (the third argument) is backed up, and the callback function defined by the threat actor is inserted as the third argument before the original `proc_root_readdir` function is called.

[Figure 3] Code that saves the original callback function and configures the system to execute the threat actor’s intended callback function
If the process name is “was_sys_relay” or if that process is the parent or grandparent, the entry is not returned to conceal it. For all other PIDs, the legitimate callback function is executed to make the process visible.

[Figure 4] Part of the code for concealing specific processes
Details regarding the concealment conditions are as follows.
| Concealment Conditions | Whether to Hide the Process |
|---|---|
| PID < 2 | Not hidden |
| “Was_sys_relay” process | Hidden |
| Processes with “was_sys_relay” as the parent process | Hidden |
| Processes for which “was_sys_relay” is the parent process | Hide |
| All other processes | Hide |
[Table 2] Concealment Conditions
2.1.2. TCP Socket Concealment (tcp4_seq_show)
The tcp4_seq_show function outputs information about each TCP socket when reading from /proc/net/tcp, and is called during TCP command execution, such as netstat. It is called once for each socket displayed, and since the output data is stored in the first argument (the `seq_file` structure), a threat actor can manipulate this to conceal information about specific sockets.
If this function is called while hooked, the original function is first executed to output information for a single socket; if a specific port number is included, as shown in the image below, that entry is removed so that the user cannot verify communication on that port.

[Figure 5] Code that removes entries containing specific ports
2.2. File Concealment (VFS Table Hooking)
The VFS (Virtual File System) table is a structure that stores pointers to file system operation functions to handle various file systems through a single common interface. The VFS hooking technique modifies the addresses of such API functions so that a function defined by the threat actor is executed first.
The threat actor performed hooking only on the `readdir` function in the VFS table, changing the `readdir` pointer in the VFS table to the address of a function defined by the threat actor.

[Figure 6] Code for changing the address of the `readdir` function through VFS table hooking
The readdir function tampered with by the threat actor is shown in the image below. Similar to the `proc_root_readdir` function described earlier, the threat actor backs up the address of the originally passed legitimate callback function (the third argument), inserts a callback function defined by the threat actor, and then executes the original `readdir` function.

[Figure 7] Code that backs up the callback function and configures the system to execute the threat actor-defined callback function
In the callback function set by the threat actor, if a file or directory name contains the string “was-patch,” the corresponding entry is not returned, thereby concealing it. If this condition is not met, the normal callback function is executed, making the remaining files or directories appear normal.

[Figure 8] Code that conceals files or directories whose names contain the “was-patch” string
However, since this method does not hide the entire Path, items containing “was-patch” cannot be detected using the `ls` command; nevertheless, it is possible to access the directory through the `cd` command and view the files within it.
2.3. Rootkit Concealment (LKM (Loadable Kernel Module) Concealment)
An LKM is an object file containing code that is dynamically loaded into the running kernel to extend kernel functionality. Syslogk hides the LKM by removing its own module node from the kernel module list.
When the concealment function is called, it first checks whether the location of the existing module node is stored in the `mod_list` variable to determine the current concealment status. If it has not yet been hidden, it backs up the current node location and then removes the node from the doubly linked list that manages kernel modules. As a result, Syslogk does not appear in the list of modules returned by the `lsmod` command.
It also removes its own kobject node from /sys/module. `State_in_sysfs` is a status value indicating whether the object is registered in sysfs; a value of 1 means it is registered. When the node is removed, this value changes to 0; therefore, Syslogk resets the value to 1 to maintain the appearance of being registered. After this process, the module can no longer be found in `/sys/module`.

[Figure 9] Code for hiding the rootkit driver
3. Rootkit Countermeasures
3.1. Rootkit Detection and Remediation
On a system where the Syslogk rootkit is active, as shown in [Figure 10], some files that actually exist do not appear in the output of the `ls` command.

[Figure 10] Status where some files are hidden by the Syslogk rootkit
When the system was scanned using the V3 Net for Linux Server product, it detected the hidden kernel module and was able to restore visibility; after remediation was complete, the previously hidden files could once again be viewed normally. This enables the detection and remediation of kernel-level concealment behaviors that are difficult to identify through standard system checks.

[Figure 11] Results of V3 Net for Linux Server detecting and unhiding a hidden kernel module

[Figure 12] Status showing that previously hidden files are visible again after remediation