Logo Search packages:      
Sourcecode: unhide version File versions  Download package

unhide-linux26.c

/* Unhide yjesus@security-projects.com */

// Needed for unistd.h to declare getpgid() and others
#define _XOPEN_SOURCE 500

// Needed for sched.h to declare sched_getaffinity()
#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wait.h>
#include <sys/resource.h>
#include <errno.h>
#include <dirent.h>
#include <sched.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/syscall.h>


// we are looking only for real process not thread and only one by one
#define COMMAND "ps --no-header -p %i o pid"
// we ara looking for session ID one by one
#define SESSION "ps --no-header -s %i o sess"
// We are looking for group ID one by one
// but ps can't select by pgid
#define PGID "ps --no-header -eL o pgid"
// We are looking for all processes even threads
#define THREADS "ps --no-header -eL o lwp"
// for sysinfo scanning, fall back to old command, as --no-header seems to create
// an extra process
#define SYS_COMMAND "ps -eL o lwp"


// sysctl kernel.pid_max
int maxpid= 32768;

// For Threads sync
int tid ;

void *funcionThread (void *parametro) {

      tid = (pid_t) syscall (SYS_gettid);
      return(&tid) ;
};


void get_max_pid(int* newmaxpid) {
      char path[]= "/proc/sys/kernel/pid_max";
      pid_t tmppid = 0;
      FILE* fd= fopen(path,"r");
      if(!fd) {
            printf("[*] Error: cannot get current maximum PID: %s\n", strerror(errno));
            return;
      }


      if((fscanf(fd, "%d", &tmppid) != 1) || tmppid < 1) {
            printf("[*] cannot get current maximum PID: Error parsing %s format\n", path);
            return;
      } else {
            *newmaxpid = tmppid;
      }
      fclose(fd) ;
}


int checkps(int tmppid, int morechecks) {

      int ok = 0;
      char pids[30];

      char compare[100];
      char command[60];


      FILE *fich_tmp ;

// The compare string is the same for all test
      sprintf(compare,"%i\n",tmppid);

      sprintf(command,COMMAND,tmppid) ;

      fich_tmp=popen (command, "r") ;
      if (fich_tmp == NULL) {
            printf("Warning : popen failed while ps checking pid %d (memory, or something set errno: %s)\n", tmppid, strerror(errno));
            return(0);
      }

      while (!feof(fich_tmp) && ok == 0) {
            char* tmp_pids = pids;

            fgets(pids, 30, fich_tmp);
            pids[29] = 0;

            while( *tmp_pids == ' ' && tmp_pids <= pids+29) {
                  tmp_pids++;
            }

            if (strncmp(tmp_pids, compare, 30) == 0) {ok = 1;}

      }

      if (fich_tmp != NULL)
            pclose(fich_tmp);

      if (1 == ok) return(ok) ;      // pid is found, no need to go further

      FILE *fich_thread ;

      fich_thread=popen (THREADS, "r") ;
      if (fich_thread == NULL) {
            printf("Warning : popen failed while thread checking pid %d (memory, or something set errno: %s)\n", tmppid, strerror(errno));
            return(0);
      }

      while (!feof(fich_thread) && ok == 0) {
            char* tmp_pids = pids;

            fgets(pids, 30, fich_thread);
            pids[29] = 0;

            while( *tmp_pids == ' ' && tmp_pids <= pids+29) {
                  tmp_pids++;
            }

            if (strncmp(tmp_pids, compare, 30) == 0) {ok = 1;}


      }
      if (fich_thread != NULL)
            pclose(fich_thread);

      if (1 == ok) return(ok) ;      // thread is found, no need to go further

      if (morechecks == 1) {

            FILE *fich_session ;

            sprintf(command,SESSION,tmppid) ;

            fich_session=popen (command, "r") ;
            if (fich_session == NULL) {
                  printf("Warning : popen failed while session checking pid %d (memory, or something set errno: %s)\n", tmppid, strerror(errno));
                  return(0);
            }


            while (!feof(fich_session) && ok == 0) {
                  char* tmp_pids = pids;

                  fgets(pids, 30, fich_tmp);
                  pids[29] = 0;

                  while( *tmp_pids == ' ' && tmp_pids <= pids+29) {
                        tmp_pids++;
                  }

                  if (strncmp(tmp_pids, compare, 30) == 0) {ok = 1;}

            }

            pclose(fich_session);

            if (1 == ok) return(ok) ;      // session is found, no need to go further

            FILE *fich_pgid ;

            fich_pgid=popen (PGID, "r") ;
            if (fich_pgid == NULL) {
                  printf("Warning : popen failed while pgid checking pid %d (memory, or something set errno: %s)\n", tmppid, strerror(errno));
                  return(0);
            }

            while (!feof(fich_pgid) && ok == 0) {
                  char* tmp_pids = pids;

                  fgets(pids, 30, fich_pgid);
                  pids[29] = 0;

                  while( *tmp_pids == ' ' && tmp_pids <= pids+29) {
                        tmp_pids++;
                  }

                  if (strncmp(tmp_pids, compare, 30) == 0) {ok = 1;}

            }

            pclose(fich_pgid);

      }
      return ok;
}

