How to Trace Process Origin in Linux: Unmasking Perl Processes with Hidden Command Lines


2 views

When investigating a Linux system with performance issues, I encountered a suspicious Perl process consuming significant CPU resources. The standard top command only revealed "perl" as the process name, and pressing c to view the full command-line showed an unexpected path: /var/spool/mail - which is clearly a directory, not an executable.

In Linux, processes can manipulate how they appear in process listings through several techniques:

  • Modifying the argv[0] parameter
  • Using symbolic links or execve() tricks
  • Process name changing via prctl(PR_SET_NAME)

For Perl specifically, this can be done with:

# Perl script that masks its identity
$0 = "/var/spool/mail";  # Changes what appears in ps/top
# Rest of malicious code...

1. Using /proc Filesystem

The most reliable method is examining the process's entry in /proc:

# Find the PID first
pid=$(pgrep -f "perl")

# Then examine these critical files
cat /proc/$pid/cmdline | tr '\0' ' '  # Actual command line
cat /proc/$pid/environ | tr '\0' '\n' # Environment variables
ls -l /proc/$pid/exe                  # Symlink to actual binary
ls -l /proc/$pid/cwd                  # Current working directory

2. Advanced Process Monitoring Tools

For comprehensive analysis, use these tools:

  • strace -p PID - Trace system calls
  • lsof -p PID - List open files
  • auditd - System-wide process auditing

3. System-Wide Process Audit

To catch such processes proactively, implement process accounting:

# Install process accounting
sudo apt install acct

# Enable process auditing
sudo apt-get install auditd
sudo auditctl -a exit,always -F arch=b64 -S execve

Here's how to fully investigate our suspicious Perl process:

# Step 1: Find the PID
PID=$(pgrep -f "perl" | head -1)

# Step 2: Examine the process tree
pstree -p $PID

# Step 3: Check open files
sudo ls -l /proc/$PID/fd

# Step 4: Check memory maps
pmap -x $PID

# Step 5: Check network connections
ss -tulpn | grep $PID

Implement these security measures:

# Monitor process executions in real-time
sudo apt-get install inotify-tools
inotifywait -m /usr/bin /usr/local/bin /tmp -e create,modify 

# Set up eBPF tracing
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%s %s\n", comm, str(args->filename)); }'

When investigating a Linux system with performance issues, I discovered a Perl process consuming significant CPU resources. While top revealed the process name, pressing c to view the command-line showed only /var/spool/mail - clearly a directory path rather than an executable command. This raised two technical questions:

  1. How can a Perl process mask its true command-line arguments?
  2. What are the most reliable methods to trace a process's origin and startup method?

Processes can obscure their command-line arguments through several methods:

  • Direct argv[0] manipulation: The executing program can modify its own argv[0] pointer
  • Symbolic link execution: Running through symlinks can hide the true binary path
  • Process name changing: Using prctl(PR_SET_NAME) or similar system calls

Example of how a Perl script could modify its appearance:

#!/usr/bin/perl
$0 = "/var/spool/mail";  # Changes how the process appears in ps/top
while(1) {
    # CPU-intensive work here
}

1. Using /proc Filesystem

The most reliable method is examining the process through /proc:

# Find the PID first
pid=$(pgrep -f '/var/spool/mail')

# Examine the actual command-line
cat /proc/$pid/cmdline | tr '\0' ' '

# Check the executable symlink
ls -l /proc/$pid/exe

# View environment variables
cat /proc/$pid/environ | tr '\0' '\n'

2. System Call Tracing with strace

Attach to the running process to see its activity:

strace -p $pid -f -s 1000

Or trace child processes from the beginning:

strace -f -e execve perl /actual/script/path.pl

3. Process Ancestry with pstree

View the process hierarchy to identify parents:

pstree -p -s $pid

4. Checking Open Files

Identify files the process is using:

lsof -p $pid

5. Auditd for System-wide Monitoring

For comprehensive tracking, configure auditd:

# Monitor execve system calls
auditctl -a exit,always -F arch=b64 -S execve

# View logs
ausearch -sc execve -i

For future monitoring:

  • Implement process accounting (acct)
  • Use centralized logging for all process executions
  • Consider security monitoring tools like SELinux or AppArmor
  • Implement system-wide auditing with auditd

For Perl specifically, you might want to:

# Install Perl module to track execution
cpanm Devel::NYTProf

# Run script with profiling
perl -d:NYTProf suspicious_script.pl

Remember that sophisticated malware might employ additional hiding techniques, requiring even deeper forensic analysis with tools like gdb or memory inspection.