How to Install Chkrootkit on Debian 13, 12 and 11

Install Chkrootkit on Debian 13, 12 and 11 to scan for rootkits. Configure daily automated scans and interpret results to detect compromises.

UpdatedPublished AuthorJoshua JamesRead time11 minGuide typeDebian

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.

MethodSource or ChannelUpdate BehaviorBest ForTrade-offs
APT packageDebian main repositoryUpdates through APT with the rest of the systemMost Debian servers, desktops, and maintenance workflowsStable Debian releases can lag behind the newest upstream checks
Source buildUpstream chkrootkit site and FTP tarballManual rebuild and replacementLabs or administrators who need upstream 0.59 checks such as process-executed-from-memory and Bootkitty/XZ-related checksFTP 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 ReleaseRepository VersionPractical Note
Debian 13 (Trixie)0.58b seriesNewest stable Debian package; includes BPFDoor-era checks and newer option support than Bookworm/Bullseye
Debian 12 (Bookworm)0.57 seriesStable package with Debian’s configuration file, daily helper, cron file, and systemd timer files
Debian 11 (Bullseye)0.54 seriesOlder 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 sudo for 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:

ResultMeaningFirst Action
not infectedThe check did not match chkrootkit’s known suspicious patternNo action unless other evidence points to compromise
not foundThe checked binary or file is not present on this systemUsually normal on minimal Debian installations
INFECTEDThe check matched a suspicious patternDo not panic; verify with package checks, logs, and offline inspection
WarningThe check found an unusual condition or possible false positiveInvestigate 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, or wpa_supplicant can 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
  1. Disconnect the host from untrusted networks or isolate it at the switch, hypervisor, or firewall layer.
  2. Preserve volatile evidence when possible, including recent logs, process listings, listening ports, and timestamps.
  3. Boot trusted rescue media and scan the mounted Debian filesystem with chkrootkit -r /mnt.
  4. Compare suspect binaries with Debian package checksums, package ownership, and known-good copies.
  5. 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.

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.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: