analyzing-linux-elf-malware
SKILL.md
Analyzing Linux ELF Malware
When to Use
- A Linux server or container has been compromised and suspicious ELF binaries are found
- Analyzing Linux botnets (Mirai, Gafgyt, XorDDoS), cryptominers, or ransomware
- Investigating malware targeting cloud infrastructure, Docker containers, or Kubernetes pods
- Reverse engineering Linux rootkits and kernel modules
- Analyzing cross-platform malware compiled for Linux x86_64, ARM, or MIPS architectures
Do not use for Windows PE binary analysis; use PEStudio, Ghidra, or IDA for Windows malware.
Prerequisites
- Ghidra or IDA with Linux ELF support for disassembly and decompilation
- Linux analysis VM (Ubuntu 22.04 recommended) with development tools installed
- strace, ltrace, and GDB for dynamic analysis and debugging
- readelf, objdump, and nm from GNU binutils for static inspection
- Radare2 for quick binary triage and scripted analysis
- Docker for isolated container-based malware execution
Workflow
Step 1: Identify ELF Binary Properties
Examine the ELF header and basic properties:
# File type identification
file suspect_binary
# Detailed ELF header analysis
readelf -h suspect_binary
# Section headers
readelf -S suspect_binary
# Program headers (segments)
readelf -l suspect_binary
# Symbol table (if not stripped)
readelf -s suspect_binary
nm suspect_binary 2>/dev/null
# Dynamic linking information
readelf -d suspect_binary
ldd suspect_binary 2>/dev/null # Only on matching architecture!
# Compute hashes
md5sum suspect_binary
sha256sum suspect_binary
# Check for packing/UPX
upx -t suspect_binary
# Python-based ELF analysis
from elftools.elf.elffile import ELFFile
import hashlib
with open("suspect_binary", "rb") as f:
data = f.read()
sha256 = hashlib.sha256(data).hexdigest()
with open("suspect_binary", "rb") as f:
elf = ELFFile(f)
print(f"SHA-256: {sha256}")
print(f"Class: {elf.elfclass}-bit")
print(f"Endian: {elf.little_endian and 'Little' or 'Big'}")
print(f"Machine: {elf.header.e_machine}")
print(f"Type: {elf.header.e_type}")
print(f"Entry Point: 0x{elf.header.e_entry:X}")
# Check if stripped
symtab = elf.get_section_by_name('.symtab')
print(f"Stripped: {'Yes' if symtab is None else 'No'}")
# Section entropy analysis
import math
from collections import Counter
for section in elf.iter_sections():
data = section.data()
if len(data) > 0:
entropy = -sum((c/len(data)) * math.log2(c/len(data))
for c in Counter(data).values() if c > 0)
if entropy > 7.0:
print(f" [!] High entropy section: {section.name} ({entropy:.2f})")
Step 2: Extract Strings and Indicators
Search for embedded IOCs and functionality clues:
# ASCII strings
strings suspect_binary > strings_output.txt
# Search for network indicators
grep -iE "(http|https|ftp)://" strings_output.txt
grep -iE "([0-9]{1,3}\.){3}[0-9]{1,3}" strings_output.txt
grep -iE "[a-zA-Z0-9.-]+\.(com|net|org|io|ru|cn)" strings_output.txt
# Search for shell commands
grep -iE "(bash|sh|wget|curl|chmod|/tmp/|/dev/)" strings_output.txt
# Search for crypto mining indicators
grep -iE "(stratum|xmr|monero|pool\.|mining)" strings_output.txt
# Search for SSH/credential theft
grep -iE "(ssh|authorized_keys|id_rsa|shadow|passwd)" strings_output.txt
# Search for persistence mechanisms
grep -iE "(crontab|systemd|init\.d|rc\.local|ld\.so\.preload)" strings_output.txt
# FLOSS for obfuscated strings (if available)
floss suspect_binary
Step 3: Analyze System Calls and Library Usage
Identify what system calls and libraries the malware uses:
# List imported functions (dynamically linked)
readelf -r suspect_binary | grep -E "socket|connect|exec|fork|open|write|bind|listen"
# Trace system calls during execution (in isolated VM only)
strace -f -e trace=network,process,file -o strace_output.txt ./suspect_binary
# Trace library calls
ltrace -f -o ltrace_output.txt ./suspect_binary
# Key system calls to watch:
# Network: socket, connect, bind, listen, accept, sendto, recvfrom
# Process: fork, execve, clone, kill, ptrace
# File: open, read, write, unlink, rename, chmod
# Persistence: inotify_add_watch (file monitoring)
Step 4: Dynamic Analysis with GDB
Debug the malware to observe runtime behavior:
# Start GDB with the binary
gdb ./suspect_binary
# Set breakpoints on key functions
(gdb) break main
(gdb) break socket
(gdb) break connect
(gdb) break execve
(gdb) break fork
# Run and analyze
(gdb) run
(gdb) info registers # View register state
(gdb) x/20s $rdi # Examine string argument
(gdb) bt # Backtrace
(gdb) continue
# For stripped binaries, break on entry point
(gdb) break *0x400580 # Entry point from readelf
(gdb) run
# Monitor network connections during execution
# In another terminal:
ss -tlnp # List listening sockets
ss -tnp # List established connections
Step 5: Reverse Engineer with Ghidra
Perform deep code analysis on the ELF binary:
Ghidra Analysis for Linux ELF:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Import: File -> Import -> Select ELF binary
- Ghidra auto-detects ELF format and architecture
- Accept default analysis options
2. Key analysis targets:
- main() function (or entry point if stripped)
- Socket creation and connection functions
- Command dispatch logic (switch/case on received data)
- Encryption/encoding routines
- Persistence installation code
- Self-propagation/scanning functions
3. For Mirai-like botnets, look for:
- Credential list for brute-forcing (telnet/SSH)
- Attack module selection (UDP flood, SYN flood, ACK flood)
- Scanner module (port scanning for vulnerable devices)
- Killer module (killing competing botnets)
4. For cryptominers, look for:
- Mining pool connection (stratum protocol)
- Wallet address strings
- CPU/GPU utilization functions
- Process hiding techniques
Step 6: Analyze Linux-Specific Persistence
Check for persistence mechanisms:
# Check for LD_PRELOAD rootkit
strings suspect_binary | grep "ld.so.preload"
# Malware writing to /etc/ld.so.preload can hook all dynamic library calls
# Check for crontab persistence
strings suspect_binary | grep -i "cron"
# Check for systemd service creation
strings suspect_binary | grep -iE "systemd|\.service|systemctl"
# Check for init script creation
strings suspect_binary | grep -iE "init\.d|rc\.local|update-rc"
# Check for SSH key injection
strings suspect_binary | grep -i "authorized_keys"
# Check for kernel module (rootkit) loading
strings suspect_binary | grep -iE "insmod|modprobe|init_module"
# Check for process hiding
strings suspect_binary | grep -iE "proc|readdir|getdents"
Key Concepts
| Term | Definition |
|---|---|
| ELF (Executable and Linkable Format) | Standard binary format for Linux executables, shared libraries, and core dumps containing headers, sections, and segments |
| Stripped Binary | ELF binary with debug symbols removed, making reverse engineering more difficult as function names are lost |
| LD_PRELOAD | Linux environment variable specifying shared libraries to load before all others; abused by rootkits to intercept system library calls |
| strace | Linux system call tracer that logs all system calls and signals made by a process, revealing file, network, and process operations |
| GOT/PLT | Global Offset Table and Procedure Linkage Table; ELF structures for dynamic linking that can be hijacked for function hooking |
| Statically Linked | Binary compiled with all library code included; common in IoT malware to run on systems without matching shared libraries |
| Mirai | Prolific Linux botnet targeting IoT devices via telnet brute-force; source code leaked, leading to many variants |
Tools & Systems
- Ghidra: NSA reverse engineering tool with full ELF support for x86, x86_64, ARM, MIPS, and other Linux architectures
- Radare2: Open-source reverse engineering framework with command-line interface for quick binary analysis and scripting
- strace: Linux system call tracing tool for observing binary behavior including file, network, and process operations
- GDB: GNU Debugger for setting breakpoints, examining memory, and stepping through Linux binary execution
- pyelftools: Python library for parsing ELF files programmatically for automated analysis pipelines
Common Scenarios
Scenario: Analyzing a Cryptominer Found on a Compromised Linux Server
Context: A cloud server shows 100% CPU usage. Investigation reveals an unknown binary running from /tmp with a suspicious name. The binary needs analysis to confirm it is a cryptominer and identify the attacker's wallet and pool.
Approach:
- Copy the binary to an analysis VM and compute SHA-256 hash
- Run
fileandreadelfto identify architecture and linking type - Extract strings and search for mining pool addresses (stratum+tcp://) and wallet addresses
- Run with strace in a sandbox to observe network connections (mining pool connection)
- Import into Ghidra to identify the mining algorithm and configuration extraction
- Check for persistence mechanisms (crontab, systemd service, SSH keys)
- Document all IOCs including pool address, wallet, C2 for updates, and persistence artifacts
Pitfalls:
- Running
lddon malware outside a sandbox (ldd can execute code in the binary) - Not checking for ARM/MIPS architecture before attempting x86_64 execution
- Missing companion scripts (.sh files) that may handle persistence and cleanup
- Ignoring the initial access vector (how the miner was deployed: SSH brute force, web exploit, container escape)
Output Format
LINUX ELF MALWARE ANALYSIS REPORT
====================================
File: /tmp/.X11-unix/.rsync
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
Type: ELF 64-bit LSB executable, x86-64
Linking: Statically linked (all libraries embedded)
Stripped: Yes
Size: 2,847,232 bytes
Packer: UPX 3.96 (unpacked for analysis)
CLASSIFICATION
Family: XMRig Cryptominer (modified)
Variant: Custom build with C2 update mechanism
FUNCTIONALITY
[*] XMR (Monero) mining via RandomX algorithm
[*] Stratum pool connection for work submission
[*] C2 check-in for configuration updates
[*] Process name masquerading (argv[0] = "[kworker/0:0]")
[*] Competitor process killing (kills other miners)
[*] SSH key injection for re-access
NETWORK INDICATORS
Mining Pool: stratum+tcp://pool.minexmr[.]com:4444
C2 Server: hxxp://update.malicious[.]com/config
Wallet: 49jZ5Q3b...Monero_Wallet_Address...
PERSISTENCE
[1] Crontab entry: */5 * * * * /tmp/.X11-unix/.rsync
[2] SSH key added to /root/.ssh/authorized_keys
[3] Systemd service: /etc/systemd/system/rsync-daemon.service
[4] Modified /etc/ld.so.preload for process hiding
PROCESS HIDING
LD_PRELOAD: /usr/lib/.libsystem.so
Hook: readdir() to hide /tmp/.X11-unix/.rsync from ls
Hook: fopen() to hide from /proc/*/maps reading
Weekly Installs
2
Repository
mukul975/anthro…y-skillsGitHub Stars
873
First Seen
1 day ago
Security Audits
Installed on
amp2
cline2
opencode2
cursor2
kimi-cli2
codex2