Use unhide to Check Linux for Hidden Processes
unhide runs on the installed Linux build, compares its standard checks, and tells you whether it found a hidden or fake thread. It is a detector, not a cleanup tool: a hit needs investigation, not an automatic reboot, kill or package change.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide matches the Ubuntu package unhide 20220611-1ubuntu1, whose executable reports upstream version 20211016. Allow about fifteen minutes for a quick check, longer if you need to investigate a discrepancy. You need shell access, sudo access, and a working /proc filesystem.
Security boundary
The actual Linux checks require root on this installation. The version and path checks below are read-only and can run without elevation. Do not use the output as proof a machine is clean: a hidden process, a false positive, or a compromised host can all affect what you see.
1. Confirm which unhide you have
Start by checking the package and the command your shell will actually execute:
$ dpkg-query -W -f='${Package} ${Version}\n' unhide
unhide 20220611-1ubuntu1
$ command -v unhide
/usr/sbin/unhide
$ ls -l /usr/sbin/unhide
lrwxrwxrwx ... /usr/sbin/unhide -> unhide-linux
$ unhide -V
Unhide 20211016
The exact package path, link metadata and copyright lines can differ. On this machine, the unqualified command links to the Linux implementation, which matters because that build provides tests such as quick, reverse, brute and procfs. Do not assume an alias has the same test list until you check it.
Checkpoint
If command -v unhide points somewhere unexpected, stop and verify the package or container image before collecting forensic evidence.
2. Run the quick comparison
For a first pass, compare the process views used by proc, procfs and sys:
$ sudo unhide quick
$ status=$?
$ printf 'unhide exit status: %s\n' "$status"
unhide exit status: 0
The manual describes quick as roughly twenty times faster than the corresponding full checks, with a higher risk of false positives. Status zero means it completed without reporting a hidden or fake thread; status one means it found one, according to the installed manual. Preserve the complete terminal output if the result is unexpected.
Do not treat a zero status as a security verdict. The check compares what different interfaces expose at one point in time, and very short-lived processes can make views disagree even without a rootkit involved.
3. Add the reverse check when the result matters
The reverse test checks that threads reported by ps can also be found through procfs and system calls. Combine it with the quick test:
$ sudo unhide quick reverse
$ printf 'unhide exit status: %s\n' "$?"
unhide exit status: 0
Run this from a quiet maintenance window if you can; busy hosts create more moving targets. If the command returns one, save the output, the date, the kernel version and the process list for a separate investigation. Do not kill the named process on the spot: unhide is reporting an inconsistency, and the process may still be legitimate.
4. Run a standard, slower comparison
When you want the direct procfs and system-call comparisons instead of the quick aggregate, use:
$ sudo unhide sys proc
$ printf 'unhide exit status: %s\n' "$?"
unhide exit status: 0
proc compares /proc with /bin/ps; sys compares information from ps with system calls. Running both gives a more readable baseline than relying only on the faster aggregate, though it still does not establish the host is uncompromised.
5. Use deeper checks carefully
For a more thorough pass, the manual gives this combination:
$ sudo unhide -m -d sys procall brute reverse
- brute probes process IDs rather than just enumerating normal process views.
- procall combines the proc and procfs checks.
- -d double-checks the brute test to cut down false positives.
- -m enables extra checks for relevant procfs, procall,
checkopendirandcheckchdirpaths, and also implies verbose output.
This can take longer and produce more output. It stays read-only with respect to processes: the manual says the kill test does not actually kill a process. That does not make the command harmless in every operational sense, so avoid running it during a latency-sensitive incident unless you have accepted the extra load.
6. Interpret warnings on current Linux
The installed manual warns that the sysinfo test can report false positives on Linux kernels newer than 2.6.33. Scheduler optimisation, cgroups and systemd can all contribute, and PREEMPT-RT can amplify the problem. A report involving the system-count comparison needs corroboration from another test and from host logs.
Use verbose output when you need the warning messages:
$ sudo unhide -v sys proc
You can repeat -v. -H adds ending messages and tells you when no hidden process is found. -u makes stdout writes unbuffered, useful when another program is consuming the output. These options change presentation, not the underlying evidence.
7. Keep logging separate from the evidence directory
The Linux options include -f, which writes unhide-linux.log in the current directory. Check the directory before using it:
$ pwd
/path/to/forensic-work
$ test ! -e unhide-linux.log && echo 'log destination is unused'
log destination is unused
$ sudo unhide -f quick
Choose a dedicated, access-controlled directory and preserve the resulting log with the rest of your evidence. Do not run -f from a shared directory or blindly overwrite an existing log; if you need to discard a test log, follow your evidence-handling policy rather than deleting it as an afterthought.
8. Know what the aliases mean
unhide-posix accepts only proc or sys and targets generic Unix systems and older Linux releases; the manual marks the Linux-only options unavailable there. unhide_rb is the C backport of the Ruby-style check, a different implementation rather than another spelling of every Linux test. Prefer the installed unhide link, or call unhide-linux explicitly, when examining a Linux 2.6-or-newer host.
There is nothing to undo in the commands above: they inspect process views and optionally write a log. They do not unload modules, edit services, remove files or terminate processes. If you ran with -f, retain or handle only that log according to your evidence policy.
Done means
- Confirmed the build. Package version, executable path and implementation alias are all recorded.
- Ran the root-only check. It completed and you captured its exit status.
- Know the limits. Status zero is not proof the host is clean.
- Preserved unexpected hits. A status one result was saved for corroboration, not treated as grounds for an automatic process kill.
- Accounted for false positives. You know modern schedulers, cgroups and systemd can trigger them.
- Handled logs carefully. Any log went to a deliberate evidence directory without overwriting an existing file.