Malware can overwrite argv[] to mask its process name. This is done to hide from analysts.
Example
Here is a simple program which sleeps for two minutes before exiting. Notice that ps shows this process’s name is argv.
wildcat# cat argv.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
sleep(120);
return 0;
}
wildcat# gcc -o argv argv.c
wildcat# ./argv &
[1] 79927 <--- pid of argv
wildcat# ps
PID TTY TIME CMD
33595 pts/0 00:00:00 sudo
33597 pts/0 00:00:01 zsh
79927 pts/0 00:00:00 argv <---
79928 pts/0 00:00:00 ps
The following modification of argv.c overwrites argv[0] with “ps”, which may help it blend in with processes on the system:
wildcat# cat argv.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
memset(argv[0], '\0', strlen(argv[0]));
strcpy(argv[0], "ps");
sleep(120);
return 0;
}
wildcat# gcc -o argv argv.c
wildcat# ./argv &
[1] 80316 <--- pid of argv
wildcat# ps -80316
PID TTY STAT TIME COMMAND
80316 pts/0 SN 0:00 ps <--- not "argv"
Hunting
On systems with procfs, you may be able to detect this behavior. In this example, you can see that /proc/PID/cmdline differs from /proc/PID/comm and the “Name” line from /proc/PID/status. Comparing these values to each other against all running processes may unearth some of these processes.
wildcat# ./argv &
[1] 80400
wildcat# cat /proc/80400/cmdline
ps# wildcat# cat /proc/80400/status
Name: argv
...snip...
wildcat# cat /proc/80400/comm
argv
The following script can identify processes exhibiting this behavior:
#!/bin/sh
# Find processes that are potentially lying about their argv[] in an
# attempt to hide in 'ps' output
for process in $(find /proc/[0-9]*/ -maxdepth 0 -type d); do
pid=$(echo $process | cut -d / -f 3)
# skip if cmdline is missing
if [ ! -e ${process}cmdline ]; then
continue
fi
cmdline=$(tr '\0' '|' < ${process}cmdline)
# skip processes without command lines.
if [ "$cmdline" = "" ]; then
continue
fi
cmd=$(echo $cmdline |cut -d '|' -f 1)
status=$(grep -E "^Name:" ${process}status)
echo $cmdline | grep $(echo $status |awk '{print $2}') >/dev/null
if [ $? = 1 ]; then
echo "[+] This process is sketchy:"
echo " PID: $pid"
echo " command: $cmd"
echo " /proc/X/cmdline: $cmdline"
echo " /proc/X/status: $status"
echo
fi
done
Here is an example of this hunting script in action. It correctly identifies the argv program above. Notice the false positive detection for /sbin/init:
wildcat# ./argv &
[1] 80613
wildcat# chmod +x find-argv.sh.
wildcat# ./find-argv.sh
[+] This process is sketchy:
PID: 1
command: /sbin/init
/proc/X/cmdline: /sbin/init|splash|
/proc/X/status: Name: systemd
[+] This process is sketchy:
PID: 80613
command: ps
/proc/X/cmdline: ps|||||
/proc/X/status: Name: argv
Real-world Examples
Here are some examples of malware that leverage this technique.