Cyber News / Article / Linux rootkits explained – Part 1: Dynamic linker hijacking

Linux rootkits explained – Part 1: Dynamic linker hijacking
Dynamic linker hijacking via LD_PRELOAD is a Linux rootkit technique utilized by different threat actors in the wild. In part one of this series on Linux rootkits, we discuss this threat and explain how to detect it.
Rootkitsare a type of malware used by threat actors to gain complete control over a compromised resource and hide malicious activity. They are often part of a broader attack campaign such as stealing sensitive information or conducting espionage. Rootkits can be difficult to detect and remove since they leverage advanced techniques to conceal their presence on a system.
To achieve different capabilities, rootkits intercept and alter normal execution flow. The interception can be in different layers of the operating system, including userland-level code and kernel-level system calls.
In this blog post series, we will focus on Linux because it is the predominant operating system in the cloud. We will cover three different Linux rootkit techniques: dynamic linker hijacking (LD_PRELOAD), Linux Kernel Module (LKM) rootkits, and eBPF rootkits. First, we will explore the userland rootkit technique,LD_PRELOAD. We will describe it, provide examples of its usage in the wild, and explain how to detect it.
Before we delve into the technique itself, let’s first understand what theLinux dynamic linkeris.
In modern operating systems like Windows and Linux, programs can be linked statically or dynamically. Statically linked binaries are compiled together with all dependencies (libraries) needed for execution. Dynamically linked binaries use shared libraries located on the operating system. These libraries will be resolved, loaded, and linked at runtime. The Linux component that is in charge of this operation is thedynamic linker, also known asld.soorld-linux.so.*.
Check it out yourself:
Let’s look at thelsbinary.
1. Thelddcommand allows us to inspect an ELF’s dependencies and shared libraries. Open your terminal and runldd ls. In the output, we can see that thelsbinaryuseslibselinux,libc, andlibpcrelibraries. The first listed dependency is the virtual dynamic shared object, a compact shared library that is automatically mapped into the address space of all user-space applications by the kernel. The last listed dependency is the dynamic linker location.
2. Next, runstrace ls. In thestraceoutput below, the libraries are loaded into memory upon execution.
If we take another look at the output, the system checks for the existence of/etc/ld.so.preload(five lines above the first red box) prior tolibselinuxbeing loaded. This leads us to the next section onLD_PRELOAD.
The Linux dynamic linker provides a significant capability calledLD_PRELOAD.LD_PRELOADholds a list of user-specified, ELF-shared objects. It enables users to load these shared objects into a process's address space before any other shared library and prior to the execution of the program itself. This feature serves multiple purposes, including debugging, testing, and runtime instrumentation, and can be used by writing to the/etc/ld.so.preloadfile or utilizing theLD_PRELOADenvironment variable.
While it has many legitimate uses,LD_PRELOADcan also be leveraged bythreat actorsas it allows the overwriting of existing functions used by dynamically linked programs. This capability also enables them to evade detection, intercept secrets, and generally alter system behavior.
Check it out yourself:
When examining thelssource code, we can see the use oflibc’sreaddirfunction.lsreads the directory entries one by one using thereaddirfunction inside a loop.
Thereaddirfunction returns a pointer to a dirent struct which contains information about the directory entry, such as the name. Once it returns NULL, it indicates the end of the directory.
Let’s create a library that modifies thereaddirfunction to hide a file called "malicious_file", compile it, and add it toLD_PRELOAD:
1. Create the directory/tmp/working-dir-testand copy the code below to thehijackls.cfile under this directory:
In the preload library code above, we define areaddirfunction which acts as an interposed function and is called instead of the originalreaddirwhen thelscommand is executed. Within our interposedreaddirfunction, we obtain the address of the originalreaddirfunction usingdlsym, and then call it to get the next directory entry. We compare the name of each entry with "malicious_file" and skip it if it matches, effectively hiding that file from thelsoutput.
dlsymallows us to obtain the address of a function within a shared object/library at runtime. UsingRTLD_NEXT handle indlsym, we can find and invoke the originalreaddirfunction.
2. Compile the code to a shared object:gcc -shared -fPIC -o /tmp/working-dir-test/libhijackls.so /tmp/working-dir-test/hijackls.c -ldl.
3. Create a directory undertmpand fill it with items:mkdir /tmp/ld-preload-test && cd /tmp/ld-preload-test && for i in file_1 file_2 malicious_file; do touch $i; done;.
4. Runlsand examine all the directory entries.
5. ExportLD_PRELOADto the location of the shared object:export LD_PRELOAD=/tmp/working-dir-test/libhijackls.so.
6. Runlsagain. You will see that we successfully hijacked thereaddirfunction and the output does not contain “malicious_file”.
7. Finally, unset the environment variable by runningunset LD_PRELOAD.
/etc/ld.so.preloadis a system-wide configuration file that applies to all processes and affects the entire system. Access to this file requires root permissions.LD_PRELOAD, on the other hand, is an environment variable that allows individual users to specify libraries to be preloaded for a specific executable or command on a per-process basis. Therefore, you don’t need to be root to use it. Libraries defined byLD_PRELOADare loaded prior to those in/etc/ld.so.preload.
The dynamic linker hijacking rootkit technique has been used by numerous threat actors. Whereas some have generated the logic from scratch, others have used publicly available open-source tools. Here are a few examples:
Winnti for Linux– This Chinese-attributed threat is composed of a user-modeLD_PRELOADrootkit and a main backdoor. The user-mode rootkit is heavily based on the open-sourceAzazelrootkit. Azazel is used to hide processes, network connections, files, and directories, and also contains backdoor capabilities. Winnti for Linux leveraged Azazel to conceal the main backdoor’s malicious activity.
TeamTNT– This group usedlibprocesshiderin different campaigns. Libprocesshider is an open-source tool designed to hide specific processes from commonly used process-listing tools such as ps, top, and lsof by overwriting thereaddirfunction. This technique enabled TeamTNT to conceal XMRig cryptomining and other malicious processes.
Symbiote– Unlike previous examples where the rootkit was an open-source-based side artifact responsible for hiding other malicious campaign activity, Symbiote is both a backdoor and a rootkit written from scratch. Symbiote conceals its malicious activity by hooking functions inlibcandlibpcap. It also uses these capabilities to harvest credentials by hookinglibc’sreadfunction and checking whether the process that is calling it issshorscp. Symbiote leverages its rootkit capabilities for remote access to the machine by hooking Linux Pluggable Authentication Module (PAM) functions and bypassing the authentication mechanism with a hardcoded password match.
OrBit– OrBit is a dynamic linker hijacking rootkit, consisting of a dropper and a malicious shared object. The dropper is tasked with ensuring the shared object is loaded before any other object. To ensure that, OrBit uses two techniques: adding the object path to/etc/ld.so.preloadand patching the loader’s binary by replacing the string of/etc/ld.so.preloadto a dedicated path provided by the malware. Similar to Symbiote, OrBit hooks functions inlibc,libpcapm, and PAM to harvest credentials, evade detection, gain persistence, and provide remote access.
As we saw in the previous examples, attackers useLD_PRELOADto hook different user-land functions and make it hard to investigate infected machines. The following detection methods can help you determine whether you have been infected with this type of rootkit:
For/etc/ld.so.preload: changes in the file will be written to the disk. It is recommended to inspect this file with an image snapshot. If you notice an unusual library path, examine it.
ForLD_PRELOAD: search for processes executed with an unexpectedLD_PRELOADenvironment variable (all environment variables per process are located under the/proc/{pid}/environ file). If you notice an uncommon library path, examine it.
Compare the runtime filesystem to the image snapshot. If there’s a difference, these files might be part of an attack hidden from certain commands.
If you are using a runtime detection tool on containers, make sure it supports drift execution libraries loaded into memory. Drift execution detects executable files that have been added or modified after deploying a container.
Utilize tools likeunhide. Unhide uses different brute force techniques to detect concealed processes.
Moreover, the Wiz runtime sensor detectsLD_PRELOADattacks. See the following example of an alert detailing a modification to/etc/ld.so.preload:
Learn moreabout the Wiz runtime sensor.
Dynamic linker hijacking viaLD_PRELOADis a Linux rootkit technique utilized by different threat actors in the wild. Attackers who successfully deploy this rootkit have powerful control over the infected resource and can benefit from numerous capabilities such as hiding malicious activity and intercepting functions for credential harvesting.
In this blog post, we learned how this rootkit works and provided best practices on how to detect it on your operating system.
Stay tuned for part 2 of this series, where we will delve into Linux Kernel Module (LKM) rootkits.
This blog post was written by Wiz Research, as part of our ongoing mission to analyze threats to the cloud, build mechanisms that prevent and detect them, and fortify cloud security strategies.
In the previous post in this series, we discussed how to do some basic cleaning of AWS access keys. In this post, we’ll show how to reduce the privileges in order to mitigate their risk.
Learn security best practices to deploy generative AI models as part of your multi-tenant cloud applications and avoid putting your customers’ data at risk.
Wiz helps simplify incident response in the cloud for faster investigation of security incidents.
Get a personalized demo
©2026Wiz, Inc.
StatusPrivacy PolicyTerms of UseModern Slavery StatementCookie Settings
You might Also like

Anthropic Says Russian Hackers Used Claude AI to Automate Malware Evasion

GitLab Patches Critical Flaws Enabling Arbitrary File Read, Credential Theft and Remote Code Execution