void printbadpid (int tmppid) {

      int statuscmd ;
      char cmd[100] ;
      struct stat buffer;

      printf ("Found HIDDEN PID: %i\n", tmppid) ;

      sprintf(cmd,"/proc/%i/cmdline",tmppid);

      statuscmd = stat(cmd, &buffer);

      if (statuscmd == 0) {

            FILE *cmdfile ;
            char cmdcont[1000];

            cmdfile=fopen (cmd, "r") ;

            if (cmdfile != NULL) {

                  while (!feof (cmdfile)) {

                        fgets (cmdcont, 1000, cmdfile);
                        printf ("Command: %s\n\n", cmdcont);
                  }
                  fclose(cmdfile);
            }
      }
}


void checkproc() {

      int procpids ;
      int statusprocbefore, statusprocafter;
      struct stat buffer;

      printf ("[*]Searching for Hidden processes through /proc scanning\n\n") ;

      for ( procpids = 1; procpids <= maxpid; procpids = procpids +1 ) {

            char directory[100] ;


            sprintf(directory,"/proc/%d",procpids);

            statusprocbefore = stat(directory, &buffer) ;
            if (statusprocbefore != 0) {
                  continue;
            }

            if(checkps(procpids,0)) {
                  continue;
            }

            statusprocafter = stat(directory, &buffer) ;
            if (statusprocafter != 0) {
                  continue;
            }

            printbadpid(procpids);
      }
}

void checkgetpriority() {

      int syspids ;

      printf ("[*]Searching for Hidden processes through getpriority() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int which = PRIO_PROCESS;

            int ret;

            errno= 0 ;

            ret = getpriority(which, syspids);
            if ( errno != 0) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno=0;
            ret = getpriority(which, syspids);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);
      }
}

void checkgetpgid() {

      int syspids ;


      printf ("[*]Searching for Hidden processes through getpgid() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = getpgid(syspids);
            if ( errno != 0 ) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno=0;
            ret = getpgid(syspids);
            if ( errno != 0 ) {
                  continue;
            }

            printbadpid(syspids);
      }
}


void checkgetsid() {

      int syspids ;


      printf ("[*]Searching for Hidden processes through getsid() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = getsid(syspids);
            if ( errno != 0) {
                  continue;
            }
            if(checkps(syspids,0)) {
                  continue;
            }
            errno=0;
            ret = getsid(syspids);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);

      }
}


void checksched_getaffinity() {

      int syspids;
      cpu_set_t mask;

      printf ("[*]Searching for Hidden processes through sched_getaffinity() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = sched_getaffinity(syspids, sizeof(cpu_set_t), &mask);
            if (errno != 0) {
                  continue;
            }
            if (checkps(syspids,0)) {
                  continue;
            }
            errno=0;
            ret = sched_getaffinity(syspids, sizeof(cpu_set_t), &mask);
            if (errno != 0) {
                  continue;
            }

            printbadpid(syspids);
      }
}


