Skip to content

ExecutionNetworkAnti-forensics

/proc Live Artifacts: Processes, Sockets and Deleted Files

The /proc pseudo-filesystem on a live Linux host: process command lines, environments, open files, memory maps, sockets and deleted binaries.

Location
/proc/<pid>/
Proves
What is running right now, from which binary, with which arguments, files and network connections
Timestamps
No file timestamps of value; process start time in clock ticks since boot (/proc/<pid>/stat field 22)
Access
root to see every process's exe, environ, fd and maps; other users see only their own
Retention
Volatile: gone at process exit or reboot
Collection
UAC, Velociraptor, cp, AVML

What it is

/proc is a pseudo-filesystem generated by the kernel on demand. Nothing in it is stored on disk: every read asks the kernel for the current state of a process, a socket table or a kernel subsystem. On a live system it is the fastest way to see what is running, where each process came from and what it is talking to, and it survives some anti-forensic tricks that defeat disk analysis, such as a binary deleted after launch.

Because it is live state, /proc sits near the top of the order of volatility: collect it before anything that changes the system, and ideally alongside a memory image.

Where it lives

PathContent
/proc/<pid>/exeSymlink to the executable; readable (and copyable) even if the file was deleted
/proc/<pid>/cmdlineArguments, NUL-separated
/proc/<pid>/environInitial environment, NUL-separated (root or same user)
/proc/<pid>/cwd, /proc/<pid>/rootCurrent working directory and root directory (reveals chroot or container root)
/proc/<pid>/fd/One symlink per open file descriptor: files, socket:[inode], pipe:[inode], anon_inode:
/proc/<pid>/mapsMemory mappings with backing file path, flags (deleted) when the file is gone
/proc/<pid>/statusName, state, PPid, Uid/Gid (real, effective, saved, fs), capabilities
/proc/<pid>/statSingle-line process record; field 22 starttime
/proc/<pid>/commShort name (16 bytes max), writable by the process itself
/proc/net/tcp, tcp6, udp, udp6, unixSocket tables with hex addresses and socket inode numbers
/proc/modulesLoaded kernel modules (same data as lsmod)
/proc/mountsCurrent mounts of the reading process's mount namespace
/proc/sys/kernel/taintedKernel taint flags

Paths are identical across distributions. On systems mounted with hidepid= on /proc, non-root users cannot see other users' processes.

What it proves

  • Which processes exist now, their parent-child tree, user and group IDs, and arguments.
  • Which binary backs each process, even after deletion (exe -> /path (deleted)), and allows recovering that binary.
  • Fileless execution: exe pointing to /memfd:<name> (deleted) shows a program run from an anonymous memory file created with memfd_create.
  • Which files, sockets and pipes each process holds open; which remote addresses it is connected to (join /proc/net/* inode numbers with fd/ links).
  • Environment variables such as LD_PRELOAD, HISTFILE or proxy settings passed to a process.
  • Not proven: anything about processes that already exited. A kernel rootkit can also filter what /proc shows, so compare with memory analysis.

Key fields

FieldWhereMeaning
PPidstatusParent PID
Uid, GidstatusReal, effective, saved set and filesystem IDs
CapEffstatusEffective capability mask
starttimestat field 22Start time in clock ticks after boot
(deleted) suffixexe, maps, fd/* linksBacking file was unlinked
local_address, rem_address, st, uid, inode/proc/net/tcpHex IP:port pairs, TCP state (0A = LISTEN, 01 = ESTABLISHED), owner UID, socket inode

Timestamps

Files under /proc show the time the kernel created the inode for the reader, not the process start, so do not use ls -l times. Convert starttime instead: divide by the clock tick rate (getconf CLK_TCK, usually 100) and add it to the boot time (btime in /proc/stat, Unix seconds UTC).

pid=1234
st=$(awk '{print $22}' /proc/$pid/stat)          # safe unless comm contains spaces
btime=$(awk '/^btime/{print $2}' /proc/stat)
date -u -d @$(( btime + st / $(getconf CLK_TCK) ))

ps -o lstart= -p <pid> gives the same value in local time.

Retention

None. Entries vanish when the process exits, and all of /proc is rebuilt at boot. Capture before containment actions such as killing processes, restarting services or isolating the network (which drops connections).

Collection

  • UAC live-response artifacts record process listings, /proc/<pid> links, open files and /proc/modules; its live_response/process/deleted.yaml artifact copies the binary of any process whose executable shows as (deleted) (first 20 MB), plus deleted files those processes still hold open.
  • Velociraptor: Linux.Sys.Pslist, Linux.Sys.Maps, Linux.Network.Netstat and friends over a fleet.
  • Manual, from trusted binaries:
# recover a deleted or memfd binary before the process ends
cp /proc/1234/exe /cases/host01/pid1234.bin && sha256sum /cases/host01/pid1234.bin
tr '\0' ' ' < /proc/1234/cmdline; echo
tr '\0' '\n' < /proc/1234/environ
ls -l /proc/1234/fd /proc/1234/cwd
ls -l /proc/[0-9]*/exe 2>/dev/null | grep -E '\(deleted\)|memfd:'

Take a memory image (see LiME and AVML) too: /proc answers "what now", memory lets you re-ask later.

Parsing

ps -eo pid,ppid,user,lstart,args --forest, ss -tanp, ss -xp and lsof -nP read /proc for you. For a memory image, Volatility 3 reconstructs the same view offline with linux.pslist, linux.pstree, linux.psaux, linux.envars, linux.lsof, linux.proc.Maps and linux.sockstat.

Investigator tips

  • A process whose exe is (deleted) or memfd: is a priority finding: legitimate cases exist (package upgrades replacing a running binary) but check the package history first.
  • comm and argv[0] can be changed by the process; trust exe and the mapped files instead.
  • Processes with cwd in /tmp, /var/tmp or /dev/shm deserve a look.
  • Compare the PID list from /proc with ps output and with memory: a mismatch suggests userland hooking (ld.so.preload) or a kernel rootkit (kernel modules).
  • A different root link than / indicates a chroot or a container; map it to the container ID before drawing conclusions (containers).
  • Record the clock: live collection times are only meaningful with the host's time and timezone captured at the same moment.

See also