Manual Host Triage.
No EDR. No XDR. Native Tools Only.
You're looking at a Windows or Linux host with nothing installed — no EDR, no XDR, no SIEM agent. A locked-down environment, an air-gapped box, a client engagement without agent-deployment access, or a cloud instance you can't put anything on. This is triage with what's already on the host: built-in cmd.exe and PowerShell cmdlets, wmic, reg, net, schtasks, wevtutil on Windows; bash, coreutils, procps, ss, journalctl on Linux. No Sysinternals, no third-party downloads, no non-default PowerShell modules.
Windows — Process Inspection
No EDR means no automatic parent-child chain, no command-line telemetry stream. Every one of these has to be pulled manually, and command-line visibility specifically requires the wmic or CIM variants below — the plain cmdlets don't show it.
Native Commands
tasklist /v // verbose: adds session name, session#, status, and user name per process wmic process list full // full property dump per process, including ParentProcessId and CommandLine — wmic is deprecated but still ships on Windows 10/11 and Server Get-Process // fast built-in process list — no CommandLine field by default, use the CIM query below for that Get-CimInstance Win32_Process | Select-Object Name,ProcessId,ParentProcessId,CommandLine // PowerShell-native equivalent of wmic process list full — command-line visibility without touching wmic
Windows — Persistence Checks
Autostart keys, scheduled tasks, and services are the three places persistence survives a reboot on a stock Windows build. Check all three — an actor only needs one to work.
Autostart Keys
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce" // the four standard autostart locations — HKLM entries run for every user, HKCU only for the current one
Scheduled Tasks & Services
schtasks /query /fo LIST /v // verbose list format — shows the actual task command/action per entry, not just names Get-ScheduledTask | Where-Object {$_.State -ne 'Disabled'} // PowerShell equivalent, easier to filter — pair with Get-ScheduledTaskInfo for last run time sc query state= all // the space after "state=" is required syntax — omitting it fails the command Get-Service | Where-Object {$_.Status -eq 'Running'} // cross-check against a known-good service baseline — an unfamiliar running service is worth a look
Windows — Network Connections
Owning-process visibility is the whole point here — a connection with no clear process behind it, or a process that has no business talking to the network, is the signal.
Native Commands
netstat -anob // -b resolves the owning executable per connection — requires an elevated (admin) prompt netstat -ano tasklist /svc // without admin rights, correlate the PID column from netstat -ano against tasklist /svc manually Get-NetTCPConnection | Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort,State,OwningProcess // PowerShell-native (NetTCPIP module, built in on Windows 8 / Server 2012 and later) — pipe OwningProcess into Get-Process for the name
Windows — Logon & User Activity
Who's logged on now, who has logged on recently, and what rights the current session holds.
Current Sessions & Accounts
quser query user // both show active interactive sessions — quser is an alias, output is identical net user // local account list — add a username to see group membership and account flags for one account net localgroup administrators // who actually has local admin right now — an unfamiliar name here is at least as urgent as the UID 0 check on the Linux side whoami /priv /groups // current session's privileges and group memberships in one call
Logon History From The Security Log
wevtutil qe Security /q:"*[System[(EventID=4624 or EventID=4625)]]" /c:50 /rd:true /f:text // 4624 = successful logon, 4625 = failed logon — /rd:true returns most recent first, /c:50 caps the count Requires admin rights to read the Security log, and requires "Audit Logon" to already be enabled. // on a host with default or minimal audit policy, this query can come back empty even after real logon activity — an empty result is not proof nothing happened, it's a coverage gap to note
Windows — File System & Log Artifacts
Hidden files, recently touched files, and pulling event log entries without opening the Event Viewer GUI.
File System
dir /a /s // /a lists all files regardless of hidden/system attribute, /s recurses subdirectories Get-ChildItem -Force // PowerShell equivalent — -Force surfaces hidden and system items Get-ChildItem skips by default forfiles /p C:\ /s /m *.* /d +0 /c "cmd /c echo @path @fdate" // forfiles /d uses relative-date matching: "+N" = modified on/after (today + N days), "-N" = modified on/before (today - N days). /d +0 surfaces files modified today; there's no single forfiles flag for a rolling "last N days" window
Event Logs, No GUI
wevtutil qe System /c:20 /rd:true /f:text wevtutil qe Application /c:20 /rd:true /f:text // same qe pattern as the logon query above — swap the log name and drop the /q filter to pull recent entries from any log wevtutil el // lists every available log name on the host, if you need one besides System/Application/Security
Correlate Across Tools, Not Within One
tasklist, netstat -ano, and wevtutil output together manually — that correlation is normally what the agent does for you.The LOLBIN Pattern To Watch For
rundll32, mshta, certutil, wmic itself) spawning a child process with no visible window, paired with an outbound connection in netstat -anob, is the pattern worth chasing — it shows up in a plain process and connection listing without any behavioral engine involved.Audit Policy Is A Real Blind Spot
Linux — Process Inspection
procps and /proc are always there, even on a minimal or container-adjacent install with nothing extra installed.
Native Commands
ps aux // BSD-style flags, no dash needed — full listing with user, %CPU, %MEM, and command ps -ef --forest // --forest draws the parent-child tree as ASCII art — the fastest way to spot an odd parent without a GUI cat /proc/<pid>/cmdline | tr '\0' ' ' cat /proc/<pid>/status // read a specific process directly from /proc when ps output looks truncated or suspicious — cmdline is NUL-separated, hence the tr
Linux — Persistence Checks
Cron, systemd units, rc.local, shell profile files, and SSH keys — the standard Linux persistence surface, all readable with core utilities.
Cron & Startup
crontab -l // per-user — run once per account, or loop: for u in $(cut -d: -f1 /etc/passwd); do crontab -u $u -l 2>/dev/null; done ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly // system-wide cron drop-in directories, separate from any user's crontab systemctl list-unit-files --type=service // shows every installed service unit and whether it's enabled — compare against a known-good baseline for the distro cat /etc/rc.local // legacy but still honored on many distros if present and executable — a common older persistence spot
Shell Profile & SSH
cat ~/.bashrc ~/.bash_profile /etc/profile ls /etc/profile.d/ // profile files run on every login shell — a single appended line is easy to miss without diffing against a baseline cat ~/.ssh/authorized_keys // an attacker-added key here is silent, persistent SSH access — check every user's home directory, not just root's
Linux — Network Connections
ss is the modern default; netstat is often absent on a minimal install unless net-tools was explicitly kept.
Native Commands
ss -tulpn // t=tcp, u=udp, l=listening, p=owning process, n=numeric — the process column needs root to populate fully netstat -tulpn // same flag meaning as ss — fall back to this only if netstat/net-tools happens to already be present lsof -i // lists open network files per process — useful when ss/netstat output needs a second source to confirm
Linux — Logon & User Activity
Who's on now, who's been on, who's failed to get on, and whether any account besides root has UID 0.
Native Commands
who w // who = who's logged in now; w adds what they're running and idle time last lastb // last = successful login history from /var/log/wtmp; lastb = failed attempts from /var/log/btmp, usually needs root awk -F: '$3 == 0 {print $1}' /etc/passwd // lists every account with UID 0 — should return exactly "root"; a second UID-0 account is a direct backdoor indicator
Linux — File System & Log Artifacts
Recently modified files, unexpected SUID binaries, dropped executables in world-writable directories, and the auth log itself.
File System
find / -xdev -mtime -1 -type f 2>/dev/null // -mtime -1 = modified within the last 1 day; -xdev keeps it from crossing into mounted filesystems and taking forever find / -xdev -perm -4000 -type f 2>/dev/null // -perm -4000 finds every SUID-bit binary on the host ls -la /tmp /dev/shm // both are world-writable by default and the two most common landing spots for a dropped executable
Logs
journalctl -xe journalctl --since "1 hour ago" // systemd-based distros — -xe adds explanatory context to recent entries, --since scopes by time /var/log/auth.log // Debian / Ubuntu — authentication events (sudo, ssh, login) /var/log/secure // RHEL / CentOS / Fedora — the equivalent authentication log
An Unfamiliar SUID Binary Is Priority One
passwd, sudo, ping, su, mount, a handful of others. Anything in the find / -perm -4000 output that isn't on that list, especially sitting in /tmp or a user's home directory, is worth investigating immediately — it's a common privilege-escalation persistence technique.ps Only Shows What's Running Right Now
ps aux unless it's actively executing at that moment. The persistence checks above have to run separately from the process checks — a clean process list says nothing about what's configured to run next boot or next login.A Second UID 0 Account Is Not Ambiguous
root should ever show UID 0 in /etc/passwd. A second entry with UID 0 is a near-certain sign of a planted backdoor account, not a misconfiguration worth debating — treat it as compromise confirmation and move to containment.