void checksched_getparam() {

      int syspids;
      struct sched_param param;

      printf ("[*]Searching for Hidden processes through sched_getparam() scanning\n\n") ;


      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = sched_getparam(syspids, &param);
            if ( errno != 0) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno=0;
            ret = sched_getparam(syspids, &param);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);

      }
}

void checksched_getscheduler() {

      int syspids ;


      printf ("[*]Searching for Hidden processes through sched_getscheduler() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = sched_getscheduler(syspids);
            if ( errno != 0) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno=0;
            ret = sched_getscheduler(syspids);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);

      }
}

void checksched_rr_get_interval() {

      int syspids;
      struct timespec tp;

      printf ("[*]Searching for Hidden processes through sched_rr_get_interval() scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;

            ret = sched_rr_get_interval(syspids, &tp);
            if ( errno != 0) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno=0;
            ret = sched_rr_get_interval(syspids, &tp);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);
      }
}

void checkkill() {

      int syspids;

      printf ("[*]Searching for Hidden processes through kill(..,0) scanning\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids = syspids +1 ) {

            int ret;

            errno= 0 ;
            ret = kill(syspids, 0);
            if ( errno != 0) {
                  continue;
            }

            if(checkps(syspids,0)) {
                  continue;
            }

            errno= 0 ;
            ret = kill(syspids, 0);
            if ( errno != 0) {
                  continue;
            }

            printbadpid(syspids);
      }
}

void checkallnoprocps() {

      /* compare the various system calls against each other,
       * without invoking 'ps' or looking at /proc */

      int ret;
      int syspids;
      struct timespec tp;
      struct sched_param param;
      cpu_set_t mask;
      int found=0;
      int found_killbefore=0;
      int found_killafter=0;

      printf ("[*]Searching for Hidden processes through  comparison of results of system calls\n\n") ;

      for ( syspids = 1; syspids <= maxpid; syspids++ ) {

            found=0;
            found_killbefore=0;
            found_killafter=0;

            errno=0;
            ret = kill(syspids, 0);
            if (errno == 0) found_killbefore=1;

            errno= 0 ;
            ret = getpriority(PRIO_PROCESS, syspids);
            if (errno == 0) found++;

            errno= 0 ;
            ret = getpgid(syspids);
            if (errno == 0) found++;

            errno= 0 ;
            ret = getsid(syspids);
            if (errno == 0) found++;

            errno= 0 ;
            ret = sched_getaffinity(syspids, sizeof(cpu_set_t), &mask);
            if (ret == 0) found++;

            errno= 0 ;
            ret = sched_getparam(syspids, &param);
            if (errno == 0) found++;

            errno= 0 ;
            ret = sched_getscheduler(syspids);
            if (errno == 0) found++;

            errno=0;
            ret = sched_rr_get_interval(syspids, &tp);
            if (errno == 0) found++;

            errno=0;
            ret = kill(syspids, 0);
            if (errno == 0) found_killafter=1;


            /* these should all agree, except if a process went or came in the middle */
            if (found_killbefore == found_killafter) {
                  if ( ! ((found_killbefore == 0 && found == 0) ||
                                (found_killbefore == 1 && found == 7)) ) {
                        printf ("Found HIDDEN PID: %i\n", syspids) ;
                  }
            } /* else: unreliable */
            else {
                  printf("Warning : syscall comparison test skipped for PID %d", syspids);
            }
      }
}

