Can You Trust ps, netstat, and ss on a Compromised Linux Host? Meet LinIR

The article examines why traditional Linux commands like ps, netstat, and ss cannot be trusted on a potentially root‑kit‑infected system, introduces the LinIR tool that collects forensic data without relying on the host's user‑space toolchain, and compares it against manual scripts, other automation tools, and commercial EDR solutions.

Black & White Path
Black & White Path
Black & White Path
Can You Trust ps, netstat, and ss on a Compromised Linux Host? Meet LinIR

Problem

In incident response the first step is to enumerate running processes, network sockets, cron jobs and systemd units. Common commands such as ps aux, netstat -tnlp, ss -tnp, crontab -l and systemctl list-units can be hijacked, hidden or return falsified output when a root‑kit controls the host, making the enumeration unreliable.

LinIR Overview

LinIR (Linux Incident Response) is a single‑binary forensic triage tool for Linux and macOS. Its design principle is zero trust of any command on the target host . Instead of invoking user‑space tools it reads kernel interfaces directly:

Process information from /proc/<pid>/stat, /proc/<pid>/exe and /proc/<pid>/cmdline.

Network connections by parsing /proc/net/tcp and /proc/net/tcp6 and matching socket inodes via /proc/<pid>/fd/.

Systemd unit files are inspected directly (fields such as ExecStart, Environment, WantedBy).

Cron jobs are read from the raw files in /etc/crontab, /etc/cron.d/ and /var/spool/cron/.

On macOS it uses syscall‑level interfaces ( sysctl, proc_pidinfo, proc_pidfdinfo).

The binary is built with CGO_ENABLED=0, statically compiled, and can be copied to any target host and executed as a single file.

Comparison with Existing Approaches

Manual command line

Trust model: fully trusts system commands.

Rootkit resistance: none.

Environment detection: none.

Result format: plain text, requires manual post‑processing.

Reproducibility: low, depends on operator.

Scoring: none.

Automation scripts (e.g., GScan, LinPEAS)

Implementation: shell/Python scripts that call system commands.

Rootkit scenario: output can be tampered.

Cross‑platform: usually Linux only.

Dependencies: requires bash, python or perl.

Maintenance cost: fragmented scripts.

Commercial EDR solutions

Deployment: requires persistent agent installation.

Permission: needs persistent root privileges.

Use‑case: continuous monitoring.

Network requirement: often needs cloud communication.

Cost: commercial license.

Core Features

One‑Shot Collection

sudo ./linir collect --yara-rules /opt/rules/ --bundle

The command performs a self‑check, environment pre‑check, process enumeration, network collection, persistence scan, integrity verification, cross‑domain correlation, YARA scan, evidence scoring, and outputs JSON, text, CSV and a tar.gz bundle.

IOC Live Monitoring

sudo ./linir watch --iocs ./iocs.txt

Three‑layer monitoring captures connections:

Layer 1 – Linux conntrack netlink or macOS BPF event‑driven (zero loss).

Layer 2 – polling /proc/net/nf_conntrack (RST connections retained ~10 s).

Layer 3 – fallback polling of /proc/net/tcp (generic).

When an IOC match occurs the tool automatically collects process context, binary hash, persistence links and YARA results, producing a scored event.

Web Dashboard

sudo ./linir gui

An interactive dark‑theme UI provides one‑click collection, risk‑score visualization, searchable tables for processes, network and persistence, real‑time IOC monitoring via Server‑Sent Events, and YARA scanning. All assets are embedded with go:embed, so no external files are required.

Scoring System

LinIR uses a rule‑based weighted model (not machine learning). Scores are calculated as “low‑score single points + high‑score combos + confidence separation”. Example rules: /tmp executable → +10.

Same file also has an established network connection, a persistence entry and a YARA hit → +10 + 10 + 10 + 20 + 10 = 60 (high severity).

Parent process apt-get halves the score (suppress mechanism).

Low host trust lowers confidence and records integrity_flags.

A clean system stays near 0; only genuine threats raise the score.

Known Limitations

PID Attribution for Short‑Lived Processes

When a process exits, its /proc entries disappear, so a connection observed after the process has terminated may lack a PID. LinIR mitigates this with:

Conntrack event capture (captures the socket while the process is still alive).

Fast inode‑to‑PID lookup (~10‑50 ms) targeting only the relevant inode.

Multiple retries before the socket FD disappears.

Pending queue to fill gaps on the next poll.

Fallback to the process name from /proc/<pid>/comm.

Extremely short‑lived processes (< 100 ms) may still be unresolved and are marked with pid_resolve_state: unresolved.

macOS Capability Gaps

BPF sees only packets traversing the NIC; loopback traffic requires extra handling.

UDP IOC monitoring was added later; the original focus was TCP SYN.

PID extraction via sysctl pcblist_n depends on struct offsets that can change across macOS releases.

Scoring Model Constraints

Cannot detect brand‑new attacks that match no rule.

Combination rules must be manually designed; no automatic pattern discovery.

The suppress mechanism relies on process‑name whitelists, so attackers masquerading as apt-get can evade reduction.

Not an EDR

LinIR is a one‑time “surgical knife” for responders: it does not auto‑remediate, report to the cloud, integrate with SIEMs, or auto‑update rules. It provides structured evidence; analysts make the final decision.

Design Rationale

Why Not eBPF?

Requires kernel ≥ 4.x (some features need 5.x).

Needs specific kernel configs ( CONFIG_BPF, CONFIG_BPF_SYSCALL).

Depends on BTF or manual version adaptation.

Violates the “single binary, zero dependency” goal.

Therefore LinIR uses /proc + netlink + BPF (macOS) to run on virtually all Linux 2.6+ and macOS 10.15+ systems, with optional eBPF enhancements planned for the future.

Why Go?

CGO_ENABLED=0

enables fully static builds.

Cross‑compilation to eight Linux and two macOS architectures with GOOS=xxx GOARCH=xxx go build.

No runtime dependencies (no libc, Python, JVM).

Go’s concurrency model fits simultaneous data‑source collection.

Resulting binary (~11 MB) can be scp’ed anywhere.

Why Prioritize Evidence Over Verdict?

LinIR reports concrete evidence rather than a binary “compromised” judgment. Example evidence for a high‑severity event:

PID 1234’s executable resides in /tmp (+10).

It holds an ESTABLISHED connection to 1.2.3.4:443 (+10).

Associated crontab persistence entry (+10).

YARA rule webshell_php matches the binary (+20).

Combination of temporary‑directory and YARA bonus (+10).

The total score of 60 yields severity: high and confidence: high . The analyst decides the final response.

Conclusion

LinIR v1.0.0 covers the most critical incident‑response stages: process, network, persistence, integrity, YARA and IOC monitoring. Known open issues include PID attribution races, macOS platform limits and scoring model tuning, but the tool offers a trustworthy forensic starting point in untrusted environments.

GitHub repository: https://github.com/dogadmin/LinIR

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GoeBPFrootkit detectionLinux incident responseforensic toolLinIR
Black & White Path
Written by

Black & White Path

We are the beacon of the cyber world, a stepping stone on the road to security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.