Modern Linux systems use systemd to manage services and resources. The resource management portion of systemd is called cgroups. Cgroups can be used to monitor and limit the resources that processes use, permissions, and Linux capabilities available to them.
A lesser known sub-component of cgroups is the freezer subsystem. The freezer is designed as a methodology to "pause" Linux processes. This concept is similar to using signals to pause and resume processes. However, the difference is that those signals can be caught and interpreted by software in any number of ways. When using freezer, the "pause" action cannot be caught or modified by the running software.
That is the key benefit here: this is a kernel-level freeze. Unlike sending a SIGSTOP
signal, which is visible to the process and can be intercepted or mismanaged, the cgroup freezer is a transparent mechanism. The suspended processes are simply stopped within the kernel and remain in a consistent, unkillable state until thawed, which is perfect for offensive cybersecurity operations. Furthermore, the freezer subsystem is available in the vast majority of kernels that implement systemd and it is available in cgroups v1 or v2.
For a red team or penetration testing exercise, why might freezer be useful? Simply put, any running processes that may interrupt, disrupt, or otherwise catch malicious behavior could be added to the freezer cgroup and effectively paused with little to no impact to the paused software itself. Take a more specific example: SSH'ing on to a Linux device and finding a running antivirus program; use the freezer cgroup to pause the antivirus program and conduct follow-on activities; when finished, "thaw" or resume the antivirus process and exit the device.
The snippets that follow are examples of commands that can be run on a Linux device to enable freezer, pause a process, then resume a process. All of these actions require root privileges.
Prerequisites:
mkdir /cgroup/freezer # create a directory used to control freezer
mount -t cgroup -o freezer freezer /cgroup/freezer # enable freezer on the new directory via a mount
mkdir /cgroup/freezer/frozen_group # create a group name for frozen processes
cat /proc/mounts | grep freezer # verify that freezer is active
Freeze a process:
# add the target process ID to the freezer cgroup
echo {PROCESS_ID} > /cgroup/freezer/frozen_group/tasks
cat /cgroup/freezer/frozen_group/freezer.state
# freeze all processes in the freezer cgroup
echo FROZEN > /cgroup/freezer/frozen_group/freezer.state
cat /cgroup/freezer/frozen_group/freezer.state
cat /proc/{PROCESS_ID}/status | grep -i state # verify the kernel state of the frozen process
Thaw a process:
# thaw/resume all processes in the freezer cgroup
echo THAWED > /cgroup/freezer/frozen_group/freezer.state
cat /cgroup/freezer/frozen_group/freezer.state
cat /proc/PID/status | grep -i state # verify the kernel state of the processes has resumed