void checksysinfo() {

      struct sysinfo info;
      int contador=0;
      int resultado_antes=0;
      int resultado_despues=0;
      int ocultos=0;
      char buffer[500];

      FILE *fich_proceso ;

      printf ("[*]Searching for Hidden processes through sysinfo() scanning\n\n") ;

      sysinfo(&info);
      resultado_antes=info.procs;

      fich_proceso=popen (SYS_COMMAND, "r") ;
      if (fich_proceso == NULL) {
            printf("popen failed while checking sysinfo (memory, or something set errno: %s)\n", strerror(errno));
            return;
      }

      buffer[499] = '\0';
      while (!feof(fich_proceso)) {

            fscanf( fich_proceso, "%499s", &buffer[0] );
            contador++;

      }

      pclose(fich_proceso);

      sysinfo(&info);
      resultado_despues=info.procs;

//    resultado=contador-5;
//    ocultos=info.procs-resultado;
      if (resultado_antes == resultado_despues) {  /* otherwise intermittent activity.. */

            ocultos=resultado_despues - contador + 3;

            if (ocultos != 0) {

                  printf("HIDDEN Processes Found: %i\n",abs(ocultos)) ;

            }
      }
      else {
            printf("Warning : sysinfo test skipped due to intermittent activity");
      }

}


void brute() {

      int i=0;
      int allpids[maxpid] ;
      int x;
      int y;
      int z;

      printf ("[*]Starting scanning using brute force against PIDS with fork()\n\n") ;

      // PID under 300 are reserved for kernel
      for(x=0; x < 300; x++) {

            allpids[x] = 0 ;
      }


      for(z=300; z < maxpid; z++) {

            allpids[z] = z ;
      }


      for (i=0; i < maxpid; i++) {
            int vpid;
            int status;

            errno= 0 ;

            if ((vpid = vfork()) == 0) {

//           allpids[getpid()] =  0;

             _exit(0);
            }

            if (0 == errno) {
                  allpids[vpid] =  0;
                  waitpid(vpid, &status, 0);
            }
      }

      /* processes that quit at this point in time create false positives */

      for(y=0; y < maxpid; y++) {

            if (allpids[y] != 0) {

                  if(!checkps(allpids[y],1) ) {

                        printbadpid(allpids[y]);

                  }
            }

      }


      printf ("[*]Starting scanning using brute force against PIDS with Threads\n\n") ;

      // PID under 300 are reserved for kernel
      for(x=0; x < 300; x++) {

            allpids[x] = 0 ;
      }


      for(z=300; z < maxpid; z++) {

            allpids[z] = z ;
      }


      for (i=0; i < maxpid ; i++) {
            void *status;

            errno= 0 ;

            pthread_t idHilo;

            int error;

            error = pthread_create (&idHilo, NULL, funcionThread, NULL);

            if (error != 0)
            {
                  perror ("Warning : Cannot create thread !");
                  exit (-1);
            }

            error = pthread_join(idHilo, &status);

            if (error != 0)
            {
                  perror ("Warning : Cannot join thread !");
                  exit (-1);
            }

            allpids[tid] =  0;

      }

      /* processes that quit at this point in time create false positives */

      for(y=0; y < maxpid; y++) {

            if (allpids[y] != 0) {

                  if(!checkps(allpids[y],1) ) {

                        printbadpid(allpids[y]);

                  }
            }

      }



}




int main (int argc, char *argv[]) {

      printf ("Unhide 20100201\n") ;
      printf ("http://www.security-projects.com/?Unhide\n\n\n") ;
      get_max_pid(&maxpid);

      if(argc != 2) {

            printf("usage: %s proc | sys | brute\n\n", argv[0]);
            exit (1);
      }

      setpriority(PRIO_PROCESS,0,-20);  /* reduce risk from intermittent processes - may fail, dont care */

      if (strcmp(argv[1], "proc") == 0) {checkproc();}

      else if (strcmp(argv[1], "sys") == 0) {
            checkkill();
            checkallnoprocps();
            checkgetpriority();
            checkgetpgid() ;
            checkgetsid();
            checksched_getaffinity();
            checksched_getparam();
            checksched_getscheduler();
            checksched_rr_get_interval();
            checksysinfo();

      }
      else if(strcmp(argv[1], "brute") == 0) {
            brute();
      }
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index