npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
When to Use
- When investigating a compromised Linux server or workstation
- For identifying persistence mechanisms (cron, systemd, SSH keys)
- When tracing user activity through shell history and authentication logs
- During incident response to determine the scope of a Linux-based breach
- For detecting rootkits, backdoors, and unauthorized modifications
Prerequisites
- Forensic image or live access to the Linux system (read-only)
- Understanding of Linux file system hierarchy (FHS)
- Knowledge of common Linux logging locations (/var/log/)
- Tools: chkrootkit, rkhunter, AIDE, auditd logs
- Familiarity with systemd, cron, and PAM configurations
- Root access for complete artifact collection
Workflow
Step 1: Mount and Collect System Artifacts
# Mount forensic image read-only
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/linux_evidence.dd /mnt/evidence
# Create collection directories
mkdir -p /cases/case-2024-001/linux/{logs,config,users,persistence,network}
# Collect authentication logs
cp /mnt/evidence/var/log/auth.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/secure* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/syslog* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/kern.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/audit/audit.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/wtmp /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/btmp /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/lastlog /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/faillog /cases/case-2024-001/linux/logs/
# Collect user artifacts
for user_dir in /mnt/evidence/home/*/; do
username=$(basename "$user_dir")
mkdir -p /cases/case-2024-001/linux/users/$username
cp "$user_dir"/.bash_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.zsh_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp -r "$user_dir"/.ssh/ /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.bashrc /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.profile /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.viminfo /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.wget-hsts /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.python_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
done
# Collect root user artifacts
cp /mnt/evidence/root/.bash_history /cases/case-2024-001/linux/users/root/ 2>/dev/null
cp -r /mnt/evidence/root/.ssh/ /cases/case-2024-001/linux/users/root/ 2>/dev/null
# Collect system configuration
cp /mnt/evidence/etc/passwd /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/shadow /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/group /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/sudoers /cases/case-2024-001/linux/config/
cp -r /mnt/evidence/etc/sudoers.d/ /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/hosts /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/resolv.conf /cases/case-2024-001/linux/config/
cp -r /mnt/evidence/etc/ssh/ /cases/case-2024-001/linux/config/Step 2: Analyze User Accounts and Authentication
# Analyze user accounts for anomalies
python3 << 'PYEOF'
print("=== USER ACCOUNT ANALYSIS ===\n")
# Parse /etc/passwd
with open('/cases/case-2024-001/linux/config/passwd') as f:
for line in f:
parts = line.strip().split(':')
if len(parts) >= 7:
username, _, uid, gid, comment, home, shell = parts[0], parts[1], int(parts[2]), int(parts[3]), parts[4], parts[5], parts[6]
# Flag accounts with UID 0 (root equivalent)
if uid == 0 and username != 'root':
print(f" ALERT: UID 0 account: {username} (shell: {shell})")
# Flag accounts with login shells that shouldn't have them
if shell not in ('/bin/false', '/usr/sbin/nologin', '/bin/sync') and uid >= 1000:
print(f" User: {username} (UID:{uid}, Shell:{shell}, Home:{home})")
# Flag system accounts with login shells
if uid < 1000 and uid > 0 and shell in ('/bin/bash', '/bin/sh', '/bin/zsh'):
print(f" WARNING: System account with shell: {username} (UID:{uid}, Shell:{shell})")
# Parse /etc/shadow for account status
print("\n=== PASSWORD STATUS ===")
with open('/cases/case-2024-001/linux/config/shadow') as f:
for line in f:
parts = line.strip().split(':')
if len(parts) >= 3:
username = parts[0]
pwd_hash = parts[1]
last_change = parts[2]
if pwd_hash and pwd_hash not in ('*', '!', '!!', ''):
hash_type = 'Unknown'
if pwd_hash.startswith('$6$'): hash_type = 'SHA-512'
elif pwd_hash.startswith('$5$'): hash_type = 'SHA-256'
elif pwd_hash.startswith('$y$'): hash_type = 'yescrypt'
elif pwd_hash.startswith('$1$'): hash_type = 'MD5 (WEAK)'
print(f" {username}: {hash_type} hash, last changed: day {last_change}")
PYEOF
# Analyze login history
last -f /cases/case-2024-001/linux/logs/wtmp > /cases/case-2024-001/linux/analysis/login_history.txt
lastb -f /cases/case-2024-001/linux/logs/btmp > /cases/case-2024-001/linux/analysis/failed_logins.txt 2>/dev/nullStep 3: Examine Persistence Mechanisms
# Check cron jobs for all users
echo "=== CRON JOBS ===" > /cases/case-2024-001/linux/persistence/cron_analysis.txt
# System cron
for cronfile in /mnt/evidence/etc/crontab /mnt/evidence/etc/cron.d/*; do
echo "--- $cronfile ---" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
cat "$cronfile" 2>/dev/null >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
done
# User cron tabs
for cronfile in /mnt/evidence/var/spool/cron/crontabs/*; do
echo "--- User crontab: $(basename $cronfile) ---" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
cat "$cronfile" 2>/dev/null >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
done
# Check systemd services for persistence
echo "=== SYSTEMD SERVICES ===" > /cases/case-2024-001/linux/persistence/systemd_analysis.txt
find /mnt/evidence/etc/systemd/system/ -name "*.service" -newer /mnt/evidence/etc/os-release \
>> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
for svc in /mnt/evidence/etc/systemd/system/*.service; do
echo "--- $(basename $svc) ---" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
cat "$svc" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
done
# Check authorized SSH keys (backdoor detection)
echo "=== SSH AUTHORIZED KEYS ===" > /cases/case-2024-001/linux/persistence/ssh_keys.txt
find /mnt/evidence/home/ /mnt/evidence/root/ -name "authorized_keys" -exec sh -c \
'echo "--- {} ---"; cat {}; echo ""' \; >> /cases/case-2024-001/linux/persistence/ssh_keys.txt
# Check rc.local and init scripts
cat /mnt/evidence/etc/rc.local 2>/dev/null > /cases/case-2024-001/linux/persistence/rc_local.txt
# Check /etc/profile.d/ for login-triggered scripts
ls -la /mnt/evidence/etc/profile.d/ > /cases/case-2024-001/linux/persistence/profile_scripts.txt
# Check for LD_PRELOAD hijacking
grep -r "LD_PRELOAD" /mnt/evidence/etc/ 2>/dev/null > /cases/case-2024-001/linux/persistence/ld_preload.txt
cat /mnt/evidence/etc/ld.so.preload 2>/dev/null >> /cases/case-2024-001/linux/persistence/ld_preload.txtStep 4: Analyze Shell History and Command Execution
# Analyze bash history for each user
python3 << 'PYEOF'
import os, glob
print("=== SHELL HISTORY ANALYSIS ===\n")
suspicious_commands = [
'wget', 'curl', 'nc ', 'ncat', 'netcat', 'python -c', 'python3 -c',
'perl -e', 'base64', 'chmod 777', 'chmod +s', '/dev/tcp', '/dev/udp',
'nmap', 'masscan', 'hydra', 'john', 'hashcat', 'passwd', 'useradd',
'iptables -F', 'ufw disable', 'history -c', 'rm -rf /', 'dd if=',
'crontab', 'at ', 'systemctl enable', 'ssh-keygen', 'scp ', 'rsync',
'tar czf', 'zip -r', 'openssl enc', 'gpg --encrypt', 'shred',
'chattr', 'setfacl', 'awk', '/tmp/', '/dev/shm/'
]
for hist_file in glob.glob('/cases/case-2024-001/linux/users/*/.bash_history'):
username = hist_file.split('/')[-2]
print(f"User: {username}")
with open(hist_file, 'r', errors='ignore') as f:
lines = f.readlines()
print(f" Total commands: {len(lines)}")
flagged = []
for i, line in enumerate(lines):
line = line.strip()
for cmd in suspicious_commands:
if cmd in line.lower():
flagged.append((i+1, line))
break
if flagged:
print(f" Suspicious commands: {len(flagged)}")
for lineno, cmd in flagged:
print(f" Line {lineno}: {cmd[:120]}")
print()
PYEOFStep 5: Check for Rootkits and Modified Binaries
# Check for known rootkit indicators
# Compare system binary hashes against known-good
find /mnt/evidence/usr/bin/ /mnt/evidence/usr/sbin/ /mnt/evidence/bin/ /mnt/evidence/sbin/ \
-type f -executable -exec sha256sum {} \; > /cases/case-2024-001/linux/analysis/binary_hashes.txt
# Check for SUID/SGID binaries (potential privilege escalation)
find /mnt/evidence/ -perm -4000 -type f 2>/dev/null > /cases/case-2024-001/linux/analysis/suid_files.txt
find /mnt/evidence/ -perm -2000 -type f 2>/dev/null > /cases/case-2024-001/linux/analysis/sgid_files.txt
# Check for suspicious files in /tmp and /dev/shm
find /mnt/evidence/tmp/ /mnt/evidence/dev/shm/ -type f 2>/dev/null \
-exec file {} \; > /cases/case-2024-001/linux/analysis/tmp_files.txt
# Check for hidden files and directories
find /mnt/evidence/ -name ".*" -not -path "*/\." -type f 2>/dev/null | \
head -100 > /cases/case-2024-001/linux/analysis/hidden_files.txt
# Check kernel modules
ls -la /mnt/evidence/lib/modules/$(ls /mnt/evidence/lib/modules/ | head -1)/extra/ 2>/dev/null \
> /cases/case-2024-001/linux/analysis/extra_modules.txt
# Check for modified PAM configuration (authentication backdoors)
diff /mnt/evidence/etc/pam.d/ /cases/baseline/pam.d/ 2>/dev/null \
> /cases/case-2024-001/linux/analysis/pam_changes.txtKey Concepts
| Concept | Description |
|---|---|
| /var/log/auth.log | Primary authentication log on Debian/Ubuntu systems |
| /var/log/secure | Primary authentication log on RHEL/CentOS systems |
| wtmp/btmp | Binary logs recording successful and failed login sessions |
| .bash_history | User command history file (can be cleared by attackers) |
| crontab | Scheduled task system commonly used for persistence |
| authorized_keys | SSH public keys granting passwordless access to an account |
| SUID bit | File permission allowing execution as the file owner (privilege escalation vector) |
| LD_PRELOAD | Environment variable that loads a shared library before all others (hooking technique) |
Tools & Systems
| Tool | Purpose |
|---|---|
| chkrootkit | Rootkit detection scanner for Linux systems |
| rkhunter | Rootkit Hunter - checks for rootkits, backdoors, and local exploits |
| AIDE | Advanced Intrusion Detection Environment - file integrity monitor |
| auditd | Linux audit framework for system call and file access monitoring |
| last/lastb | Parse wtmp/btmp for login and failed login history |
| Plaso/log2timeline | Super-timeline creation including Linux artifacts |
| osquery | SQL-based system querying for live forensic investigation |
| Velociraptor | Endpoint agent with Linux artifact collection capabilities |
Common Scenarios
Scenario 1: SSH Brute Force Followed by Compromise Analyze auth.log for failed SSH attempts followed by success, identify the attacking IP, check .bash_history for post-compromise commands, examine authorized_keys for added backdoor keys, check crontab for persistence, review network connections.
Scenario 2: Web Server Compromise via Application Vulnerability Examine web server access and error logs for exploitation attempts, check /tmp and /dev/shm for webshells, analyze the web server user's activity (www-data), check for privilege escalation via SUID binaries or kernel exploits, review outbound connections.
Scenario 3: Insider Threat on Database Server Analyze the suspect user's bash_history for database dump commands, check for large tar/zip files in home directory or /tmp, examine scp/rsync commands for data transfer, review cron jobs for automated exfiltration, check USB device logs.
Scenario 4: Crypto-Miner on Cloud Instance Check for high-CPU processes in /proc (live) or systemd service files, examine crontab entries for miner restart scripts, check /tmp for mining binaries, analyze network connections for mining pool communications, review authorized_keys for attacker access.
Output Format
Linux Forensics Summary:
System: webserver01 (Ubuntu 22.04 LTS)
Hostname: webserver01.corp.local
Kernel: 5.15.0-91-generic
User Accounts:
Total: 25 (3 with UID 0 - 1 ANOMALOUS)
Interactive shells: 8 users
Recently created: admin2 (created 2024-01-15)
Authentication Events:
Successful SSH logins: 456
Failed SSH attempts: 12,345 (from 23 unique IPs)
Sudo executions: 89
Persistence Mechanisms Found:
Cron jobs: 3 suspicious (reverse shell, miner restart)
Systemd services: 1 unknown (update-checker.service)
SSH keys: 2 unauthorized keys in root authorized_keys
rc.local: Modified with download cradle
Suspicious Activity:
- bash_history contains wget to pastebin URL
- SUID binary /tmp/.hidden/escalate found
- /dev/shm/ contains compiled ELF binary
- LD_PRELOAD in /etc/ld.so.preload pointing to /lib/.hidden.so
Report: /cases/case-2024-001/linux/analysis/References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md3.4 KB
API Reference: Linux Forensic Artifact Analysis Tools
Key Artifact Locations
| Artifact | Path | Description |
|---|---|---|
| Auth logs | /var/log/auth.log (Debian) /var/log/secure (RHEL) |
Authentication events |
| Login history | /var/log/wtmp |
Successful logins (binary, use last) |
| Failed logins | /var/log/btmp |
Failed logins (binary, use lastb) |
| Bash history | ~/.bash_history |
Command history per user |
| SSH keys | ~/.ssh/authorized_keys |
Authorized public keys |
| Crontab | /etc/crontab, /var/spool/cron/crontabs/ |
Scheduled tasks |
| Systemd services | /etc/systemd/system/ |
Service definitions |
| LD_PRELOAD | /etc/ld.so.preload |
Shared library preloading |
| SUID binaries | find / -perm -4000 |
Setuid executables |
last / lastb - Login History
Syntax
last -f /var/log/wtmp # Successful logins
lastb -f /var/log/btmp # Failed logins
last -i -f /var/log/wtmp # Show IP addresses
last -s 2024-01-15 -t 2024-01-20 # Date range filterOutput Format
user pts/0 192.168.1.50 Mon Jan 15 09:00 still logged inchkrootkit - Rootkit Scanner
Syntax
chkrootkit # Full scan
chkrootkit -r /mnt/evidence # Scan mounted evidence
chkrootkit -q # Quiet (infected only)rkhunter - Rootkit Hunter
Syntax
rkhunter --check # Full system check
rkhunter --check --rootdir /mnt/ev # Check evidence root
rkhunter --list tests # List available tests
rkhunter --propupd # Update file properties DBCheck Categories
| Check | Description |
|---|---|
rootkits |
Known rootkit signatures |
trojans |
Trojanized system binaries |
properties |
File permission anomalies |
filesystem |
Hidden files and directories |
auditd Log Parsing
ausearch Syntax
ausearch -m execve -ts recent # Recent command execution
ausearch -m USER_AUTH -ts today # Authentication events
ausearch -k suspicious_activity # Custom audit rule key
ausearch -ua 0 -ts today # Root user actionsaureport Syntax
aureport --auth # Authentication summary
aureport --login # Login summary
aureport --file # File access summary
aureport --summary # Overall summaryosquery - SQL-based System Queries
Syntax
osqueryi "SELECT * FROM users WHERE uid = 0"
osqueryi "SELECT * FROM crontab"
osqueryi "SELECT * FROM authorized_keys"
osqueryi "SELECT * FROM suid_bin"
osqueryi "SELECT * FROM process_open_sockets"Key Tables
| Table | Content |
|---|---|
users |
User account information |
crontab |
Cron job entries |
authorized_keys |
SSH authorized keys |
suid_bin |
SUID binaries |
process_open_sockets |
Network connections by process |
shell_history |
Command history entries |
Plaso / log2timeline - Super Timeline
Syntax
log2timeline.py /cases/timeline.plaso /mnt/evidence
psort.py -o l2tcsv /cases/timeline.plaso > timeline.csv
psort.py -o l2tcsv /cases/timeline.plaso "date > '2024-01-15'"AIDE - File Integrity
Syntax
aide --init # Initialize database
aide --check # Check for changes
aide --compare # Compare databasesScripts 1
agent.py9.7 KB
#!/usr/bin/env python3
"""Linux system artifact forensics agent for investigating compromised systems."""
import os
import sys
import glob
import shlex
import subprocess
def run_cmd(cmd):
"""Execute a command and return output."""
if isinstance(cmd, str):
cmd = shlex.split(cmd)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
return result.stdout.strip(), result.stderr.strip(), result.returncode
def analyze_passwd(passwd_path):
"""Analyze /etc/passwd for suspicious accounts."""
findings = []
with open(passwd_path, "r") as f:
for line in f:
parts = line.strip().split(":")
if len(parts) < 7:
continue
username, _, uid, gid = parts[0], parts[1], int(parts[2]), int(parts[3])
home, shell = parts[5], parts[6]
if uid == 0 and username != "root":
findings.append({
"severity": "CRITICAL",
"finding": f"UID 0 account: {username} (shell: {shell})",
})
login_shells = ["/bin/bash", "/bin/sh", "/bin/zsh", "/usr/bin/zsh"]
if uid < 1000 and uid > 0 and shell in login_shells:
findings.append({
"severity": "WARNING",
"finding": f"System account with login shell: {username} (UID:{uid})",
})
if uid >= 1000 and shell not in ["/bin/false", "/usr/sbin/nologin", "/bin/sync"]:
findings.append({
"severity": "INFO",
"finding": f"Interactive user: {username} (UID:{uid}, Home:{home})",
})
return findings
def analyze_shadow(shadow_path):
"""Analyze /etc/shadow for password hash types and status."""
findings = []
with open(shadow_path, "r") as f:
for line in f:
parts = line.strip().split(":")
if len(parts) < 3:
continue
username = parts[0]
pwd_hash = parts[1]
if pwd_hash and pwd_hash not in ("*", "!", "!!", ""):
hash_type = "Unknown"
if pwd_hash.startswith("$6$"):
hash_type = "SHA-512"
elif pwd_hash.startswith("$5$"):
hash_type = "SHA-256"
elif pwd_hash.startswith("$y$"):
hash_type = "yescrypt"
elif pwd_hash.startswith("$1$"):
hash_type = "MD5 (WEAK)"
findings.append({
"severity": "WARNING",
"finding": f"{username} uses weak MD5 password hash",
})
findings.append({
"severity": "INFO",
"finding": f"{username}: {hash_type} hash, last changed day {parts[2]}",
})
return findings
def analyze_bash_history(history_path, username="unknown"):
"""Analyze bash history for suspicious commands."""
suspicious_patterns = [
"wget", "curl", "nc ", "ncat", "netcat", "python -c", "python3 -c",
"perl -e", "base64", "chmod 777", "chmod +s", "/dev/tcp", "/dev/udp",
"nmap", "masscan", "hydra", "john", "hashcat", "passwd", "useradd",
"iptables -F", "ufw disable", "history -c", "rm -rf", "dd if=",
"crontab", "systemctl enable", "ssh-keygen", "scp ", "rsync",
"/tmp/", "/dev/shm/", "mkfifo", "socat",
]
findings = []
with open(history_path, "r", errors="ignore") as f:
lines = f.readlines()
for i, line in enumerate(lines):
line_stripped = line.strip()
for pattern in suspicious_patterns:
if pattern in line_stripped.lower():
findings.append({
"user": username,
"line_number": i + 1,
"command": line_stripped[:200],
"matched_pattern": pattern,
})
break
return findings
def check_cron_persistence(evidence_root):
"""Check cron jobs for persistence mechanisms."""
findings = []
cron_paths = [
os.path.join(evidence_root, "etc/crontab"),
*glob.glob(os.path.join(evidence_root, "etc/cron.d/*")),
*glob.glob(os.path.join(evidence_root, "var/spool/cron/crontabs/*")),
]
for cron_path in cron_paths:
if os.path.exists(cron_path) and os.path.isfile(cron_path):
with open(cron_path, "r", errors="ignore") as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
suspicious = any(
p in line.lower()
for p in ["wget", "curl", "/tmp/", "/dev/shm/", "base64",
"python", "bash -i", "reverse", "nc ", "ncat"]
)
if suspicious:
findings.append({
"severity": "HIGH",
"source": cron_path,
"entry": line[:200],
})
return findings
def check_ssh_keys(evidence_root):
"""Check for unauthorized SSH authorized_keys."""
findings = []
key_files = glob.glob(
os.path.join(evidence_root, "home/*/.ssh/authorized_keys")
) + glob.glob(
os.path.join(evidence_root, "root/.ssh/authorized_keys")
)
for key_file in key_files:
if os.path.exists(key_file):
with open(key_file, "r") as f:
keys = [l.strip() for l in f if l.strip() and not l.startswith("#")]
if keys:
findings.append({
"file": key_file,
"key_count": len(keys),
"keys": [k[:80] + "..." for k in keys],
})
return findings
def check_systemd_persistence(evidence_root):
"""Check for suspicious systemd service files."""
findings = []
service_dirs = [
os.path.join(evidence_root, "etc/systemd/system"),
os.path.join(evidence_root, "usr/lib/systemd/system"),
]
for svc_dir in service_dirs:
if not os.path.exists(svc_dir):
continue
for svc_file in glob.glob(os.path.join(svc_dir, "*.service")):
with open(svc_file, "r", errors="ignore") as f:
content = f.read()
suspicious = any(
p in content.lower()
for p in ["/tmp/", "/dev/shm/", "wget", "curl", "reverse",
"bash -i", "nc ", "python", "base64"]
)
if suspicious:
findings.append({
"severity": "HIGH",
"file": svc_file,
"preview": content[:300],
})
return findings
def check_ld_preload(evidence_root):
"""Check for LD_PRELOAD rootkit indicators."""
findings = []
preload_path = os.path.join(evidence_root, "etc/ld.so.preload")
if os.path.exists(preload_path):
with open(preload_path, "r") as f:
content = f.read().strip()
if content:
findings.append({
"severity": "CRITICAL",
"finding": f"/etc/ld.so.preload contains: {content}",
})
return findings
def find_suid_binaries(evidence_root):
"""Find SUID/SGID binaries (potential privilege escalation)."""
result = subprocess.run(
["find", evidence_root, "-perm", "-4000", "-type", "f"],
capture_output=True, text=True, timeout=30
)
stdout = result.stdout.strip()
return stdout.splitlines() if result.returncode == 0 and stdout else []
def find_suspicious_tmp_files(evidence_root):
"""Find suspicious files in /tmp and /dev/shm."""
findings = []
for tmp_dir in ["tmp", "dev/shm"]:
full_path = os.path.join(evidence_root, tmp_dir)
if os.path.exists(full_path):
for root, dirs, files in os.walk(full_path):
for fname in files:
fpath = os.path.join(root, fname)
findings.append(fpath)
return findings
if __name__ == "__main__":
print("=" * 60)
print("Linux System Artifacts Forensics Agent")
print("User accounts, persistence, shell history, rootkit detection")
print("=" * 60)
evidence_root = sys.argv[1] if len(sys.argv) > 1 else "/mnt/evidence"
if os.path.exists(evidence_root):
print(f"\n[*] Examining evidence root: {evidence_root}")
passwd_path = os.path.join(evidence_root, "etc/passwd")
if os.path.exists(passwd_path):
print("\n--- User Account Analysis ---")
for f in analyze_passwd(passwd_path):
print(f" [{f['severity']}] {f['finding']}")
print("\n--- Cron Persistence ---")
cron = check_cron_persistence(evidence_root)
for c in cron:
print(f" [{c['severity']}] {c['source']}: {c['entry'][:80]}")
print("\n--- SSH Authorized Keys ---")
ssh = check_ssh_keys(evidence_root)
for s in ssh:
print(f" {s['file']}: {s['key_count']} keys")
print("\n--- Systemd Persistence ---")
systemd = check_systemd_persistence(evidence_root)
for s in systemd:
print(f" [{s['severity']}] {s['file']}")
print("\n--- LD_PRELOAD Rootkit Check ---")
ld = check_ld_preload(evidence_root)
for l in ld:
print(f" [{l['severity']}] {l['finding']}")
print("\n--- Suspicious Temp Files ---")
tmp = find_suspicious_tmp_files(evidence_root)
for t in tmp[:20]:
print(f" {t}")
else:
print(f"\n[DEMO] Usage: python agent.py <evidence_mount_point>")
print("[*] Mount a forensic image and provide the path for analysis.")