"Fossies" - the Fresh Open Source Software Archive

Member "chkrootkit-0.55/chkproc.c" (8 Mar 2021, 10056 Bytes) of package /linux/misc/chkrootkit-0.55.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "chkproc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.54_vs_0.55.

    1 /*
    2   (C) Nelson Murilo - 2004/09/13
    3   Version 0.10
    4   C port from chkproc.pl code from Klaus Steding-Jessen <jessen@nic.br>
    5   and Cristine Hoepers <cristine@nic.br> +little output changes.
    6 
    7   2002/03/02 - Segmentation fault in ps for non ASCII user name, by RainbowHat
    8 
    9   2002/06/13 Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
   10   - corrected the program return value ;
   11   - added a verbose mode displaying information about the hidden process.
   12 
   13   2002/08/08 - Value of MAX_PROCESSES was increased to 99999 (new versions
   14     of FreeBSD, HP-UX and others), reported by Morohoshi Akihiko, Paul
   15     and others.
   16 
   17   2002/09/03 - Eliminate (?) false-positives. Original idea from Aaron Sherman.
   18 
   19   2002/11/15 - Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
   20   - ported to SunOS.
   21 
   22   2003/01/19 - Another Adore based lkm test. Original idea from Junichi Murakami
   23 
   24   2003/02/02 - More little fixes - Nelson Murilo
   25 
   26   2003/02/23 - Use of kill to eliminate false-positives abandonated, It is
   27   preferable false-positives that false-negatives. Uncomment kill() functions
   28   if you like  it.
   29 
   30   2003/06/07 - Fix for NPTL threading mechanisms - patch by Mike Griego
   31 
   32   2003/09/01 - Fix for ps mode detect, patch by Bill Dupree and others
   33 
   34   2004/04/03 - More fix for linux's threads - Nelson Murilo
   35 
   36   2004/09/13 - More and more fix for linux's threads - Nelson Murilo
   37 
   38   2005/02/23 - More and more and more fix for linux's threads - Nelson Murilo
   39 
   40   2005/10/28 - Bug fix for FreeBSD: chkproc was sending a SIGXFSZ (kill -25)
   41                to init, causing a reboot.  Patch by Nelson Murilo.
   42                Thanks to Luiz E. R. Cordeiro.
   43 
   44   2005/11/15 - Add check for Enye LKM - Nelson Murilo
   45 
   46   2005/11/25 - Fix for long lines in PS output - patch by Lantz Moore
   47 
   48   2006/01/05 - Add getpriority to identify LKMs, ideas from Yjesus(unhide) and
   49                Slider/Flimbo (skdet)
   50 
   51   2006/01/11 - Fix signal 25 on parisc linux and return of kill() -
   52                Thanks to Lantz Moore
   53 
   54   2014/07/16 -  MAX_PROCESSES now is 999999 - 
   55         Thanks to Nico Koenrades
   56 
   57   2017/04/13 -  MAX_PROCESSES now is 4194384 if linux64 
   58         Thanks to DS Store
   59 */
   60 
   61 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__sun)
   62 int main (){ return 0; }
   63 #else
   64 #include <stdio.h>
   65 #include <string.h>
   66 #include <errno.h>
   67 #include <sys/types.h>
   68 #include <dirent.h>
   69 #include <ctype.h>
   70 #include <stdlib.h>
   71 #include <unistd.h>
   72 #include <signal.h>
   73 #include <sys/stat.h>
   74 #if defined(__sun)
   75 #include <procfs.h>
   76 #include <fcntl.h>
   77 #endif
   78 #include <sys/resource.h>
   79 
   80 #define PS_SUN 0
   81 #define PS_LOL 1
   82 #define PS_COM 2
   83 #define PS_LNX 3
   84 #define PS_MAX 3
   85 #define ENYELKM "/proc/12345"
   86 // #define ENYELKM "/tmp/12345"
   87 
   88 #if defined(__sun)
   89 #define FIRST_PROCESS 0
   90 #else
   91 #define FIRST_PROCESS 1
   92 #endif
   93 #define MAX_PROCESSES 999999 
   94 #if (defined (__x86_64) > 0  || defined (__amd64) > 0) 
   95 #undef MAX_PROCESSES
   96 #define MAX_PROCESSES 4194304
   97 #endif
   98 #define MAX_BUF 1024
   99 
  100 #if !defined (SIGXFSZ)
  101 #define SIGXFSZ 25
  102 #endif
  103 
  104 static char *ps_cmds[] = {
  105         "ps -edf",
  106         "ps auxw",
  107         "ps mauxw 2>&1 ",
  108             "ps auxw -T|tr -s ' '|cut -d' ' -f2-",
  109           };
  110 
  111 int psproc [MAX_PROCESSES+1];
  112 int dirproc[MAX_PROCESSES+1];
  113 #if defined(__linux__)
  114 int isathread[MAX_PROCESSES+1];
  115 #endif
  116 
  117 /*
  118  * read at most the first (size-1) chars into s and terminate with a '\0'.
  119  * stops reading after a newline or EOF.  if a newline is read, it will be
  120  * the last char in the string.  if no newline is found in the first
  121  * (size-1) chars, then keep reading and discarding chars until a newline
  122  * is found or EOF.
  123  */
  124 char *readline(char *s, int size, FILE *stream)
  125 {
  126   char *rv = fgets(s, size, stream);
  127 
  128   if (strlen(s) == (size-1) && s[size-1] != '\n')
  129   {
  130     char buf[MAX_BUF];
  131     fgets(buf, MAX_BUF, stream);
  132     while (strlen(buf) == (MAX_BUF-1) && buf[MAX_BUF-1] != '\n')
  133     {
  134       fgets(buf, MAX_BUF, stream);
  135     }
  136   }
  137 
  138   return rv;
  139 }
  140 
  141 int main(int argc, char **argv)
  142 {
  143    char buf[MAX_BUF], *p, path[MAX_BUF];
  144    char *pscmd = (char *)0;
  145    FILE *ps;
  146    DIR *proc = opendir("/proc");
  147    struct dirent *dir;
  148    struct stat sb;
  149    int i, j, retps, retdir, pv, verbose;
  150    long ret = 0L;
  151    char * tmp_d_name;
  152 #if defined(__linux__)
  153    int maybeathread;
  154 #endif
  155 #if defined(__sun)
  156    psinfo_t psbuf;
  157 #endif
  158 
  159    pv = verbose = 0;
  160 
  161    if (!proc)
  162    {
  163       perror("proc");
  164       exit (1);
  165    }
  166    for (i = 1; i < argc; i++)
  167    {
  168       if (!memcmp(argv[i], "-v", 2))
  169     verbose++;
  170       else if (!memcmp(argv[i], "-?", 2))
  171       {
  172     printf("Usage: %s [-v] [-v] -p <num>\n", argv[0]);
  173     return 0;
  174       }
  175 #if defined(__linux__)
  176       else if (!memcmp(argv[i], "-p", 2))
  177       {
  178          if (i+1 < argc)
  179             pv = atoi(argv[++i]);
  180          else
  181          {
  182         printf("Usage: %s [-v] [-v] [-p procps version]\n", argv[0]);
  183         return 0;
  184          }
  185       }
  186 #endif
  187    }
  188 #if defined(__sun)
  189    pscmd = ps_cmds[PS_SUN];
  190 #elif !defined (__linux__)
  191    pscmd = ps_cmds[PS_COM];
  192 #endif
  193 #if defined(__linux__)
  194    if (pv < 1 || pv > PS_MAX)
  195       pv = 1;
  196    pscmd = ps_cmds[pv];
  197 /*  printf("pv = %d\n\r", pv); /* -- DEBUG */
  198 #endif
  199 
  200 /* printf("pscmd = %s\n\r", pscmd); /* -- DEBUG */
  201    if (!(ps = popen(pscmd, "r")))
  202    {
  203        perror("ps");
  204        exit(errno);
  205    }
  206 
  207    *buf = 0;
  208    readline(buf, MAX_BUF, ps); /* Skip header */
  209 #if defined(__sun)
  210    if (!isspace(*buf))
  211 #else
  212    if (!isalpha(*buf))
  213 #endif
  214    {
  215      readline(buf, MAX_BUF, ps); /* Skip header */
  216      if (!isalpha(*buf) && pv != PS_LNX)
  217      {
  218     if (pv != PS_LOL)
  219        execlp(argv[0], argv[0], "-p 1", NULL);
  220         fprintf(stderr, "OooPS!\n");
  221         exit(2);
  222      }
  223    }
  224    if (!memcmp(buf, "ps:", 3) && (pv != PS_LOL))
  225       execlp(argv[0], argv[0], "-p 1", NULL);
  226 
  227    for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++) { /* Init matrix */
  228      psproc[i] = dirproc[i] = 0;
  229 #if defined(__linux__)
  230      isathread[i] = 0;
  231 #endif
  232    }
  233 
  234    while (readline(buf, MAX_BUF, ps))
  235    {
  236       p = buf;
  237 #if defined(__sun)
  238       while (isspace(*p)) /* Skip spaces */
  239           p++;
  240 #endif
  241       while (!isspace(*p)) /* Skip User */
  242           p++;
  243       while (isspace(*p)) /* Skip spaces */
  244           p++;
  245 /*  printf(">>PS %s<<\n", p);  /* -- DEBUG */
  246       ret = atol(p);
  247       if ( ret < 0 || ret > MAX_PROCESSES )
  248       {
  249          fprintf (stderr, " OooPS, not expected %ld value\n", ret);
  250          exit (2);
  251       }
  252       psproc[ret] = 1;
  253    }
  254    pclose(ps);
  255 
  256    while ((dir = readdir(proc)))
  257    {
  258 #if defined(__linux__)
  259       maybeathread = 0;
  260 #endif
  261       tmp_d_name = dir->d_name;
  262       if (!strcmp(tmp_d_name, ".") || !strcmp(tmp_d_name, ".."))
  263          continue;
  264 #if defined(__linux__)
  265       if (*tmp_d_name == '.') { /* here we catch the new NTPL threads in linux.  They are listed in /proc as PIDs with a period prepended */
  266          tmp_d_name++;
  267          maybeathread = 1;
  268       }
  269 #endif
  270       if(!isdigit(*tmp_d_name))
  271          continue;
  272 #if defined(__linux__)
  273       else if (maybeathread) {
  274          isathread[atol(tmp_d_name)] = 1; /* mark it as a linux NTPL thread if it's in the form of "\.[0-9]*" */
  275          if (verbose)
  276             printf("%ld is a Linux Thread, marking as such...\n", atol(tmp_d_name));
  277       }
  278 #endif
  279 
  280 /*      printf("%s\n", tmp_d_name); /* -- DEBUG */
  281       dirproc[atol(tmp_d_name)] = 1;
  282    }
  283    closedir(proc);
  284 
  285    /* Brute force */
  286    strcpy(buf, "/proc/");
  287    retps = retdir = 0;
  288    for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++)
  289    {
  290       // snprintf(&buf[6], 6, "%d", i);
  291        snprintf(&buf[6], 8, "%d", i);
  292       if (!chdir(buf))
  293       {
  294          if (!dirproc[i] && !psproc[i])
  295          {
  296 #if defined(__linux__)
  297             if (!isathread[i]) {
  298 #endif
  299             retdir++;
  300             if (verbose)
  301            printf ("PID %5d(%s): not in readdir output\n", i, buf);
  302 #if defined(__linux__)
  303             }
  304 #endif
  305          }
  306          if (!psproc[i] ) /* && !kill(i, 0)) */
  307          {
  308 #if defined(__linux__)
  309             if(!isathread[i]) {
  310 #endif
  311             retps++;
  312             if (verbose)
  313            printf ("PID %5d: not in ps output\n", i);
  314 #if defined(__linux__)
  315             }
  316 #endif
  317      }
  318 #if defined(__linux__)
  319          if(!isathread[i]) {
  320 #endif
  321 /*   if ((!dirproc[i] || !psproc[i]) && !kill(i, 0) && (verbose > 1)) */
  322      if ((!dirproc[i] || !psproc[i]) && (verbose > 1))
  323      {
  324 #if defined(__linux__)
  325         j = readlink ("./cwd", path, sizeof(path));
  326         path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
  327         printf ("CWD %5d: %s\n", i, path);
  328         j = readlink ("./exe", path, sizeof(path));
  329         path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
  330         printf ("EXE %5d: %s\n", i, path);
  331 #elif defined(__FreeBSD__)
  332         j = readlink ("./file", path, sizeof(path));
  333         path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
  334         printf ("FILE %5d: %s\n", i, path);
  335 #elif defined(__sun)
  336         if ((j = open("./psinfo", O_RDONLY)) != -1)
  337             {
  338                if (read(j, &psbuf, sizeof(psbuf)) == sizeof(psbuf))
  339                   printf ("PSINFO %5d: %s\n", i, psbuf.pr_psargs);
  340                else
  341                   printf ("PSINFO %5d: unknown\n", i);
  342                close(j);
  343             }
  344             else
  345                printf ("PSINFO %5d: unknown\n", i);
  346 #endif
  347          }
  348 #if defined(__linux__)
  349          }
  350 #endif
  351       }
  352 #ifndef __FreeBSD__
  353       else
  354       {
  355          errno = 0;
  356          getpriority(PRIO_PROCESS, i);
  357          if (!errno)
  358          {
  359             retdir++;
  360             if (verbose)
  361            printf ("PID %5d(%s): not in getpriority readdir output\n", i, buf);
  362      }
  363       }
  364 #endif
  365    }
  366    if (retdir)
  367       printf("You have % 5d process hidden for readdir command\n", retdir);
  368    if (retps)
  369       printf("You have % 5d process hidden for ps command\n", retps);
  370 #if defined(__linux__)
  371    kill(1, 100); /*  Check for SIGINVISIBLE Adore signal */
  372    if (kill (1, SIGXFSZ) < 0  && errno == 3)
  373    {
  374       printf("SIGINVISIBLE Adore found\n");
  375       retdir+= errno;
  376    }
  377    /* Check for Enye LKM */
  378    if (stat(ENYELKM, &sb) && kill (12345, 58) >= 0)
  379    {
  380       printf("Enye LKM found\n");
  381       retdir+= errno;
  382    }
  383 #endif
  384    return (retdir+retps);
  385 }
  386 #endif