Home / Alt manpages / unhide.rb(8)

  • unhide.rb(8)
  • Admin command
  • linux

Check for Hidden Processes with unhide.rb

unhide.rb scans the system for hidden processes and writes diagnostics and hits to standard error. This guide keeps that output separate from progress messages and turns the exit status into a usable check. Allow about ten minutes for a manual run, longer on a busy or unusual host.

This guide uses the installed Debian package version 22-6. You need a shell and the unhide.rb package. The command has no documented options, and this workflow does not change any services, processes or persistent configuration.

Safety boundary

A hidden-process report is a signal to investigate, not proof of malware. Do not kill a process, delete files or reboot a host solely because this command reports a hit. Preserve the output first and follow your incident-handling procedure.

1. Confirm the installed command

Check which executable and package version will be used. These are ordinary, read-only commands and need no elevated privileges:

$ command -v unhide.rb
/usr/sbin/unhide.rb
$ dpkg-query -W -f='${Package} ${Version}\n' unhide.rb
unhide.rb 22-6

Your path or package version may differ. What matters is that the command resolves to the package you actually intend to inspect.

Checkpoint

If command -v prints nothing, stop here. Install or repair the package through your normal system change process rather than guessing another command name.

2. Run one scan and observe both streams

Run the command without arguments:

$ unhide.rb
Scanning for hidden processes...

The progress line goes to standard output. Error diagnostics and hidden-process information go to standard error, so a terminal shows both streams together even though they are separate. The scan can take longer than a quick command; do not interrupt it just because no further progress line appears immediately.

There is no undo step here. When the scan exits, it has not altered the system. To stop a long-running scan, press Ctrl-C, which interrupts the check and means you must not treat the result as a complete scan.

3. Save progress and findings separately

For a record you can inspect later, redirect each stream to its own file:

$ run_id=$(date +%Y%m%d-%H%M%S)
$ unhide.rb >/tmp/unhide-$run_id.stdout 2>/tmp/unhide-$run_id.stderr
$ status=$?
$ printf 'exit status: %s\n' "$status"
$ printf 'progress: /tmp/unhide-%s.stdout\n' "$run_id"
$ printf 'findings: /tmp/unhide-%s.stderr\n' "$run_id"

The shell variable stores the command's status before another command can overwrite it. The files under /tmp are temporary and may be swept up by normal system cleanup, so copy evidence to an approved, access-controlled incident location if it needs to be retained. Treat the stderr file as security-sensitive, since it may identify processes or expose host details.

Inspect the two files without changing them:

$ sed -n '1,80p' "/tmp/unhide-$run_id.stdout"
$ sed -n '1,160p' "/tmp/unhide-$run_id.stderr"
$ printf 'recorded status: %s\n' "$status"

With no hidden process detected, the command's normal exit status is 0. Status 2 means one or more hidden processes were detected; status 1 means something went wrong during scanning. The status is the machine-readable result, so do not decide success by scanning the output for a particular sentence.

4. Classify the result in a script

Use a case statement when another check, report or monitoring job needs a clear outcome:

#!/bin/sh
unhide.rb >/var/tmp/unhide.rb.stdout 2>/var/tmp/unhide.rb.stderr
status=$?

case "$status" in
    0)
        printf '%s\n' 'No hidden processes found'
        exit 0
        ;;
    1)
        printf '%s\n' 'unhide.rb could not complete its scan' >&2
        exit 1
        ;;
    2)
        printf '%s\n' 'Hidden process detected; inspect /var/tmp/unhide.rb.stderr' >&2
        exit 2
        ;;
    *)
        printf 'Unexpected unhide.rb status: %s\n' "$status" >&2
        exit 1
        ;;
esac

The wrapper deliberately keeps status 2 distinct from a scan failure. A monitoring system can alert on both, but the operator response differs: status 1 just needs a repeatable scan, while status 2 needs investigation of the reported process and the scan's evidence.

The example uses /var/tmp so its files normally survive a reboot, but it is still not a suitable evidence archive. Choose a directory with permissions and retention rules that match your environment, and check it exists and is writable by the running account before deploying the wrapper.

5. Investigate a non-zero result without making changes

For status 1, read both saved streams and check the account, host state and any local execution restrictions. Repeat the command manually once you have corrected the identified problem. Do not convert a failed scan into a clean result.

For status 2, preserve the stderr output, note the time and host, and compare the report with trusted process views and your deployment records. The command tells you it detected one or more hidden processes; it does not identify the owner, cause or remediation. Escalate according to your security process before stopping anything.

Run the check with the least privilege that produces a complete result. The manpage does not require sudo, so do not add it automatically. If your host policy requires elevated access for a complete scan, record that choice and run the command under the approved account: elevated privileges do not make an unexplained status 2 safe to ignore.

6. Keep the command's limits visible

unhide.rb accepts no options: there is no profile name, configuration file or output-format switch to pass it. Progress belongs on standard output; diagnostics and hits belong on standard error. That split helps automation, but it gives you no severity rating or remediation action.

The installed manpage describes this program as a Ruby port of unhide. Do not silently substitute another implementation: command names, tests, diagnostics and status handling can all differ. If you need to compare results with another tool, label each tool and retain its separate output.

Once the check is complete, remove temporary copies that are no longer needed:

$ rm -f "/tmp/unhide-$run_id.stdout" "/tmp/unhide-$run_id.stderr"

This removes only the two files created in step 3. If the output may matter to an investigation, do not run this cleanup until the approved copy has been verified.

Done means

  • Confirmed the build. unhide.rb resolves to the expected installed package and version.
  • Let the scan finish. You ran it with no invented options and did not cut it short.
  • Kept the streams apart. Standard output and standard error stayed separate when a record was needed.
  • Handled every status. 0, 1 and 2 are treated as distinct outcomes.
  • Investigated hits properly. A status 2 is preserved and investigated, not treated as automatic proof of an attack.
  • Changed nothing. No process, service or persistent configuration was touched by the check itself.