Snapekit detection with Wazuh

| by | Wazuh 4.9.1
Post icon

The Snapekit rootkit was reported by Gen Threat Labs on X (formerly Twitter) on October 2, 2024. They identified several behavioral patterns of the rootkit. At the time of writing, all publicly available Snapekit samples specifically target Arch Linux (6.10.2-arch1-1 x86_64). However, the rootkit can be easily adapted to impact other versions of Arch Linux and potentially other Linux distributions.

In this blog post, we analyze Snapekit and demonstrate how Wazuh can detect it. We also illustrate how Wazuh not only detects Snapekit but also uses similar techniques to identify other Linux kernel-mode rootkits.

Static analysis of Snapekit

Hash of sample analyzed:

MD518c23bc9e6dbba7f3cadd59687685718
SHA100a38e5fd7e3303c23596f0ebdbd1f0e3b481ab3
SHA2562600eb7673dddacda0e780bf3b163b0b89b41f9925eebbd2a2b3dfa234bc1a22

We performed further analysis on a Snapekit sample to validate the findings of Gen Threat Labs. Our investigation reveals that Snapekit is embedded in a dropper program designed to evade sandboxes and debuggers. The dropper checks its environment and only unpacks and loads the rootkit if it confirms it is not running within a sandbox. The sandbox evasion capability significantly complicates dynamic analysis.

Static analysis reveals that the names of some sandboxes and debuggers are embedded in the dropper.

Sandboxes dropper

It is embedded with other functionalities to detect sandbox analysis. For example, it checks if the time of the victim endpoint is sped up, an operation commonly performed by sandbox engines.

The dropper spoofs the kworker process name.

Kworker process

kworker is a kernel process in Linux responsible for handling background tasks such as deferred work or scheduled events that are executed in the kernel space.

The dropper then checks if Linux capabilities (CAP) are enabled, and then attempts to escalate privileges by manipulating the capability flags of the current process.

Dropper Linux capabilities

The dropper then unpacks Snapekit as snapekit.ko in the /lib/modules/ directory.

Snapekit dropper
Snapekit directory

The dropper loads the snapekit.ko rootkit module to the kernel.

Snapekit.ko rootkit module

Our analysis of the dropper shows that the embedded rootkit file starts at offset 0x5100 and has the length 0xC4DF8.

Dropper analysis
Rootkit file

Manually unpacking the rootkit

We manually unpack the rootkit to bypass the execution of the dropper. By manually extracting the rootkit file from the dropper, we can examine the embedded payload without triggering any evasion techniques or malicious behaviors that the dropper might employ.

1. We create a Python script unpack.py to unpack the rootkit from the dropper file without executing it:

#!/usr/bin/env python3

from elftools.elf.elffile import ELFFile

def unpack_data_from_elf(file_path, start_address, length):
    with open(file_path, 'rb') as f:
        elffile = ELFFile(f)
        section = elffile.get_section_by_name('.data')
        if section is None:
            print('No .data section found in ELF file.')
            return

        section_offset = section['sh_offset']
        file_offset = start_address - section['sh_addr'] + section_offset
        f.seek(file_offset)
        data = f.read(length)

        with open('snapekit.ko', 'wb') as output_file:
            output_file.write(data)

        print(f'Data extracted to snapekit.ko, length: {length} bytes.')

# Define the parameters
file_path = '/home/user1/snapekit/2600eb7673dddacda0e780bf3b163b0b89b41f9925eebbd2a2b3dfa234bc1a22.elf'
start_address = 0x5100
length = 0xc4df8

# Run the function
unpack_data_from_elf(file_path, start_address, length)

Note: If you want to unpack it yourself, replace the value of the file_path variable with the file path of the dropper on your endpoint.

2. We install pyelftools on Arch Linux, as it is required to run unpack.py, and then proceed to unpack the rootkit:

# pacman -S python-pyelftools
# python3 unpack.py
Data extracted to snapekit.ko, length: 806392 bytes.

We successfully unpacked the rootkit as snapekit.ko with the SHA256 sum  571f2143cf04cca39f92c67a12ea088bf0aee1161f490e1f8a935019939d56cb.

Further analysis of the rootkit file reveals that Snapekit hooks several syscalls including open, read, write, unlink, ptrace, tcp4_seq_show, udp4_seq_show, and others. These hooks enable it to achieve the malicious objectives of the threat actor while maintaining its stealth.

Simulating Snapekit infection

