Rootkit checks are most useful before a suspicious Debian system becomes the only source of truth you can inspect. To install chkrootkit on Debian, use the Debian package for routine monitoring, then consider the upstream source build only when you specifically need the newest upstream checks and accept the manual update and download-trust trade-offs.
Chkrootkit is a local scanner, not a live antivirus engine or a guarantee that a compromised host is clean. It compares binaries, process views, network state, and log artifacts against known rootkit and backdoor patterns. A practical workflow is to install it, run a baseline scan while the system is healthy, configure repeat scans, and investigate changes with Debian package checks, logs, and offline scans when the result looks serious.
Install Chkrootkit on Debian
Choose a Chkrootkit Method on Debian
Debian gives you two realistic paths. The APT package is the safest default because it comes from Debian’s signed repositories, installs Debian’s helper files, and receives updates through normal package maintenance. The source build installs upstream chkrootkit outside APT, so it is better treated as an advanced method for users who need upstream 0.59 checks before they reach Debian stable.
| Method | Source or Channel | Update Behavior | Best For | Trade-offs |
|---|---|---|---|---|
| APT package | Debian main repository | Updates through APT with the rest of the system | Most Debian servers, desktops, and maintenance workflows | Stable Debian releases can lag behind the newest upstream checks |
| Source build | Upstream chkrootkit site and FTP tarball | Manual rebuild and replacement | Labs or administrators who need upstream 0.59 checks such as process-executed-from-memory and Bootkitty/XZ-related checks | FTP download, MD5-only checksum, no Debian package ownership, wrapper-managed command path, and no packaged scheduler integration |
Use only one method on a normal system. Installing both can make command paths confusing because the Debian package uses /usr/sbin/chkrootkit, while the source method creates a local wrapper at /usr/local/bin/chkrootkit.
Check Debian Repository Versions
Debian’s package version depends on the release. Current Debian package metadata lists these stable, oldstable, and Bullseye LTS packages:
| Debian Release | Repository Version | Practical Note |
|---|---|---|
| Debian 13 (Trixie) | 0.58b series | Newest stable Debian package; includes BPFDoor-era checks and newer option support than Bookworm/Bullseye |
| Debian 12 (Bookworm) | 0.57 series | Stable package with Debian’s configuration file, daily helper, cron file, and systemd timer files |
| Debian 11 (Bullseye) | 0.54 series | Older package; useful for baseline checks, but it lacks the newer upstream 0.58b and 0.59 additions |
The source build currently installs upstream 0.59. That release is useful when you need its newer checks, but the Debian package remains the better default when package trust, automatic updates, and predictable removal matter more than the newest signature set.
Install Chkrootkit with APT
Refresh APT metadata before installing the package:
sudo apt update
These commands use
sudofor package installation and root-level scans. If your account cannot use sudo yet, run the commands from a root shell or follow how to add a user to sudoers on Debian first.
Install the Debian package:
sudo apt install chkrootkit
Verify the installed version with sudo and the absolute package path. Debian installs the APT package command under /usr/sbin, and that directory may not be in a normal user’s non-login shell path.
sudo /usr/sbin/chkrootkit -V
Version output varies by Debian release:
chkrootkit version 0.58b
If you are checking paths or building scripts around the command, remember that chkrootkit prints its version to standard error and returns a nonzero status after -V. That behavior is normal for chkrootkit, but scripts using set -e need to capture it deliberately.
Inspect the Debian-owned files when you want to confirm what the package installed:
dpkg -L chkrootkit | grep -E '/usr/sbin/chkrootkit|/etc/chkrootkit|/etc/cron.daily/chkrootkit|chkrootkit\.(service|timer)'
On Debian 12 and Debian 13, relevant package files include the configuration directory, daily cron hook, systemd service/timer files, and /usr/sbin/chkrootkit. Debian 11 has an older package layout, so do not assume every newer configuration file exists on Bullseye.
Install Chkrootkit from Source
The source method installs upstream chkrootkit 0.59 under /usr/local. Use it when the newer checks matter enough to justify a manual lifecycle. The upstream download page provides the tarball over FTP and a matching MD5 file; MD5 can catch accidental corruption, but it is not a strong authenticity guarantee like a modern signed checksum.
Install build tools, wget, and the runtime commands used by upstream chkrootkit’s checks:
sudo apt install build-essential wget binutils net-tools procps
Create a temporary build directory, download the tarball and MD5 file, then verify the download:
build_dir=$(mktemp -d)
cd "$build_dir" || exit
wget ftp://ftp.chkrootkit.org/pub/seg/pac/chkrootkit.tar.gz
wget ftp://ftp.chkrootkit.org/pub/seg/pac/chkrootkit.md5
md5sum -c chkrootkit.md5
A matching tarball reports:
chkrootkit.tar.gz: OK
Extract and compile the source:
tar -xzf chkrootkit.tar.gz
cd chkrootkit-*/ || exit
make sense
Successful compilation ends with commands similar to these:
cc -o chkproc chkproc.c cc -o chkdirs chkdirs.c cc -o check_wtmpx check_wtmpx.c cc -static -o strings-static strings.c cc -o chkutmp chkutmp.c
Check the compiled version. The 2>&1 || true ending keeps the shell from treating chkrootkit’s version-status behavior as a failed command:
./chkrootkit -V 2>&1 || true
chkrootkit version 0.59
Install the compiled directory under /usr/local/share/chkrootkit and create a wrapper in /usr/local/bin. The wrapper is important because upstream chkrootkit expects its helper binaries in the current working directory. The guard prevents replacing an unrelated real file at /usr/local/bin/chkrootkit:
if sudo test -e /usr/local/bin/chkrootkit && ! sudo test -L /usr/local/bin/chkrootkit && ! sudo grep -q 'LinuxCapable source wrapper' /usr/local/bin/chkrootkit 2>/dev/null; then
printf '%s\n' "Stop: /usr/local/bin/chkrootkit exists and is not a managed symlink or wrapper."
else
sudo rm -rf /usr/local/share/chkrootkit
sudo mv "$PWD" /usr/local/share/chkrootkit
sudo rm -f /usr/local/bin/chkrootkit
sudo tee /usr/local/bin/chkrootkit >/dev/null <<'WRAPPER'
#!/bin/sh
# LinuxCapable source wrapper for upstream chkrootkit.
cd /usr/local/share/chkrootkit || exit 1
exec ./chkrootkit "$@"
WRAPPER
sudo chmod 755 /usr/local/bin/chkrootkit
fi
cd || exit
rm -rf "$build_dir"
Confirm the source-installed command from outside the build directory. If the previous command printed a Stop message, resolve that existing file before continuing.
/usr/local/bin/chkrootkit -V 2>&1 || true
chkrootkit version 0.59
Run Chkrootkit Scans on Debian
Run your first scan while the system is behaving normally. That baseline helps you recognize which messages are normal for your host before you are troubleshooting a real incident. Scans need root privileges because chkrootkit reads protected process, binary, and log locations.
Run a Full Chkrootkit Scan
Start with a full scan:
sudo chkrootkit
A clean system usually prints many routine checks. The exact list depends on installed commands and the Debian release:
ROOTDIR is `/' Checking `amd'... not found Checking `basename'... not infected Checking `chfn'... not infected Checking `chsh'... not infected Checking `cron'... not infected Checking `crontab'... not infected Checking `ifpromisc'... not infected Checking `login'... not infected Checking `ls'... not infected Checking `netstat'... not infected Checking `ps'... not infected Checking `sshd'... not infected
Read the result labels carefully:
| Result | Meaning | First Action |
|---|---|---|
not infected | The check did not match chkrootkit’s known suspicious pattern | No action unless other evidence points to compromise |
not found | The checked binary or file is not present on this system | Usually normal on minimal Debian installations |
INFECTED | The check matched a suspicious pattern | Do not panic; verify with package checks, logs, and offline inspection |
Warning | The check found an unusual condition or possible false positive | Investigate the named file, process, or test before making changes |
Run Quiet Mode for Daily Checks
Quiet mode suppresses routine clean output and prints only suspicious findings:
sudo chkrootkit -q
No output from quiet mode means chkrootkit did not find a suspicious match in that run. Any output deserves investigation, especially if a previous clean baseline did not show it.
List and Run Individual Chkrootkit Tests
List available tests before running a targeted check:
sudo chkrootkit -l
chkrootkit: tests: aliens asp bindshell lkm rexedcs sniffer w55808 wted scalper slapper z2 chkutmp OSX_RSPLUG amd basename biff chfn chsh cron crontab date du dirname echo egrep env find ...
Run one test by naming it after the command. For example, the lkm test checks for signs of Linux kernel module rootkits:
sudo chkrootkit lkm
The bindshell test is another common targeted check when you are investigating unexpected listening ports:
sudo chkrootkit bindshell
Skip Network Mounts or Specific Filesystems
Use -n to skip NFS-mounted directories:
sudo chkrootkit -n
Debian 13 and upstream 0.59 also support -T for a named filesystem type. Do not use this option with the Debian 11 or Debian 12 packaged command because those older packaged versions do not include it. A bare -T is incomplete syntax even on versions that support the option.
sudo chkrootkit -T nfs
sudo chkrootkit -T nfs4
This matters on servers with large network mounts because scanning remote trees can slow the run and create noisy results unrelated to the local Debian root filesystem.
Scan a Mounted System from Rescue Media
If the running system may already be compromised, boot from trusted rescue media and scan the mounted Debian filesystem instead of trusting binaries from the suspect host:
sudo chkrootkit -r /mnt
The -p option points chkrootkit at trusted external commands. Combine it with -r when rescue media stores known-good commands outside the mounted suspect filesystem:
sudo chkrootkit -r /mnt -p /usr/bin:/usr/sbin:/bin:/sbin
For a noisy or hard-to-read result, expert mode shows the strings and intermediate findings that caused chkrootkit to report a check:
sudo chkrootkit -x | more
Configure Automatic Chkrootkit Scans on Debian
Automatic scans are useful only when you know which scheduler owns them. Debian’s APT package includes Debian-specific helper files, while source builds do not. Avoid adding a second custom cron job until you have checked the package-provided schedule.
Configure the Debian APT Package Schedule
Debian 12 and Debian 13 package files include /etc/chkrootkit/chkrootkit.conf, /etc/cron.daily/chkrootkit, and systemd timer/service files. The helper reads RUN_DAILY from the configuration file:
sudo grep -E '^(RUN_DAILY|RUN_DAILY_OPTS|MAILTO|DIFF_MODE)=' /etc/chkrootkit/chkrootkit.conf
RUN_DAILY="true" RUN_DAILY_OPTS="" MAILTO="root"
Open the file when you need to change whether the daily helper runs, which options it passes, or where mail is sent:
sudo nano /etc/chkrootkit/chkrootkit.conf
On Debian 12 and Debian 13, check whether the packaged timer is present and scheduled:
systemctl list-unit-files 'chkrootkit*' --no-pager
systemctl list-timers 'chkrootkit*' --all --no-pager
If your Debian 11 system does not have /etc/chkrootkit/chkrootkit.conf or a chkrootkit.timer unit, use the package-provided /etc/cron.daily/chkrootkit file as the schedule indicator instead of creating a duplicate root crontab. Debian 11 ships an older package layout than Bookworm and Trixie.
Review recent packaged helper output through the systemd journal when the timer is active:
sudo journalctl -u chkrootkit.service -n 50 --no-pager
When cron owns the daily run, output may be mailed to root or written according to the package configuration. If you do not have local mail configured, run a manual quiet scan regularly enough that suspicious output does not sit unseen.
Create a Cron Job for Source Builds
Source installations do not install Debian’s helper files. Use a dedicated cron drop-in instead of root’s personal crontab so the schedule is easy to find and remove later. The command uses the local wrapper created during the source install.
printf '%s\n' \
'SHELL=/bin/sh' \
'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' \
'0 3 * * * root /usr/local/bin/chkrootkit -q >> /var/log/chkrootkit.log 2>&1' | sudo tee /etc/cron.d/chkrootkit-local > /dev/null
sudo chmod 644 /etc/cron.d/chkrootkit-local
Verify the saved cron file:
sudo cat /etc/cron.d/chkrootkit-local
SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 0 3 * * * root /usr/local/bin/chkrootkit -q >> /var/log/chkrootkit.log 2>&1
This cron entry appends only quiet-mode findings. If you want email alerts instead, configure local mail delivery first, then pipe the output to a mail command that you have tested on the same system.
Update Chkrootkit on Debian
Update the APT Package
The Debian package updates with normal APT maintenance. To refresh metadata and upgrade only chkrootkit when an update is available, use:
sudo apt update
sudo apt install --only-upgrade chkrootkit
For broader security maintenance, keep the whole Debian system patched with your normal update workflow or unattended upgrades on Debian.
Update a Source Build Manually
Use a helper script for source updates so version capture, checksum comparison, compilation, replacement, and cleanup stay repeatable. Run this script manually instead of scheduling it, because source updates can fail from upstream download issues, compiler errors, or changed source layout.
nano ~/update-chkrootkit-source.sh
Add the script:
#!/usr/bin/env bash
set -euo pipefail
install_dir="/usr/local/share/chkrootkit"
launcher="/usr/local/bin/chkrootkit"
tar_url="ftp://ftp.chkrootkit.org/pub/seg/pac/chkrootkit.tar.gz"
md5_url="ftp://ftp.chkrootkit.org/pub/seg/pac/chkrootkit.md5"
work_dir=$(mktemp -d)
force="${1:-}"
cleanup() {
rm -rf "$work_dir"
}
trap cleanup EXIT
case "$force" in
""|--force)
;;
*)
printf 'Usage: %s [--force]\n' "$0" >&2
exit 1
;;
esac
write_launcher() {
sudo rm -f "$launcher"
sudo tee "$launcher" >/dev/null <<'WRAPPER'
#!/bin/sh
# LinuxCapable source wrapper for upstream chkrootkit.
cd /usr/local/share/chkrootkit || exit 1
exec ./chkrootkit "$@"
WRAPPER
sudo chmod 755 "$launcher"
}
for cmd in wget tar make cc md5sum; do
if ! command -v "$cmd" >/dev/null 2>&1; then
printf 'Missing required command: %s\n' "$cmd" >&2
printf 'Install prerequisites with: sudo apt install build-essential wget binutils net-tools procps\n' >&2
exit 1
fi
done
if [ ! -x "$launcher" ]; then
printf 'Source-installed chkrootkit was not found at %s\n' "$launcher" >&2
exit 1
fi
if sudo test -e "$launcher" && ! sudo test -L "$launcher" && ! sudo grep -q 'LinuxCapable source wrapper' "$launcher" 2>/dev/null; then
printf 'Refusing to replace %s because it is not the source wrapper.\n' "$launcher" >&2
exit 1
fi
current=$("$launcher" -V 2>&1 || true)
cd "$work_dir"
wget -q "$tar_url" -O chkrootkit.tar.gz
wget -q "$md5_url" -O chkrootkit.md5
md5sum -c chkrootkit.md5
tar -xzf chkrootkit.tar.gz
cd chkrootkit-*/
latest=$(./chkrootkit -V 2>&1 || true)
printf 'Current installed version: %s\n' "$current"
printf 'Downloaded version: %s\n' "$latest"
if [ "$current" = "$latest" ] && [ "$force" != "--force" ]; then
printf 'No source update needed. Run with --force to rebuild the same version.\n'
exit 0
fi
read -r -p "Compile and replace the source install? [y/N] " answer
case "$answer" in
y|Y|yes|YES)
;;
*)
printf 'Update cancelled.\n'
exit 0
;;
esac
make sense
sudo rm -rf "$install_dir"
sudo mv "$PWD" "$install_dir"
write_launcher
cd "$HOME" || cd /
"$launcher" -V 2>&1 || true
Save the script, make it executable, and run it:
chmod +x ~/update-chkrootkit-source.sh
~/update-chkrootkit-source.sh
A no-change run keeps the existing install untouched. Use --force only when you intentionally want to rebuild the same upstream version:
chkrootkit.tar.gz: OK Current installed version: chkrootkit version 0.59 Downloaded version: chkrootkit version 0.59 No source update needed. Run with --force to rebuild the same version.
Troubleshoot Chkrootkit on Debian
Fix Command Not Found After APT Install
If chkrootkit -V returns command not found after an APT install, the package may still be installed correctly. Debian places the packaged command in /usr/sbin, which is not always in a normal user’s PATH.
dpkg -L chkrootkit | grep '/usr/sbin/chkrootkit'
sudo /usr/sbin/chkrootkit -V
If the first command shows /usr/sbin/chkrootkit and the sudo version check prints a version, the install is fine. Use sudo chkrootkit for scans when you have only the Debian package installed, or keep the absolute path when you are deliberately checking the package binary.
Investigate Chkrootkit False Positives
Chkrootkit can report false positives because it matches patterns rather than proving intent. Treat a suspicious result as a lead, not as final proof.
- bindshell findings: Honeypot or monitoring tools that intentionally bind unusual ports can resemble classic backdoor ports.
- sniffer findings: Network managers such as
systemd-networkd, NetworkManager, orwpa_supplicantcan appear in packet-sniffer checks on legitimate systems. - suckit or process findings: Short-lived processes can disappear between process-list comparisons and create suspicious-looking mismatches.
- suspicious dotfiles: Development artifacts such as
.packlist,.cvsignore, or similar hidden files can match older rootkit naming patterns.
Example suspicious output can look severe even when it needs confirmation:
Checking `bindshell'... INFECTED (PORTS: 31337) Checking `suckit'... Warning: possible process hiding
Install debsums when you need to compare package-managed files against Debian package checksums:
sudo apt install debsums
sudo debsums -c
No output from sudo debsums -c means package-managed files still match their recorded checksums. Modified package files appear by path and package name:
debsums: changed file /usr/bin/suspicious-binary (from package-name)
debsums does not validate files installed under /usr/local, local configuration files, deleted logs, or unowned attacker files. Use it as one evidence source alongside logs, package ownership checks, and offline inspection.
Respond to INFECTED Results
A single suspicious line can be a false positive. Multiple core binaries reporting INFECTED, hidden-process messages, or results that appear suddenly after a known intrusion attempt deserve a stronger response:
Checking `ls'... INFECTED Checking `netstat'... INFECTED Checking `ps'... INFECTED Checking `lkm'... You have 2 process hidden for readdir command
- Disconnect the host from untrusted networks or isolate it at the switch, hypervisor, or firewall layer.
- Preserve volatile evidence when possible, including recent logs, process listings, listening ports, and timestamps.
- Boot trusted rescue media and scan the mounted Debian filesystem with
chkrootkit -r /mnt. - Compare suspect binaries with Debian package checksums, package ownership, and known-good copies.
- Reinstall from trusted media when compromise is confirmed or when you cannot prove the host is trustworthy.
Do not “fix” a serious rootkit finding by only reinstalling one package on the running host. If a rootkit can hide processes or alter command output, the running system may also hide the evidence you are trying to inspect.
Fix Source Build Errors
If make sense fails because cc, make, or Linux header files are missing, reinstall the build prerequisites first:
sudo apt install build-essential linux-libc-dev wget
The linux-libc-dev package provides userspace Linux headers such as linux/sched.h. Do not reach for linux-headers-$(uname -r) first unless you are building kernel modules; chkrootkit’s userspace build normally needs the libc development headers, not the running kernel’s module headers.
If the upstream FTP download fails, use the Debian APT package until the upstream server is reachable again. Avoid replacing the official source URL with a random mirror unless you can verify that mirror and its checksum source.
Remove Chkrootkit from Debian
Remove the APT Package
Purge the Debian package when you want to remove its package-owned configuration and scheduler files:
sudo apt purge chkrootkit
Preview orphaned dependencies before removing them:
sudo apt autoremove --dry-run
If the dry run lists only packages you no longer need, run the real cleanup:
sudo apt autoremove
Confirm the packaged command is gone:
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' chkrootkit 2>/dev/null || true
Remove a Source Build
Remove the source-installed directory, local wrapper, cron drop-in, and update helper:
sudo rm -rf /usr/local/share/chkrootkit
sudo rm -f /usr/local/bin/chkrootkit
sudo rm -f /etc/cron.d/chkrootkit-local
rm -f ~/update-chkrootkit-source.sh
Verify the source wrapper no longer exists:
test ! -e /usr/local/bin/chkrootkit && printf '%s\n' "source wrapper removed"
source wrapper removed
If the APT package is still installed, sudo chkrootkit may continue to work through /usr/sbin/chkrootkit. Remove the APT package separately if you used both methods during testing.
Complementary Security Tools for Debian
Chkrootkit works best as one layer in a Debian security workflow. Pair it with tools that answer questions chkrootkit does not cover:
If you are comparing chkrootkit with rkhunter, treat them as complementary scanners rather than direct replacements. Chkrootkit focuses on local rootkit signatures, suspicious processes, hidden directories, and altered command behavior, while rkhunter uses its own property database and policy-style checks. Running more than one scanner can reduce blind spots, but a clean result from either tool still does not prove a system is safe after a serious compromise.
- Tripwire for file integrity monitoring can help you notice file changes after you establish a trusted baseline.
- Fail2ban for brute-force protection reduces repeated login attacks before they become a deeper incident.
- UFW or Firewalld helps keep exposed services intentional.
- SSH setup on Debian matters because remote access is often the first place you need logs, hardening, and lockout controls.
- Nmap on Debian can verify which ports are actually reachable from the network.
- Timeshift snapshots on Debian can support rollback on desktop-style systems, though confirmed compromise still usually requires a clean reinstall.
Conclusion
Chkrootkit is installed on Debian with a clear update path, scheduled scan owner, and investigation workflow. Keep the APT package for routine systems unless a specific upstream 0.59 check justifies manual maintenance, then compare suspicious results with Debian package checks, logs, and offline scans before trusting or rebuilding a host.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>