Requirements

  • A deployment of the Wazuh central components version 4.9.1 (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow the Virtual Machine (OVA) – Installation guide to download and set up the Wazuh virtual machine.
  • An Arch Linux (6.10.2-arch1-1 x86_64) victim endpoint with the Wazuh agent installed and enrolled to the Wazuh server. Install the Wazuh agent from source using Pacman, and ensure the Linux CONFIG_MODULE_SIG feature is enabled on this endpoint. For detailed instructions, refer to the Arch Linux documentation on signed kernel modules.

Arch Linux endpoint

To test the Snapekit rootkit, you need to ensure that the kernel of the victim endpoint matches its targeted version (6.10.2-arch1-1 x86_64).

Check your kernel version with the following command:

# uname -r
6.10.2-arch1-1

Running the rootkit

We executed Snapekit’s dropper and found the following artifacts on the victim endpoint to confirm that the rootkit functions are loaded into the kernel.

1. The contents of the /lib/modules/ directory confirms that the dropper unpacked Snapekit:

# ls -l /lib/modules/
total 792
drwxr-xr-x 4 root root   4096 Oct  8 20:43 6.10.2-arch1-1
-rwxr-xr-x 1 root root 806392 Oct 10 10:25 snapekit.ko

The presence of the snapekit.ko file indicates that the rootkit has successfully unpacked itself.

2. The kernel module is loaded:

# lsmod | grep snapekit
snapekit               28672  0

3. Snapekit in the Linux kernel symbol table:

# cat /proc/kallsyms | grep snapekit
ffffffffc0a7d010 t init_callback	[snapekit]
ffffffffc0a81a40 b payload_pid_spinlock	[snapekit]
ffffffffc0a7e910 t change_wp	[snapekit]
ffffffffc0a7e990 t hook_kernelAPI	[snapekit]
ffffffffc0a7e9d0 t unhook_kernelAPI	[snapekit]
ffffffffc0a7d060 t udp6_seq_show_snape	[snapekit]
ffffffffc0a7d120 t udp4_seq_show_snape	[snapekit]
ffffffffc0a7d1e0 t tcp6_seq_show_snape	[snapekit]
ffffffffc0a7d2a0 t tcp4_seq_show_snape	[snapekit]
ffffffffc0a7d360 t check_pid.part.0	[snapekit]
.............

Detection with Wazuh

Wazuh has an in-built rule (rule.id 5132) to detect when unsigned kernel modules are loaded. The image below shows alerts triggered by Wazuh when we execute Snapekit on the monitored endpoint.

Snapekit monitored endpoint

See more details in the expanded alert data below.

Snapekit document details

The highlighted segment in the alert data shows that the operating system generated a log indicating the Snapekit module failed the verification process. This suggests the module was loaded without a valid signature, tainting the kernel and marking it as potentially compromised.

This detection is possible because the monitored endpoint has CONFIG_MODULE_SIG enabled, which allows the system to verify module signatures. When an unsigned or improperly signed module like Snapekit is loaded, it triggers an alert due to the failed verification. You can check this configuration on the endpoint by running the following command:

# zgrep CONFIG_MODULE_SIG /proc/config.gz
CONFIG_MODULE_SIG_FORMAT=y
CONFIG_MODULE_SIG=y
# CONFIG_MODULE_SIG_FORCE is not set
CONFIG_MODULE_SIG_ALL=y
# CONFIG_MODULE_SIG_SHA1 is not set
# CONFIG_MODULE_SIG_SHA256 is not set
# CONFIG_MODULE_SIG_SHA384 is not set
CONFIG_MODULE_SIG_SHA512=y
# CONFIG_MODULE_SIG_SHA3_256 is not set
# CONFIG_MODULE_SIG_SHA3_384 is not set
# CONFIG_MODULE_SIG_SHA3_512 is not set
CONFIG_MODULE_SIG_HASH="sha512"
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
# CONFIG_MODULE_SIG_KEY_TYPE_RSA is not set
CONFIG_MODULE_SIG_KEY_TYPE_ECDSA=y

The example output above indicates that module signature verification is enabled (CONFIG_MODULE_SIG=y), but it is passive. This means the endpoint allows unsigned modules to be loaded, as CONFIG_MODULE_SIG_FORCE is not set. To enforce stricter security and ensure that only signed kernel modules can be loaded, you must enable CONFIG_MODULE_SIG_FORCE. Refer to the kernel module signing facility documentation for more details.

Conclusion

Detecting the Snapekit rootkit with Wazuh highlights the importance of proactive monitoring and endpoint security. Snapekit uses techniques such as sandbox evasion and privilege escalation to maintain stealth and persistence on infected endpoints. Our analysis revealed that it targets the Linux kernel integrity by loading unsigned modules.

Leveraging the Wazuh monitoring capabilities, administrators can detect suspicious activities such as unsigned kernel module loading, which is often a sign of rootkit infection. For enhanced security, enabling strict kernel module signature verification (CONFIG_MODULE_SIG_FORCE) can prevent unauthorized modules from loading, adding a layer of defense against rootkits.

References