chkrootkit-0.46a004075500017500001750000000000001033044150400133045ustar00jessenjessenchkrootkit-0.46a/ifpromisc.c010044400017500001750000000211031032550146600155220ustar00jessenjessen/* ifpromisc - This is a simple subset of Fred N. van Kempen, 's ifconfig and iplink code. Show state of all ethernet interfaces xxx is PROMISC or xxx is not promisc Version: @(#)ifpromisc.c 0.8 2003/11/30 @(#)ifpromisc.c 0.7 2003/06/07 Last Changes: Better detection of promisc mode on newer Linux kernels Lantz Moore Fix for newer linux kernels, minor fixes Nelson Murilo, Ports for Solaris Andre Gustavo Port for OpenBSD Nelson Murilo, Author: Nelson Murilo, Copyright 1997-2003 (C) Pangeia Informatica This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #ifdef __linux__ #include #include #include #include #include #else #include #ifndef __OpenBSD__ #include #endif #endif #ifdef SOLARIS2 #include #endif #include #include #include #include #include #include #include struct interface { char name[IFNAMSIZ]; /* interface name */ short type; /* if type */ short flags; /* various flags */ #ifdef __linux__ int index; /* interface index */ #endif }; char *Release = "chkrootkit package", *Version = "@(#) ifpromisc 0.8 (2003/11/30)"; int skfd = -1; /* AF_INET or AF_PACKET raw socket desc. */ int q = 0; /* Quiet mode on or off */ struct packet_info { int index; int type; int proto; int inode; char *cmd; struct packet_info *next; }; #ifdef __linux__ /* * the contents of /proc/net/packet */ static struct packet_info *proc_net_packet = 0; /* * read the entries from /proc/net/packet */ static void read_proc_net_packet() { FILE *proc; char buf[80]; proc = fopen("/proc/net/packet", "r"); if (!proc) { if (errno != ENOENT) { perror("opening /proc/net/packet"); } return; } /* skip the header */ fgets(buf, 80, proc); while (fgets(buf, 80, proc)) { int type = 0; unsigned int proto = 0; int index = 0; unsigned int inode = 0; if (sscanf(buf, "%*p %*d %d %x %d %*d %*u %*u %u", &type, &proto, &index, &inode) == 4) { struct packet_info *pi; pi = (struct packet_info *)malloc(sizeof(struct packet_info)); pi->type = type; pi->proto = proto; pi->index = index; pi->inode = inode; pi->cmd = 0; pi->next = proc_net_packet; proc_net_packet = pi; } else { fprintf(stderr, "cannot grok /proc/net/packet: %s", buf); } } fclose(proc); } /* look up an entry from /proc/net/packet by inode */ static struct packet_info *find_packet_info(int inode) { struct packet_info *p; for (p = proc_net_packet; p; p = p->next) { if (p->inode == inode) { return p; } } return NULL; } /* walk a processes fd dir looking for sockets with inodes that match the * inodes from /proc/net/packet, when a match is found, the processes exe * is stored */ static void walk_process(char *process) { DIR *dir; struct dirent *ent; char path[1024]; if (snprintf(path, sizeof(path), "/proc/%s/fd", process) == -1) { fprintf(stderr, "giant process name! %s\n", process); return; } if ((dir = opendir(path)) == NULL) { perror(path); return; } while ((ent = readdir(dir))) { struct stat statbuf; struct packet_info *info; if (snprintf(path, sizeof(path), "/proc/%s/fd/%s", process, ent->d_name) == -1) { fprintf(stderr, "giant fd name /proc/%s/fd/%s\n", process, ent->d_name); continue; } if (stat(path, &statbuf) == -1) { perror(path); continue; } if (S_ISSOCK(statbuf.st_mode) && (info = find_packet_info(statbuf.st_ino))) { char link[1024]; memset(link, 0, sizeof(link)); /* no need to check rv since it has to be long enough, * otherwise, one of the ones above will have failed */ snprintf(path, sizeof(path), "/proc/%s/exe", process); readlink(path, link, sizeof(link) - 1); info->cmd = strdup(link); } } closedir(dir); } /* walk the proc file system looking for processes, call walk_proc on each * process */ static void walk_processes() { DIR *dir; struct dirent *ent; if ((dir = opendir("/proc")) == NULL) { perror("/proc"); return; } while ((ent = readdir(dir))) { /* we only care about dirs that look like processes */ if (strspn(ent->d_name, "0123456789") == strlen(ent->d_name)) { walk_process(ent->d_name); } } closedir(dir); } /* return 1 if index is a member of pcap_session_list, 0 otherwise. */ static int has_packet_socket(int index) { struct packet_info *p; for (p = proc_net_packet; p; p = p->next) { if (p->index == index) { return 1; } } return 0; } #endif /* __linux__ */ static void ife_print(struct interface *ptr) { #ifdef __linux__ int promisc = ptr->flags & IFF_PROMISC; int has_packet = has_packet_socket(ptr->index); if (promisc || has_packet) { printf("%s:", ptr->name); if (promisc) printf(" PROMISC"); if (has_packet) { struct packet_info *p; printf(" PF_PACKET("); p = proc_net_packet; if (p) { printf("%s", p->cmd); for (p = p->next; p; p = p->next) { if (p->index == ptr->index) { printf(", %s", p->cmd); } } } printf(")"); } printf("\n"); } else { if (!q) printf("%s: not promisc and no PF_PACKET sockets\n", ptr->name); } #else if (ptr->flags & IFF_PROMISC) printf("%s is %s", ptr->name, "PROMISC"); else { if (!q) printf("%s is %s", ptr->name, "not promisc"); } putchar('\n'); #endif } /* Fetch the inteface configuration from the kernel. */ static int if_fetch(char *ifname, struct interface *ife) { struct ifreq ifr; memset((char *) ife, 0, sizeof(struct interface)); strcpy(ife->name, ifname); strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-1); ife->flags = ifr.ifr_flags; #ifdef __linux__ /* store the device index */ if (ioctl(skfd, SIOCGIFINDEX, &ifr) < 0) return(-1); ife->index = ifr.ifr_ifindex; #endif return(0); } static void if_print() { char buff[1024]; struct interface ife; struct ifconf ifc; struct ifreq *ifr; int i; ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); return; } ifr = ifc.ifc_req; for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if (if_fetch(ifr->ifr_name, &ife) < 0) { #ifdef __linux__ fprintf(stderr, "%s: unknown interface.\n", ifr->ifr_name); #endif continue; } if (!memcmp(ifr->ifr_name, "lo", 2)) continue; ife_print(&ife); } } int main(int argc, char **argv) { if (argc == 2 && !memcmp(argv[1], "-q", 2)) q++; /* Create a channel to the NET kernel. */ if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) { perror("socket"); exit(-1); } #ifdef __linux__ read_proc_net_packet(); walk_processes(); #endif if_print(); (void) close(skfd); exit(0); } chkrootkit-0.46a/COPYRIGHT010044400017500001750000000024771032550143700146710ustar00jessenjessen# @(#)COPYRIGHT 1.2 (Pangeia Informatica) 2/21/97 Copyright 1996-2003 - Pangeia Informatica, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. chkrootkit-0.46a/chkdirs.c010044400017500001750000000154361032775122400151730ustar00jessenjessen/* Copyright (C) Hal Pomeranz and Deer Run Assoc, 2002/11/24 All rights reserved. Permission granted to freely redistribute and update as long as this Copyright notice is preserved. No warranty expressed or implied. $Id: chkdirs.c,v 1.3 2003/01/20 19:44:13 hal Exp $ Usage: chkdirs [-n] dir ... Examples: chkdirs / chkdirs -n /proc Recursively traverses one or more directories looking for discrepancies between the parent directory link count and the number of subdirectories (parent directory link count should always equal the number of subdirs plus two-- anything else indicates a "hidden" directory). "-n" option means check directory but don't recursively descend into subdirectories. Changelog : 2002/12/19 - Little port for *BSB and Solaris - Nelson Murilo 2003/01/09 - More fix for Solaris - Nelson Murilo 2003/01/14 - HP-UX patch - Gerard Breiner 2003/01/20 - NAME_MAX Fix by Hal Pomeranz 2003/09/01 - BSDI port by Nelson Murilo and Thomas Davidson 2005/22/05 - APPLE test for limits.h included by Aaron Harwood */ #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__sun) || defined (hpux) || defined (__bsdi__) || defined (bsdi) || defined (__APPLE__) #include #elif defined(__APPLE__) && defined(__MACH__) #include #endif #include #include #include #include #include #include #include #include #ifndef NAME_MAX #define NAME_MAX PATH_MAX #endif struct dirinfolist { char dil_name[NAME_MAX+1]; int dil_lc; struct dirinfolist *dil_next; }; void usage () { fprintf(stderr, "chkdirs [-n] dir ...\n"); exit(255); } char *make_pathname (char *path, char *dir, char **buffer) { int plen, pathname_len, bufsize, offs; plen = strlen(path); pathname_len = plen + strlen(dir) + 2; if (!(*buffer) || (sizeof(*buffer) < pathname_len)) { if (buffer) free((void *)*buffer); bufsize = (pathname_len > PATH_MAX) ? pathname_len : PATH_MAX; if (!(*buffer = (char *)malloc(bufsize))) { return((char *)NULL); } } if (dir[0] == '/') { /* "dir" is absolute pathname, don't prepend "path" */ offs = 0; } else { strcpy(*buffer, path); if ((*buffer)[plen-1] == '/') { /* "path" ends in "/", don't add extra */ offs = plen; } else { (*buffer)[plen] = '/'; offs = plen + 1; } } strcpy((*buffer)+offs, dir); return((*buffer)); } int check_dir (char *dir, char *path, int linkcount, int norecurse) { int diff = -1; int plen, buflen, numdirs; char *curpath, *fullpath; DIR *dirhandle; struct dirent *finfo; struct dirinfolist *dl, *dptr; struct stat statinfo; /* When called recursively, "path" will be the full path of the cwd, but when called from main() "path" is empty. We need the cwd path so we can chdir() back at the end of this routine, as well as when printing errors and other output. */ if (!path || !(plen = strlen(path))) { buflen = PATH_MAX; retry: if (!(curpath = (char *)malloc(buflen))) { fprintf(stderr, "malloc() failed: %s\n", strerror(errno)); return(-1); } if (!getcwd(curpath, buflen)) { if (errno == ERANGE) { free((void *)curpath); buflen = buflen * 2; goto retry; } else { fprintf(stderr, "getcwd() failed: %s\n", strerror(errno)); return(-1); } } } else { /* "path" is set, so just copy it into "curpath" */ if (!(curpath = (char *)malloc(plen+1))) { fprintf(stderr, "malloc() failed: %s\n", strerror(errno)); return(-1); } strcpy(curpath, path); } /* Now set "fullpath" to be the absolute path name of the directory we will be checking (prepend "curpath" if "dir" is not already an absolute pathname). */ fullpath = (char *)NULL; if (!make_pathname(curpath, dir, &fullpath)) { fprintf(stderr, "make_pathname() failed: %s\n", strerror(errno)); free((void *)curpath); return(-1); } if (chdir(dir)) { fprintf(stderr, "chdir(%s): %s\n", fullpath, strerror(errno)); free((void *)curpath); free((void *)fullpath); return(-1); } /* Again, "linkcount" (the link count of the current directory) is set only if check_dir() is called recursively. Otherwise, we need to stat the directory ourselves. */ if (!linkcount) { if (lstat(".", &statinfo)) { fprintf(stderr, "lstat(%s): %s\n", fullpath, strerror(errno)); goto abort; } linkcount = statinfo.st_nlink; } if (!(dirhandle = opendir("."))) { fprintf(stderr, "opendir(%s): %s\n", fullpath, strerror(errno)); goto abort; } numdirs = 0; dl = (struct dirinfolist *)NULL; while ((finfo = readdir(dirhandle))) { if (!strcmp(finfo->d_name, ".") || !strcmp(finfo->d_name, "..")) continue; if (lstat(finfo->d_name, &statinfo)) { fprintf(stderr, "lstat(%s/%s): %s\n", fullpath, finfo->d_name, strerror(errno)); closedir(dirhandle); goto abort; } if (S_ISDIR(statinfo.st_mode)) { numdirs++; if (norecurse) continue; /* just count subdirs if "-n" */ /* Otherwise, keep a list of all directories found that have link count > 2 (indicating directory contains subdirectories). We'll call check_dir() on each of these subdirectories in a moment... */ if (statinfo.st_nlink > 2) { dptr = dl; if (!(dl = (struct dirinfolist *)malloc(sizeof(struct dirinfolist)))) { fprintf(stderr, "malloc() failed: %s\n", strerror(errno)); norecurse = 1; while (dptr) { dl = dptr->dil_next; free((void *)dptr); dptr = dl; } continue; } strcpy(dl->dil_name, finfo->d_name); dl->dil_lc = statinfo.st_nlink; dl->dil_next = dptr; } } } closedir(dirhandle); /* Parent directory link count had better equal #subdirs+2... */ diff = linkcount - numdirs - 2; if (diff) printf("%d\t%s\n", diff, fullpath); /* Now check all subdirectories in turn... */ while (dl) { check_dir(dl->dil_name, fullpath, dl->dil_lc, norecurse); dptr = dl->dil_next; free((void *)dl); dl = dptr; } abort: if (chdir(curpath)) { fprintf(stderr, "Final chdir(%s) failed (%s) -- EXIT!\n", curpath, strerror(errno)); exit(255); } free((void *)fullpath); free((void *)curpath); return(diff); } int main (int argc, char **argv) { int norecurse = 0; int i, retval; char c; opterr = 0; while ((c = getopt(argc, argv, "n")) > 0) { switch (c) { case 'n': norecurse = 1; break; default: usage(); } } if (argc <= optind) usage(); for (i = optind; i < argc; i++) { retval = check_dir(argv[i], (char *)NULL, 0, norecurse); } exit(retval); } chkrootkit-0.46a/check_wtmpx.c010044400017500001750000000160331032550144400160450ustar00jessenjessen/* * @(#)check_wtmpx.c 0.02 beta 2001/06/27 NsFocus Copyleft 2001-2010 *------------------------------------------------------------------------ * File : check_wtmpx.c * Version : 0.02 beta * Platform : SPARC/Solaris 2.6/7 * Author : NsFocus Security Team * : http://www.nsfocus.com * Fix : scz < mailto: scz@nsfocus.com > * Compile : gcc -Wall -O3 -o check_wtmpx check_wtmpx.c * : /usr/ccs/bin/strip check_wtmpx * : /usr/ccs/bin/mcs -d check_wtmpx * Date : 2001-06-27 11:36 */ #if !defined(__SunOS__) && !defined(SOLARIS2) int main () { return 0; } #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WTMP_FILENAME "/var/adm/wtmp" #define WTMPX_FILENAME "/var/adm/wtmpx" struct file_utmp_entry { char ut_user[8]; /* User login name */ char ut_id[4]; /* /etc/inittab id */ char ut_line[12]; /* device name (console, lnxx) */ int16_t ut_pid; /* process id */ int16_t ut_type; /* type of entry */ struct { int16_t e_termination; /* Process termination status */ int16_t e_exit; /* Process exit status */ } ut_exit; /* The exit status of a process */ uint32_t ut_time; /* time entry was made */ }; struct timeval_32 { uint32_t tv_sec; /* seconds */ int32_t tv_usec; /* and microseconds */ }; /* * This data structure describes the utmp *file* contents using * fixed-width data types. It should only be used by the implementation. * * Applications should use the getutxent(3c) family of routines to interact * with this database. */ struct file_utmpx_entry { char ut_user[32]; /* user login name */ char ut_id[4]; /* inittab id */ char ut_line[32]; /* device name (console, lnxx) */ uint32_t ut_pid; /* process id */ int16_t ut_type; /* type of entry */ struct { int16_t e_termination; /* process termination status */ int16_t e_exit; /* process exit status */ } ut_exit; /* exit status of a process */ struct timeval_32 ut_tv; /* time entry was made */ int32_t ut_session; /* session ID, user for windowing */ int32_t pad[5]; /* reserved for future use */ int16_t ut_syslen; /* significant length of ut_host */ char ut_host[257]; /* remote host name */ }; static void usage ( char * arg ) { fprintf( stderr, " Usage: %s [-h] [-w wtmp] [-x wtmpx]\n", arg ); exit( EXIT_FAILURE ); } /* end of usage */ int main ( int argc, char * argv[] ) { int fd_wtmp, fd_wtmpx; char filename_wtmp[128] = WTMP_FILENAME; char filename_wtmpx[128] = WTMPX_FILENAME; ssize_t wtmp_bytes_read; ssize_t wtmpx_bytes_read; uint32_t wtmp_read_counter = 0; uint32_t wtmpx_read_counter = 0; int c; struct file_utmp_entry utmp_entry; struct file_utmpx_entry utmpx_entry; opterr = 0; /* Don't want getopt() writing to stderr */ while ( ( c = getopt( argc, argv, "hw:x:" ) ) != EOF ) { switch ( c ) { case 'w': strncpy( filename_wtmp, optarg, 128 ); filename_wtmp[127] = '\0'; break; case 'x': strncpy( filename_wtmpx, optarg, 128 ); filename_wtmpx[127] = '\0'; break; case 'h': case '?': usage( argv[0] ); break; } /* end of switch */ } /* end of while */ fd_wtmp = open( filename_wtmp, O_RDONLY ); if ( fd_wtmp < 0 ) { fprintf( stderr, "Unable to open %s\n", filename_wtmp ); return( EXIT_FAILURE ); } fd_wtmpx = open( filename_wtmpx, O_RDONLY ); if ( fd_wtmpx < 0 ) { fprintf( stderr, "Unable to open %s\n", filename_wtmpx ); close( fd_wtmp ); return( EXIT_FAILURE ); } while ( 1 ) { wtmpx_bytes_read = read( fd_wtmpx, &utmpx_entry, sizeof( struct file_utmpx_entry ) ); if ( wtmpx_bytes_read > 0 ) { if ( wtmpx_bytes_read < sizeof( struct file_utmpx_entry ) ) { fprintf( stderr, "wtmpx entry may be corrupted\n" ); break; } wtmpx_read_counter++; } wtmp_bytes_read = read( fd_wtmp, &utmp_entry, sizeof( struct file_utmp_entry ) ); if ( wtmp_bytes_read > 0 ) { if ( wtmp_bytes_read < sizeof( struct file_utmp_entry ) ) { fprintf( stderr, "wtmp entry may be corrupted\n" ); break; } wtmp_read_counter++; } if ( ( wtmpx_bytes_read <= 0 ) || ( wtmp_bytes_read <= 0 ) ) { break; } if ( strncmp( utmp_entry.ut_user, utmpx_entry.ut_user, 8 ) != 0 ) { fprintf( stderr, "[ %u ] ut_user %s <-> %s\n", wtmp_read_counter, utmp_entry.ut_user, utmpx_entry.ut_user ); break; } if ( memcmp( utmp_entry.ut_id, utmpx_entry.ut_id, 4 ) != 0 ) { fprintf( stderr, "[ %u ] utmp_entry.ut_id != utmpx_entry.ut_id\n", wtmp_read_counter ); break; } if ( strcmp( utmp_entry.ut_line, utmpx_entry.ut_line ) != 0 ) { fprintf( stderr, "[ %u ] ut_line %s <-> %s\n", wtmp_read_counter, utmp_entry.ut_line, utmpx_entry.ut_line ); break; } if ( utmp_entry.ut_pid != utmpx_entry.ut_pid ) { fprintf( stderr, "[ %u ] ut_pid %d <-> %d\n", wtmp_read_counter, utmp_entry.ut_pid, utmpx_entry.ut_pid ); break; } if ( utmp_entry.ut_type != utmpx_entry.ut_type ) { fprintf( stderr, "[ %u ] ut_type %d <-> %d\n", wtmp_read_counter, utmp_entry.ut_type, utmpx_entry.ut_type ); break; } if ( utmp_entry.ut_time != utmpx_entry.ut_tv.tv_sec ) { fprintf( stderr, "[ %u ] ut_time %08X <-> %08X\n", wtmp_read_counter, utmp_entry.ut_time, utmpx_entry.ut_tv.tv_sec ); break; } } /* end of while */ if ( wtmpx_read_counter != wtmp_read_counter ) { fprintf( stderr, "wtmpx or wtmp entry may be deleted\n" ); } close( fd_wtmpx ); close( fd_wtmp ); return( EXIT_SUCCESS ); } /* end of main */ #endif chkrootkit-0.46a/chkrootkit.lsm010044400017500001750000000010761033044122000162530ustar00jessenjessenBegin3 Title: Chkrootkit Version: 0.46a Entered-date: Fri Oct 28 13:23:52 BRST 2005 Description: locally checks for signs of a rootkit Keywords: rootkit check vulnerability unix LKM Ramen Lion Worn Adore Worm Author: Nelson Murilo Maintained-by: Nelson Murilo, Klaus Steding-Jessen Primary-site: http://www.chkrootkit.org Alternate-site: ftp://ftp.pangeia.com.br/pub/seg/pac/ Original-site: Platform: Linux, FreeBSD, OpenBSD, NetBSD, Sun/Solaris, HPUX, BSDI, TRU64 Copying-policy: AMS End chkrootkit-0.46a/Makefile010044400017500001750000000031441032550143700150260ustar00jessenjessen# # Makefile for chkrootkit # (C) 1997-2003 Nelson Murilo, Pangeia Informatica, AMS Foundation and others. # CC = gcc CFLAGS = -DHAVE_LASTLOG_H STATIC = -static ### ### Solaris 2.x ### # If you have Solaris 2.x, uncomment the next two lines #CFLAGS = -DHAVE_LASTLOG_H -DSOLARIS2 #LDFLAGS=-lsocket # If you use gcc in Solaris don't uncomment STATIC line below #STATIC = -B static ### ### Mac OS X ### # If you have Mac OS X, uncomment the next line #STATIC = ### ### FreeBSD or OpenBSD 2.x ### # If you have FreeBSD or OpenBSD 2.x, uncomment the next line #CFLAGS = SRCS = chklastlog.c chkwtmp.c ifpromisc.c chkproc.c chkdirs.c check_wtmpx.c strings.c OBJS = chklastlog.o chkwtmp.o ifpromisc.o chkproc.o chkdirs.o check_wtmpx.o strings-static.o all: @echo '*** stopping make sense ***' @exec make sense sense: chklastlog chkwtmp ifpromisc chkproc chkdirs check_wtmpx strings-static chkutmp chklastlog: chklastlog.c ${CC} ${CFLAGS} -o $@ chklastlog.c @strip $@ chkwtmp: chkwtmp.c ${CC} ${CFLAGS} -o $@ chkwtmp.c @strip $@ ifpromisc: ifpromisc.c ${CC} ${CFLAGS} ${LDFLAGS} -D_FILE_OFFSET_BITS=64 -o $@ ifpromisc.c @strip $@ chkproc: chkproc.c ${CC} ${LDFLAGS} -o $@ chkproc.c @strip $@ chkdirs: chkdirs.c ${CC} ${LDFLAGS} -o $@ chkdirs.c @strip $@ check_wtmpx: check_wtmpx.c ${CC} ${LDFLAGS} -o $@ check_wtmpx.c @strip $@ chkutmp: chkutmp.c ${CC} ${LDFLAGS} -o $@ chkutmp.c @strip $@ strings-static: strings.c ${CC} ${STATIC} ${LDFLAGS} -o $@ strings.c @strip $@ clean: rm -f ${OBJS} core chklastlog chkwtmp ifpromisc chkproc chkdirs check_wtmpx strings-static chkutmp chkrootkit-0.46a/ACKNOWLEDGMENTS010044400017500001750000000065521032775150200155460ustar00jessenjessenThe following people have contributed to the chkrootkit project: Agustin Navarro (debug help) Alberto Courrege Gomide (debug help) Andre Gustavo de Carvalho Albuquerque (debug, performance and Solaris patches) Dave Ansalvish (Solaris debug help) Bruno Lopes (debug help) Daniel Lafraia (source code addition) Josh Karp (debug help for Solaris 8) Klaus Steding-Jessen (debug, lots of good suggestions and LKM check Perl code) Paulo C. Marques F. (debug help) Pedro Vazquez (lots of good suggestions) Richard Eisenman (Red Hat support) Manfred Bartz (debug help) Luiz E. R. Cordeiro (debug help) Vince Hillier (debug help) Steve Campbell (Solaris bug fixes) Strashimir Mihnev (new rootkit) Patrick Duane Dunston (Adore LKM detection) Rudolf Leitgeb (chklastlog bug fix) Marcos Aguinaldo Forquesato (Solaris debug) scz (check_wtmpx code) Yaroslav Polyakov (inetdconf function) Andreas Tirok (chklastlog patch) Sean D. True (strings.c) Leif Neland (duarawkz rootkit) Kaveh Goudarzi (Pizdakit rootkit) m0xx (monkit and Bobkit rootkits) Bob Grabowsky and Mihai Sandu (t0rn v8.0 variant) Razvan Cosma (new rootkit) Kostya Kortchinsky (chkproc patch) Frank Haverkamp (new rookit) Ludovic Drolez (new rootkit) Dan Irwin (new rootkit) Anton Chuvakin (new rootkit) Steve Collins (new rootkit) Indra Kusuma (new rootkit) Mark Newby (new rootkit) anonymous (new rootkit) Gerard van Wageningen (chklastlog.c) Morohoshi Akihiko, Kostya Kortchinsky and Aaron Sherman (chkproc.c) Andrey Chernomyrdin (new rootkit) Razvan Cosma (new rootkit) zeno (new rootkits) Hal Pomeranz (chkdirs.c) marc (Bug report) Piete Brooks (patches for chkrootkit) Kostya Kortchinsky (chkproc Solaris port) Jan Brinham (chkrookit additions) Paulo Rodrigo (Bug report) Andreas Unterluggauer (Bug report) Mihnea Stoenescu (ideas for chkrootkit) Anton Chuvakin (new rootkit) Russ Reynaga (SunOS debug/tests) ymailer (lots of rootkits) Junichi Murakami (Adore detection method) Gérard Breiner (HP-UX Port) Andrea Barbieri (SunOS debug) Matthew Deatherage (Bug report) Eduardo Bacchi Kienetz (Slapper-B detection) aka br (SiN Rootkit) Ymailer (shv4, Big and Aquatica) Eduardo Bacchi (shv4) T. Tanaka (bug fix) Jan Iven (suckit tests) Rob Thomas Michael Griego (chkproc NPTL threading mechanisms patch) Marcel Haman (aditional Suckit detection) Andreas Grundle (Volc Rookit) Bejamin Molitor (Gold2 Rookit) James Mackinnon (TC2 Worm) Joshua J Robinson (Anonoying Rootkit) Bill Orvis (ZK Rootkit) Thomas Davidson (BSDI support) Bill DuPree (chkproc.c fix) Jeremy H. Brown (-r option corrections) Jason Montleon (bug report) Djony W Tambosi (bug report) Benjamin Schüdz (bug report) Eugene Tsyrklevich (bug report) Michael Dorrington (web page) Ragnar Rova (write test fix) Chris Campbell (C++ comments causing problems on old Solaris compilers) Markus Alt (Typo) Egon Eckert (tcpd test at debian) Silvio and nacho (zaRwT rootkit) Lantz Moore (promisc test on Linux kernels 2.[46].x) Marcel Haman (another Suckit sign) Alfred (found sniffer in another area (/usr/lib)) Ymailer (several CGI backdoors) Dietrich Raisin (del counter fix in chkwtmp.c) Patrick Gosling (tnfs function improvement) Mikhail Zotov (bug report) Michael Schwendt (patches) Yukio Yamada (bug report) h0nIng (Fu rootkit) Jeff Kuehn (bug report) Jeremy Miller (chkutmp) Cristine Hoepers (chkrootkit homepage redesign using valid strict XHTML) Ighighi X (chkutmp) Jérémie Andréi (chkwtmp) Aaron Harwood (chkdirs) chkrootkit-0.46a/README.chkwtmp010044400017500001750000000024141032550144300157160ustar00jessenjessen chkwtmp - check wtmp-file for overwritten information Copyright (c) DFN-CERT, Univ. of Hamburg 1994 Univ. Hamburg, Dept. of Computer Science DFN-CERT Vogt-Koelln-Strasse 30 22527 Hamburg Germany This program is free software; you can distribute it and/or modify it as long as you retain the DFN-CERT copyright statement. It can be obtained via anonymous FTP from ftp://ftp.cert.dfn.de/pub/tools/admin/chkwtmp/chkwtmp.tar.Z This program is distributed WITHOUT ANY WARRANTY; without the IMPLIED WARRANTY of merchantability or fitness for a particular purpose. This package contains: README MANIFEST chkwtmp.1 chkwtmp.c chkwtmp.txt To create chkwtmp under SunOS 4.x, type: % cc -o chkwtmp chkwtmp.c To run chkwtmp you need read permission on the file /var/adm/wtmp. Normally this file is world-readable and no special privileges are required to run the checker. The following is an example of the output of chkwtmp. Running chkwtmp on a machine with deleted wtmp-entries, under csh(1): % chkwtmp 1 deletion(s) between Thu Sep 29 08:23:57 1994 and Thu Sep 29 14:11:58 1994 % Running chkwtmp on a machine with no deleted wtmp-entries, under csh(1): % chkwtmp % chkrootkit-0.46a/chklastlog.c010044400017500001750000000170621032550144700156720ustar00jessenjessen/* Copyright (c) DFN-CERT, Univ. of Hamburg 1994 Univ. Hamburg, Dept. of Computer Science DFN-CERT Vogt-Koelln-Strasse 30 22527 Hamburg Germany 02/20/97 - Minimal changes for Linux/FreeBSD port. 02/25/97 - Another little bit change 12/26/98 - New Red Hat compatibility Nelson Murilo, nelson@pangeia.com.br 01/05/00 - Performance patches 09/07/00 - Ports for Solaris Andre Gustavo de Carvalho Albuquerque 12/15/00 - Add -f & -l options Nelson Murilo, nelson@pangeia.com.br 01/09/01 - Many fixes Nelson Murilo, nelson@pangeia.com.br 01/20/01 - More little fixes Nelson Murilo, nelson@pangeia.com.br 24/01/01 - Segfault in some systems fixed, Thanks for Manfred Bartz 02/06/01 - Beter system detection & fix bug in OBSD, Thanks for Rudolf Leitgeb 09/19/01 - Another Segfault in some systems fixed, Thanks for Andreas Tirok 06/26/02 - Fix problem with maximum uid number - Thanks for Gerard van Wageningen 07/02/02 - Minor fixes Nelson Murilo, nelson@pangeia.com.br */ #if defined(SOLARIS2) || defined(__linux__) #define HAVE_LASTLOG_H 1 #else #undef HAVE_LASTLOG_H #endif #include #ifdef __linux__ #include #endif #include #include #include #include #include #include #include #if (HAVE_LASTLOG_H) #include #endif #include #ifdef SOLARIS2 #include #endif #ifdef __FreeBSD__ #define WTMP_FILENAME "/var/log/wtmp" #define LASTLOG_FILENAME "/var/log/lastlog" #endif #ifdef __OpenBSD__ #define WTMP_FILENAME "/var/log/wtmp" #define LASTLOG_FILENAME "/var/log/lastlog" #endif #ifndef WTMP_FILENAME #define WTMP_FILENAME "/var/adm/wtmp" #endif #ifndef LASTLOG_FILENAME #define LASTLOG_FILENAME "/var/adm/lastlog" #endif #define TRUE 1L #define FALSE 0L long total_wtmp_bytes_read=0; size_t wtmp_file_size; uid_t *uid; void read_status(); struct s_localpwd { int numentries; uid_t *uid; char **uname; }; #ifndef SOLARIS2 int nonuser(struct utmp utmp_ent); #endif struct s_localpwd *read_pwd(); void free_results(struct s_localpwd *); uid_t *localgetpwnam(struct s_localpwd *, char *); int getslot(struct s_localpwd *, uid_t); #define MAX_ID 99999 int main(int argc, char*argv[]) { int fh_wtmp; int fh_lastlog; struct lastlog lastlog_ent; struct utmp utmp_ent; long userid[MAX_ID]; long i, slot; int status = 0; long wtmp_bytes_read; struct stat wtmp_stat; struct s_localpwd *localpwd; uid_t *uid; char wtmpfile[128], lastlogfile[128]; memcpy(wtmpfile, WTMP_FILENAME, 127); memcpy(lastlogfile, LASTLOG_FILENAME, 127); while (--argc && ++argv) /* poor man getopt */ { if (!memcmp("-f", *argv, 2)) { if (!--argc) break; ++argv; memcpy(wtmpfile, *argv, 127); } else if (!memcmp("-l", *argv, 2)) { if (!--argc) break; ++argv; memcpy(lastlogfile, *argv, 127); } } signal(SIGALRM, read_status); alarm(5); for (i=0; i0) { if (wtmp_bytes_read < sizeof(struct utmp)) { fprintf(stderr, "wtmp entry may be corrupted"); break; } total_wtmp_bytes_read+=wtmp_bytes_read; if ( !nonuser(utmp_ent) && strncmp(utmp_ent.ut_line, "ftp", 3) && (uid=localgetpwnam(localpwd,utmp_ent.ut_name)) != NULL ) { if (*uid > MAX_ID) { fprintf(stderr, "MAX_ID is %ld and current uid is %ld, please check\n\r", MAX_ID, *uid ); exit (1); } if (!userid[*uid]) { lseek(fh_lastlog, (long)*uid * sizeof (struct lastlog), 0); if ((wtmp_bytes_read = read(fh_lastlog, &lastlog_ent, sizeof (struct lastlog))) > 0) { if (wtmp_bytes_read < sizeof(struct lastlog)) { fprintf(stderr, "lastlog entry may be corrupted"); break; } if (lastlog_ent.ll_time == 0) { if (-1 != (slot = getslot(localpwd, *uid))) printf("user %s deleted or never logged from lastlog!\n", NULL != localpwd->uname[slot] ? (char*)localpwd->uname[slot] : "(null)"); else printf("deleted user uid(%d) not in passwd\n", *uid); ++status; } userid[*uid]=TRUE; } } } } #if 0 printf("\n"); #endif free_results(localpwd); close(fh_wtmp); close(fh_lastlog); return(status); } #ifndef SOLARIS2 /* minimal funcionality of nonuser() */ int nonuser(struct utmp utmp_ent) { return (!memcmp(utmp_ent.ut_name, "shutdown", sizeof ("shutdown"))); } #endif void read_status() { double remaining_time; static long last_total_bytes_read=0; int diff; diff = total_wtmp_bytes_read-last_total_bytes_read; if (diff == 0) diff = 1; remaining_time=(wtmp_file_size-total_wtmp_bytes_read)*5/(diff); last_total_bytes_read=total_wtmp_bytes_read; printf("Remaining time: %6.2f seconds\n", remaining_time); /* signal(SIGALRM,read_status); alarm(5); */ } struct s_localpwd *read_pwd() { struct passwd *pwdent; int numentries=0,i=0; struct s_localpwd *localpwd; setpwent(); while ((pwdent = getpwent())) { numentries++; } endpwent(); localpwd = (struct s_localpwd *)malloc((size_t)sizeof(struct s_localpwd)); localpwd->numentries=numentries; localpwd->uid = (uid_t *)malloc((size_t)numentries*sizeof(uid_t)); localpwd->uname = (char **)malloc((size_t)numentries*sizeof(char *)); for (i=0;iuname[i] = (char *)malloc((size_t)30*sizeof(char)); } i=0; setpwent(); while ((pwdent = getpwent()) && (iuid[i]=pwdent->pw_uid; memcpy(localpwd->uname[i],pwdent->pw_name,(strlen(pwdent->pw_name)>29)?29:strlen(pwdent->pw_name)+1); i++; } endpwent(); return(localpwd); } void free_results(struct s_localpwd *localpwd) { int i; free(localpwd->uid); for (i=0;i<(localpwd->numentries);i++) { free(localpwd->uname[i]); } free(localpwd->uname); free(localpwd); } uid_t *localgetpwnam(struct s_localpwd *localpwd, char *username) { int i; size_t len; for (i=0; i<(localpwd->numentries);i++) { len = (strlen(username)>29)?30:strlen(username)+1; if (!memcmp(username,localpwd->uname[i],len)) { return &(localpwd->uid[i]); } } return NULL; } int getslot(struct s_localpwd *localpwd, uid_t uid) { int i; for (i=0; i<(localpwd->numentries);i++) { if (localpwd->uid[i] == uid) return i; } return -1; } chkrootkit-0.46a/chkrootkit010075500017500001750000002147361032775517600155270ustar00jessenjessen#! /bin/sh # -*- Shell-script -*- # $Id: chkrootkit, v 0.46 2005/10/26 CHKROOTKIT_VERSION='0.46' # Authors: Nelson Murilo (main author) and # Klaus Steding-Jessen # # (C)1997-2005 Nelson Murilo, Pangeia Informatica, AMS Foundation and others. # All rights reserved ### workaround for some Bourne shell implementations unalias login > /dev/null 2>&1 unalias ls > /dev/null 2>&1 unalias netstat > /dev/null 2>&1 unalias ps > /dev/null 2>&1 unalias dirname > /dev/null 2>&1 # Workaround for recent GNU coreutils export _POSIX2_VERSION=199209 # Native commands TROJAN="amd basename biff chfn chsh cron date du dirname echo egrep env find \ fingerd gpm grep hdparm su ifconfig inetd inetdconf identd init killall \ ldsopreload login ls lsof mail mingetty netstat named passwd pidof pop2 pop3 \ ps pstree rpcinfo rlogind rshd slogin sendmail sshd syslogd tar tcpd \ tcpdump top telnetd timed traceroute vdir w write" # Tools TOOLS="aliens asp bindshell lkm rexedcs sniffer w55808 wted scalper slapper z2 chkutmp" # Return Codes INFECTED=0 NOT_INFECTED=1 NOT_TESTED=2 NOT_FOUND=3 INFECTED_BUT_DISABLED=4 # Many trojaned commands have this label GENERIC_ROOTKIT_LABEL="^/bin/.*sh$|bash|elite$|vejeta|\.ark" ###################################################################### # tools functions # # 55808.A Worm # w55808 (){ W55808_FILES="${ROOTDIR}tmp/.../a ${ROOTDIR}tmp/.../r" STATUS=0 for i in ${W55808_FILES}; do if [ -f ${i} ]; then STATUS=1 fi done if [ ${STATUS} -eq 1 ] ;then echo "Warning: Possible 55808 Worm installed" else if [ "${QUIET}" != "t" ]; then echo "not infected"; fi return ${NOT_INFECTED} fi } # # SLAPPER.{A,B,C,D} and the multi-platform variant # slapper (){ SLAPPER_FILES="${ROOTDIR}tmp/.bugtraq ${ROOTDIR}tmp/.bugtraq.c" SLAPPER_FILES="$SLAPPER_FILES ${ROOTDIR}tmp/.unlock ${ROOTDIR}tmp/httpd \ ${ROOTDIR}tmp/update ${ROOTDIR}tmp/.cinik ${ROOTDIR}tmp/.b" SLAPPER_PORT="0.0:2002 |0.0:4156 |0.0:1978 |0.0:1812 |0.0:2015 " OPT=-an STATUS=0 file_port= if ${netstat} "${OPT}"|${egrep} ^tcp|${egrep} "${SLAPPER_PORT}"> /dev/null 2>&1 then STATUS=1 [ "$SYSTEM" = "Linux" ] && file_port=`netstat -p ${OPT} | \ $egrep ^tcp|$egrep "${SLAPPER_PORT}" | awk '{ print $7 }' | tr -d :` fi for i in ${SLAPPER_FILES}; do if [ -f ${i} ]; then file_port=$file_port $i STATUS=1 fi done if [ ${STATUS} -eq 1 ] ;then echo "Warning: Possible Slapper Worm installed ($file_port)" else if [ "${QUIET}" != "t" ]; then echo "not infected"; fi return ${NOT_INFECTED} fi } scalper (){ SCALPER_FILES="${ROOTDIR}tmp/.uua ${ROOTDIR}tmp/.a" SCALPER_PORT=2001 OPT=-an STATUS=0 if ${netstat} "${OPT}" | ${egrep} "0.0:${SCALPER_PORT} "> /dev/null 2>&1; then STATUS=1 fi for i in ${SCALPER_FILES}; do if [ -f ${i} ]; then STATUS=1 fi done if [ ${STATUS} -eq 1 ] ;then echo "Warning: Possible Scalper Worm installed" else if [ "${QUIET}" != "t" ]; then echo "not infected"; fi return ${NOT_INFECTED} fi } asp (){ ASP_LABEL="poop" STATUS=${NOT_INFECTED} CMD=`loc asp asp $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${egrep} ^asp ${ROOTDIR}etc/inetd.conf" expertmode_output "${strings} -a ${CMD}" return 5 fi if ${egrep} "^asp" ${ROOTDIR}etc/inetd.conf >/dev/null 2>&1; then echo "Warning: Possible Ramen Worm installed in inetd.conf" STATUS=${INFECTED} fi if [ ${CMD} = "asp" -o ${CMD} = "${ROOTDIR}asp" ]; then if [ "${QUIET}" != "t" ]; then echo "not infected"; fi return ${NOT_INFECTED} fi if ${strings} -a ${CMD} | ${egrep} "${ASP_LABEL}" >/dev/null 2>&1; then echo "INFECTED" STATUS=${INFECTED} else if [ "${QUIET}" != "t" ]; then echo "not infected"; fi return ${NOT_INFECTED} fi return ${STATUS} } sniffer () { if [ "${ROOTDIR}" != "/" ]; then echo "not tested" return ${NOT_TESTED} fi if [ "$SYSTEM" = "SunOS" ]; then return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "./ifpromisc" -v return 5 fi if [ ! -x ./ifpromisc ]; then echo "not tested: can't exec ./ifpromisc" return ${NOT_TESTED} else [ "${QUIET}" != "t" ] && ./ifpromisc -v || ./ifpromisc -q fi } chkutmp() { if [ ! -x ./chkutmp ]; then echo "not tested: can't exec ./chkutmp" return ${NOT_TESTED} fi if ./chkutmp then if [ "${QUIET}" != "t" ]; then echo "chkutmp: nothing deleted"; fi fi } z2 () { if [ ! -x ./chklastlog ]; then echo "not tested: can't exec ./chklastlog" return ${NOT_TESTED} fi WTMP=`loc wtmp wtmp "${ROOTDIR}var/log ${ROOTDIR}var/adm"` LASTLOG=`loc lastlog lastlog "${ROOTDIR}var/log ${ROOTDIR}var/adm"` if [ ! -f $WTMP -a ! -f $LASTLOG ]; then echo "not tested: not found wtmp and/or lastlog file" return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "./chklastlog -f ${WTMP} -l ${LASTLOG}" return 5 fi if ./chklastlog -f ${WTMP} -l ${LASTLOG} then if [ "${QUIET}" != "t" ]; then echo "chklastlog: nothing deleted"; fi fi } wted () { if [ ! -x ./chkwtmp ]; then echo "not tested: can't exec ./chkwtmp" return ${NOT_TESTED} fi if [ "$SYSTEM" = "SunOS" ]; then if [ ! -x ./check_wtmpx ]; then echo "not tested: can't exec ./check_wtmpx" else if [ "${EXPERT}" = "t" ]; then expertmode_output "./check_wtmpx" return 5 fi if [ -f ${ROOTDIR}var/adm/wtmp ]; then if ./check_wtmpx then if [ "${QUIET}" != "t" ]; then \ echo "check_wtmpx: nothing deleted in /var/adm/wtmpx"; fi fi fi fi else WTMP=`loc wtmp wtmp "${ROOTDIR}var/log ${ROOTDIR}var/adm"` if [ "${EXPERT}" = "t" ]; then expertmode_output "./chkwtmp -f ${WTMP}" return 5 fi fi if ./chkwtmp -f ${WTMP} then if [ "${QUIET}" != "t" ]; then echo "chkwtmp: nothing deleted"; fi fi } bindshell () { PORT="114|145|465|511|600|1008|1524|1999|1978|2881|3049|3133|3879|4000|4369|5190|5665|10008|12321|23132|27374|29364|30999|31336|31337|45454|47017|47889|60001" OPT="-an" PI="" if [ "${ROOTDIR}" != "/" ]; then echo "not tested" return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${netstat} ${OPT}" return 5 fi for P in `echo $PORT | ${sed} 's/|/ /g'`; do if ${netstat} "${OPT}" | ${egrep} "^tcp.*LIST|^udp" | ${egrep} \ "[.:]${P}[^0-9.:]" >/dev/null 2>&1 then PI="${PI} ${P}" fi done if [ "${PI}" != "" ] then echo "INFECTED (PORTS: $PI)" else if [ "${QUIET}" != "t" ]; then echo "not infected"; fi fi } lkm () { prog="" if [ \( "${SYSTEM}" = "Linux" -o \( "${SYSTEM}" = "FreeBSD" -a \ `echo ${V} | ${awk} '{ if ($1 > 4.3) print 1; else print 0 }'` -eq 1 \) \) -a "${ROOTDIR}" = "/" ]; then [ ! -x ./chkproc ] && prog="./chkproc" [ ! -x ./chkdirs ] && prog="$prog ./chkdirs" if [ "$prog" != "" ]; then # echo "not tested: can't exec $prog" return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then [ -r /proc/ksyms ] && ${egrep} -i "adore|sebek" < /proc/ksyms 2>/dev/null [ -d /proc/knark ] && ${ls} -la /proc/knark 2> /dev/null PV=`$ps -V 2>/dev/null| $cut -d " " -f 3 |$awk -F . '{ print $1 "." $2 $3 }' | ${awk} '{ if ($0 > 3.19) print 3; else if ($0 < 2.11) print 1; else print 2 }'` [ "$PV" = "" ] && PV=2 [ "${SYSTEM}" = "SunOS" ] && PV=0 expertmode_output "./chkproc -v -v -p $PV" return 5 fi ### adore LKM [ -r /proc/ksyms ] && \ if `${egrep} -i adore < /proc/ksyms >/dev/null 2>&1`; then echo "Warning: Adore LKM installed" fi ### sebek LKM (Adore based) [ -r /proc/ksyms ] && \ if `${egrep} -i sebek < /proc/ksyms >/dev/null 2>&1`; then echo "Warning: Sebek LKM installed" fi ### knark LKM if [ -d /proc/knark ]; then echo "Warning: Knark LKM installed" fi PV=`$ps -V 2>/dev/null| $cut -d " " -f 3 |$awk -F . '{ print $1 "." $2 $3 }' | ${awk} '{ if ($0 > 3.19) print 3; else if ($0 < 2.11) print 1; else print 2 }'` [ "$PV" = "" ] && PV=2 [ "${SYSTEM}" = "SunOS" ] && PV=0 if [ "${DEBUG}" = "t" ]; then ${echo} "*** PV=$PV ***" fi if ./chkproc -p ${PV} then if [ "${QUIET}" != "t" ]; then echo "chkproc: nothing detected"; fi else echo "chkproc: Warning: Possible LKM Trojan installed" fi else if [ "${QUIET}" != "t" ]; then echo "chkproc: not tested"; fi fi } aliens () { if [ "${EXPERT}" = "t" ]; then ### suspicious files FILES="usr/bin/sourcemask usr/bin/ras2xm usr/sbin/in.telnet \ sbin/vobiscum usr/sbin/jcd usr/sbin/atd2 usr/bin/.etc usr/bin/xstat \ etc/ld.so.hash" expertmode_output "${find} ${ROOTDIR}dev -type f" expertmode_output "${find} ${ROOTDIR}var/run/.tmp" expertmode_output "${find} ${ROOTDIR}usr/man/man1/lib/.lib" expertmode_output "${find} ${ROOTDIR}usr/man/man2/.man8" expertmode_output "${find} ${ROOTDIR}usr/man/man1 -name '.. *'" expertmode_output "${find} ${ROOTDIR}usr/share/locale/sk" expertmode_output "${find} ${ROOTDIR}usr/lib/dy0" expertmode_output "${find} ${ROOTDIR}tmp -name 982235016-gtkrc-429249277" for i in ${FILES}; do expertmode_output "${ls} ${ROOTDIR}${i} 2> /dev/null" done [ -d ${ROOTDIR}lib/.so ] && expertmode_output "${find} ${ROOTDIR}lib/.so" [ -d "${ROOTDIR}usr/include/.. " ] && expertmode_output ${find} "${ROOTDIR}usr/include/.. " [ -d ${ROOTDIR}usr/lib/.fx ] && expertmode_output ${find} ${ROOTDIR}usr/lib/.fx [ -d ${ROOTDIR}var/local/.lpd ] && expertmode_output ${find} ${ROOTDIR}var/local/.lpd [ -d ${ROOTDIR}dev/rd/cdb ] && expertmode_output ${find} ${ROOTDIR}dev/rd/cdb ### sniffer's logs expertmode_output "${find} ${ROOTDIR}dev ${ROOTDIR}usr ${ROOTDIR}tmp \ ${ROOTDIR}lib ${ROOTDIR}etc ${ROOTDIR}var ${findargs} -name tcp.log -o -name \ .linux-sniff -o -name sniff-l0g -o -name core_ -o -name ${ROOTDIR}usr/lib/in.httpd -o \ -name ${ROOTDIR}usr/lib/in.pop3d" ### t0rn expertmode_output "${find} ${ROOTDIR}etc ${ROOTDIR}sbin \ ${ROOTDIR}usr/src/.puta ${ROOTDIR}lib ${ROOTDIR}usr/info -name \ ttyhash -o -name xlogin -o -name ldlib.tk -o -name .t?rn" LIBS= [ -d ${ROOTDIR}lib ] && LIBS="${ROOTDIR}lib" [ -d ${ROOTDIR}usr/lib ] && LIBS="${LIBS} ${ROOTDIR}usr/lib" [ -d ${ROOTDIR}usr/local/lib ] && \ LIBS="${LIBS} ${ROOTDIR}usr/local/lib" expertmode_output "${find} ${LIBS} -name libproc.a" ## Lion Worm expertmode_output "${find} ${ROOTDIR}dev/.lib/lib -name 1i0n.sh 2> /dev/null" ### ark expertmode_output "${find} ${ROOTDIR}dev -name ptyxx" expertmode_output "${find} ${ROOTDIR}usr/doc -name '... '" expertmode_output "${find} ${ROOTDIR}usr/lib -name '.ark*'" ### RK17 expertmode_output "${find} ${ROOTDIR}bin -name rtty -o -name squit" expertmode_output "${find} ${ROOTDIR}sbin -name pback" expertmode_output "${find} ${ROOTDIR}usr/man/man3 -name psid 2> /dev/null" expertmode_output "${find} ${ROOTDIR}proc -name kset 2> /dev/null" expertmode_output "${find} ${ROOTDIR}usr/src/linux/modules -name \ autod.o -o -name soundx.o 2> /dev/null" expertmode_output "${find} ${ROOTDIR}usr/bin -name gib -o \ -name ct -o -name snick -o -name kfl" CGIDIR="" for cgidir in www/httpd/cgi-bin www/cgi-bin var/www/cgi-bin \ var/lib/httpd/cgi-bin usr/local/httpd/cgi-bin usr/local/apache/cgi-bin \ home/httpd/cgi-bin /usr/local/apache2; do [ -d ${ROOTDIR}${cgidir} ] && CGIDIR="${CGIDIR} ${ROOTDIR}${cgidir}" done BACKDOORS="number.cgi void.cgi psid becys.cgi nobody.cgi bash.zk.cgi alya.cgi \ shell.cgi alin.cgi httpd.cgi linux.cgi sh.cgi take.cgi bogus.cgi alia.cgi all4one.cgi \ zxcvbnm.cgi secure.cgi ubb.cgi" for j in ${CGIDIR}; do for i in ${BACKDOORS}; do [ -f ${j}/${i} ] && echo ${j}/${i} done done ### rsha expertmode_output "${find} ${ROOTDIR}bin ${ROOTDIR}usr/bin -name kr4p \ -o -name n3tstat -o -name chsh2" expertmode_output "${find} ${ROOTDIR}etc/rc.d/rsha" expertmode_output "${find} ${ROOTDIR}etc/rc.d/arch/alpha/lib/.lib \ ${ROOTDIR}usr/src/linux/arch/alpha/lib/.lib/" ### ShitC Worm expertmode_output "${find} ${ROOTDIR}bin ${ROOTDIR}sbin -name home \ -o -name frgy -o -name sy" expertmode_output "${find} ${ROOTDIR}usr/bin -type d -name dir" expertmode_output "${find} ${ROOTDIR}usr/sbin -type d -name in.slogind" ### Omega Worm expertmode_output "${find} ${ROOTDIR}dev -name chr" ### rh-sharpe expertmode_output "${find} ${ROOTDIR}bin ${ROOTDIR}usr/bin -name lps \ -o -name .ps -o -name lpstree -o -name .lpstree -o -name lkillall \ -o -name ldu -o -name lnetstat" expertmode_output "${find} ${ROOTDIR}usr/include/rpcsvc -name du" ### Adore Worm expertmode_output "${find} ${ROOTDIR}usr/lib ${ROOTDIR}usr/bin \ -name red.tar -o -name start.sh -o -name klogd.o -o -name 0anacron-bak \ -o -name adore" expertmode_output "${find} ${ROOTDIR}usr/lib/lib" expertmode_output "${find} ${ROOTDIR}usr/lib/libt" ### suspicious files and dirs suspects="/usr/lib/pt07 /usr/bin/atm /tmp/.cheese /dev/ptyzx /dev/ptyzg /usr/bin/sourcemask /dev/ida /dev/xdf* /usr/lib/libx?otps /sbin/init.zk" DIR=${ROOTDIR}usr/lib [ -d ${ROOTDIR}usr/man ] && DIR="${DIR} ${ROOTDIR}usr/man" [ -d ${ROOTDIR}lib ] && DIR="${DIR} ${ROOTDIR}lib" [ -d ${ROOTDIR}usr/lib ] && DIR="${DIR} ${ROOTDIR}usr/lib" expertmode_output "${find} ${DIR} -name '.[A-Za-z]*'" expertmode_output "${find} ${DIR} -type d -name '.*'" expertmode_output "${find} ${DIR} -name '...*'" expertmode_output "${ls} ${suspects}" ### Maniac RK expertmode_output "${find} ${ROOTDIR}usr/bin -name mailrc" ### Ramen Worm expertmode_output "${find} ${ROOTDIR}usr/src/.poop \ ${ROOTDIR}tmp/ramen.tgz ${ROOTDIR}etc/xinetd.d/asp" ### Sadmind/IIS Worm expertmode_output "${find} ${ROOTDIR}dev/cuc" ### Monkit expertmode_output "${find} ${ROOTDIR}lib/defs" ### Showtee expertmode_output "${ls} ${ROOTDIR}usr/lib/.egcs \ ${ROOTDIR}usr/lib/.wormie ${ROOTDIR}usr/lib/libfl.so \ ${ROOTDIR}usr/lib/.kinetic ${ROOTDIR}/usr/lib/liblog.o \ ${ROOTDIR}/usr/include/addr.h ${ROOTDIR}usr/include/cron.h \ ${ROOTDIR}/usr/include/file.h ${ROOTDIR}usr/include/proc.h \ ${ROOTDIR}/usr/include/syslogs.h ${ROOTDIR}/usr/include/chk.h" ### Optickit expertmode_output "${find} ${ROOTDIR}usr/bin -name xchk -o -name xsf" ### T.R.K expertmode_output "${find} ${ROOTDIR}usr/bin -name soucemask -o -name ct" ### MithRa's Rootkit expertmode_output "${find} ${ROOTDIR}usr/lib/locale -name uboot" ### OpenBSD rootkit v1 if [ "$SYSTEM" != "SunOS" -a ! -f /usr/lib/security/libgcj.security ] then expertmode_output "${find} ${ROOTDIR}usr/lib/security" fi ### LOC rootkit expertmode_output "${find} ${ROOTDIR}tmp -name xp -o -name kidd0.c" ### Romanian rootkit expertmode_output "${ls} ${ROOTDIR}usr/include/file.h \ ${ROOTDIR}usr/include/proc.h ${ROOTDIR}usr/include/addr.h \ ${ROOTDIR}usr/include/syslogs.h" ## HKRK rootkit ${egrep} "\.hk" ${ROOTDIR}etc/rc.d/init.d/network 2>/dev/null ## Suckit rootkit expertmode_output "${strings} ${ROOTDIR}sbin/init | ${egrep} HOME" expertmode_output "cat ${ROOTDIR}proc/1/maps | ${egrep} init." ## Volc rootkit expertmode_output "${ls} ${ROOTDIR}usr/bin/volc" expertmode_output "${find} ${ROOTDIR}usr/lib/volc" ## Gold2 rootkit expertmode_output "${ls} ${ROOTDIR}usr/bin/ishit" ## TC2 Worm expertmode_output "${ls} ${ROOTDIR}usr/bin/util ${ROOTDIR}usr/info \ ${ROOTDIR}usr/sbin/initcheck ${ROOTDIR}usr/sbin/ldb" ## Anonoiyng rootkit expertmode_output "${ls} ${ROOTDIR}usr/sbin/mech* ${ROOTDIR}usr/sbin/kswapd" ## ZK rootkit expertmode_output "${ls} ${ROOTDIR}etc/sysconfig/console/load*" ## ShKit expertmode_output "${ls} ${ROOTDIR}lib/security/.config ${ROOTDIR}etc/ld.so.hash" ## AjaKit expertmode_output "${find} ${ROOTDIR}lib -name .ligh.gh" expertmode_output "${find} ${ROOTDIR}dev -name tux" ## zaRwT expertmode_output "${find} ${ROOTDIR}bin -name imin -o -name imout" ## Madalin rootkit expertmode_output "${find} ${ROOTDIR}usr/include -name icekey.h -o \ -name iceconf.h -o -name iceseed.h" ## Fu rootkit expertmode_output "${find} ${ROOTDIR}sbin ${ROOTDIR}bin \ ${ROOTDIR}usr/include -name xc -o -name .lib -o name ivtype.h" ## Kenga3 Rookit expertmode_output "${find} ${ROOTDIR}usr/include/. ." ## ESRK Rookit expertmode_output "${ls} -l ${ROOTDIR}usr/lib/tcl5.3" ## rootedoor for i in `$echo ${PATH}|tr -s ':' ' '`; do expertmode_output "${ls} -l ${ROOTDIR}${i}/rootedoor" done ### shell history file check if [ ! -z "${SHELL}" -a ! -z "${HOME}" ]; then expertmode_output "${find} ${ROOTDIR}${HOME} -name .*history \ -size 0" expertmode_output "${find} ${ROOTDIR}${HOME} -name .*history \ \( -links 2 -o -type l \)" fi return 5 ### expert mode ends here fi ### ### suspicious files and sniffer's logs ### suspects="usr/lib/pt07 usr/bin/atm tmp/.cheese /dev/ptyzx dev/ptyzy \ usr/bin/sourcemask dev/ida dev/xdf1 dev/xdf2 usr/bin/xstat \ tmp/982235016-gtkrc-429249277 usr/bin/sourcemask /usr/bin/ras2xm \ usr/sbin/in.telnet sbin/vobiscum usr/sbin/jcd usr/sbin/atd2 usr/bin/.etc \ etc/ld.so.hash sbin/init.zk usr/lib/in.httpd usr/lib/in.pop3d" dir="var/run/.tmp lib/.so usr/lib/.fx var/local/.lpd dev/rd/cdb" files=`${find} ${ROOTDIR}dev -type f -exec ${egrep} -l "^[0-5] " {} \;` if [ "${files}" != "" ]; then echo echo ${files} fi for i in ${dir}; do if [ -d ${ROOTDIR}${i} ]; then echo echo "Suspect directory ${i} FOUND! Looking for sniffer logs" files=`${find} ${ROOTDIR}${i}` echo echo ${files} fi done for i in ${suspects}; do if [ -f ${ROOTDIR}${i} ]; then echo "${ROOTDIR}${i} " files="INFECTED" fi done if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "no suspect files"; fi fi if [ "${QUIET}" != "t" ]; then \ printn "Searching for sniffer's logs, it may take a while... "; fi files=`${find} ${ROOTDIR}dev ${ROOTDIR}tmp ${ROOTDIR}lib ${ROOTDIR}etc ${ROOTDIR}var \ ${findargs} \( -name "tcp.log" -o -name ".linux-sniff" -o -name "sniff-l0g" -o -name "core_" \) \ 2>/dev/null` if [ "${files}" = "" ] then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo echo ${files} fi ### HiDrootkit if [ "${QUIET}" != "t" ]; then printn \ "Searching for HiDrootkit's default dir... "; fi if [ -d ${ROOTDIR}var/lib/games/.k ] then echo "Possible HiDrootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### t0rn if [ "${QUIET}" != "t" ]; then printn\ "Searching for t0rn's default files and dirs... "; fi if [ -f ${ROOTDIR}etc/ttyhash -o -f ${ROOTDIR}sbin/xlogin -o \ -d ${ROOTDIR}usr/src/.puta -o -r ${ROOTDIR}lib/ldlib.tk -o \ -d ${ROOTDIR}usr/info/.t0rn ] then echo "Possible t0rn rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### t0rn v8 if [ "${QUIET}" != "t" ]; then \ printn "Searching for t0rn's v8 defaults... "; fi [ -d ${ROOTDIR}lib ] && LIBS=${ROOTDIR}lib [ -d ${ROOTDIR}usr/lib ] && LIBS="${LIBS} ${ROOTDIR}usr/lib" [ -d ${ROOTDIR}usr/local/lib ] && LIBS="${LIBS} ${ROOTDIR}usr/local/lib" if [ `find ${LIBS} -name libproc.a 2> /dev/null` ] then echo "Possible t0rn v8 \(or variation\) rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Lion Worm if [ "${QUIET}" != "t" ]; then \ printn "Searching for Lion Worm default files and dirs... "; fi if [ -d ${ROOTDIR}usr/info/.torn -o -d ${ROOTDIR}dev/.lib -o \ -f ${ROOTDIR}bin/in.telnetd -o -f ${ROOTDIR}bin/mjy ] then echo "Possible Lion worm installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### RSHA rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for RSHA's default files and dir... "; fi if [ -r "${ROOTDIR}bin/kr4p" -o -r "${ROOTDIR}usr/bin/n3tstat" \ -o -r "${ROOTDIR}usr/bin/chsh2" -o -r "${ROOTDIR}usr/bin/slice2" \ -o -r "${ROOTDIR}usr/src/linux/arch/alpha/lib/.lib/.1proc" \ -o -r "${ROOTDIR}etc/rc.d/arch/alpha/lib/.lib/.1addr" \ -o -d "${ROOTDIR}etc/rc.d/rsha" \ -o -d "${ROOTDIR}etc/rc.d/arch/alpha/lib/.lib" ] then echo "Possible RSHA's rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### RH-Sharpe rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for RH-Sharpe's default files... "; fi if [ -r "${ROOTDIR}bin/lps" -o -r "${ROOTDIR}usr/bin/lpstree" \ -o -r "${ROOTDIR}usr/bin/ltop" -o -r "${ROOTDIR}usr/bin/lkillall" \ -o -r "${ROOTDIR}usr/bin/ldu" -o -r "${ROOTDIR}usr/bin/lnetstat" \ -o -r "${ROOTDIR}usr/bin/wp" -o -r "${ROOTDIR}usr/bin/shad" \ -o -r "${ROOTDIR}usr/bin/vadim" -o -r "${ROOTDIR}usr/bin/slice" \ -o -r "${ROOTDIR}usr/bin/cleaner" -o -r "${ROOTDIR}usr/include/rpcsvc/du" ] then echo "Possible RH-Sharpe's rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ark rootkit if [ "${QUIET}" != "t" ]; then printn \ "Searching for Ambient's rootkit (ark) default files and dirs... "; fi if [ -d ${ROOTDIR}dev/ptyxx -o -r "${ROOTDIR}usr/lib/.ark?" -o \ -d ${ROOTDIR}usr/doc/"... " ]; then echo "Possible Ambient's rootkit \(ark\) installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### suspicious files and dirs DIR="${ROOTDIR}usr/lib" [ -d ${ROOTDIR}usr/man ] && DIR="$DIR ${ROOTDIR}usr/man" [ -d ${ROOTDIR}lib ] && DIR="$DIR ${ROOTDIR}lib" if [ "${QUIET}" != "t" ]; then printn \ "Searching for suspicious files and dirs, it may take a while... "; fi files=`${find} ${DIR} -name ".[A-Za-z]*" -o -name "...*" -o -name ".. *"` dirs=`${find} ${DIR} -type d -name ".*"` if [ "${files}" = "" -a "${dirs}" = "" ] then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo echo ${files} echo ${dirs} fi ### LPD Worm if [ "${QUIET}" != "t" ]; then \ printn "Searching for LPD Worm files and dirs... "; fi if ${egrep} "^kork" ${ROOTDIR}etc/passwd > /dev/null 2>&1 || \ ${egrep} "^666" ${ROOTDIR}etc/inetd.conf > /dev/null 2>&1 ; then echo "Possible LPD worm installed" elif [ -d ${ROOTDIR}dev/.kork -o -f ${ROOTDIR}bin/.ps -o \ -f ${ROOTDIR}bin/.login ]; then echo "Possible LPD worm installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Ramem Worm if [ "${QUIET}" != "t" ]; then \ printn "Searching for Ramen Worm files and dirs... "; fi if [ -d ${ROOTDIR}usr/src/.poop -o -f \ ${ROOTDIR}tmp/ramen.tgz -o -f ${ROOTDIR}etc/xinetd.d/asp ] then echo "Possible Ramen worm installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Maniac rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for Maniac files and dirs... "; fi files=`${find} ${ROOTDIR}usr/bin -name mailrc` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### RK17 rookit if [ "${QUIET}" != "t" ]; then \ printn "Searching for RK17 files and dirs... "; fi CGIDIR="" for cgidir in www/httpd/cgi-bin www/cgi-bin var/www/cgi-bin \ var/lib/httpd/cgi-bin usr/local/httpd/cgi-bin usr/local/apache/cgi-bin \ home/httpd/cgi-bin /usr/local/apache2 ; do [ -d ${ROOTDIR}${cgidir} ] && CGIDIR="$CGIDIR ${ROOTDIR}${cgidir}" done files=`${find} ${ROOTDIR}bin -name rtty -o -name squit && \ ${find} ${ROOTDIR}sbin -name pback && \ ${find} ${ROOTDIR}usr/man/man3 -name psid 2>/dev/null && \ ${find} ${ROOTDIR}proc -name kset 2> /dev/null && \ ${find} ${ROOTDIR}usr/src/linux/modules -name autod.o -o -name soundx.o \ 2> /dev/null && \ ${find} ${ROOTDIR}usr/bin -name gib -o -name ct -o -name snick -o -name kfl 2> /dev/null` BACKDOORS="number.cgi void.cgi psid becys.cgi nobody.cgi bash.zk.cgi alya.cgi \ shell.cgi alin.cgi httpd.cgi linux.cgi sh.cgi take.cgi bogus.cgi alia.cgi all4one.cgi \ zxcvbnm.cgi secure.cgi ubb.cgi" files="" for j in ${CGIDIR}; do for i in ${BACKDOORS}; do [ -f ${j}/${i} ] && files="${files} ${j}/${i}" done done if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### Ducoci rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for Ducoci rootkit... "; fi files=`${find} . ${CGIDIR} -name last.cgi` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### Adore Worm if [ "${QUIET}" != "t" ]; then printn "Searching for Adore Worm... "; fi files=`${find} ${ROOTDIR}usr/lib ${ROOTDIR}usr/bin -name red.tar -o \ -name start.sh -o -name klogd.o -o -name 0anacron-bak -o -name adore` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" files=`${find} ${ROOTDIR}usr/lib/lib ${ROOTDIR}usr/lib/libt 2>/dev/null` [ "${files}" != "" ] && echo ${files} fi ### ShitC Worm if [ "${QUIET}" != "t" ]; then printn "Searching for ShitC Worm... "; fi files=`${find} ${ROOTDIR}bin -name homo -o -name frgy -o -name dy || \ ${find} ${ROOTDIR}usr/bin -type d -name dir || \ ${find} ${ROOTDIR}usr/sbin -name in.slogind` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### Omega Worm if [ "${QUIET}" != "t" ]; then printn "Searching for Omega Worm... "; fi files=`${find} ${ROOTDIR}dev -name chr` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### China Worm (Sadmind/IIS Worm) if [ "${QUIET}" != "t" ];then printn "Searching for Sadmind/IIS Worm... "; fi files=`${find} ${ROOTDIR}dev/cuc > /dev/null 2>&1` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### MonKit if [ "${QUIET}" != "t" ];then printn "Searching for MonKit... "; fi files=`${find} ${ROOTDIR}lib/defs ${ROOTDIR}usr/lib/libpikapp.a \ > /dev/null 2>&1` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### Showtee if [ "${QUIET}" != "t" ];then printn "Searching for Showtee... "; fi if [ -d ${ROOTDIR}usr/lib/.egcs ] || [ -f ${ROOTDIR}usr/lib/libfl.so ] || \ [ -d ${ROOTDIR}usr/lib/.kinetic ] || [ -d ${ROOTDIR}usr/lib/.wormie ] || \ [ -f ${ROOTDIR}usr/lib/liblog.o ] || [ -f ${ROOTDIR}usr/include/addr.h ] || \ [ -f ${ROOTDIR}usr/include/cron.h ] || [ -f ${ROOTDIR}usr/include/file.h ] || \ [ -f ${ROOTDIR}usr/include/proc.h ] || [ -f ${ROOTDIR}usr/include/syslogs.h ] || \ [ -f ${ROOTDIR}usr/include/chk.h ]; then echo "Warning: Possible Showtee Rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ### OpticKit ### if [ "${QUIET}" != "t" ];then printn "Searching for OpticKit... "; fi files=`${find} ${ROOTDIR}usr/bin/xchk ${ROOTDIR}usr/bin/xsf \ > /dev/null 2>&1` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### T.R.K files="" if [ "${QUIET}" != "t" ];then printn "Searching for T.R.K... "; fi files=`${ROOTDIR}usr/bin -name xchk -o -name xsf >/dev/null 2>&1` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### Mithra's Rootkit files="" if [ "${QUIET}" != "t" ];then printn "Searching for Mithra... "; fi files=`${ROOTDIR}usr/lib/locale -name uboot >/dev/null 2>&1` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### OpenBSD rootkit v1 if [ "${SYSTEM}" != "SunOS" -a ! -f ${ROOTDIR}usr/lib/security/libgcj.security ]; then files="" if [ "${QUIET}" != "t" ];then printn "Searching for OBSD rk v1... "; fi files=`find ${ROOTDIR}usr/lib/security 2>/dev/null` if [ "${files}" = "" -o "${SYSTEM}" = "HP-UX" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi fi ### LOC rootkit files="" if [ "${QUIET}" != "t" ];then printn "Searching for LOC rootkit... "; fi files=`find ${ROOTDIR}tmp -name xp -o -name kidd0.c 2>/dev/null` if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" loc epic epic $pth fi ### Romanian rootkit files="" if [ "${QUIET}" != "t" ];then printn "Searching for Romanian rootkit... "; fi for i in file.h proc.h addr.h syslogs.h; do if [ -f ${ROOTDIR}usr/include/${i} ]; then files="$files ${ROOTDIR}usr/include/$i" fi done if [ "${files}" = "" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi else echo "${files}" fi ### HKRK if [ -f ${ROOTDIR}etc/rc.d/init.d/network ]; then if [ "${QUIET}" != "t" ];then printn "Searching for HKRK rootkit... "; fi if ${egrep} "\.hk" ${ROOTDIR}etc/rc.d/init.d/network 2>/dev/null ; then echo "Warning: /etc/rc.d/init.d/network INFECTED" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi fi ### Suckit if [ -f ${ROOTDIR}sbin/init ]; then if [ "${QUIET}" != "t" ];then printn "Searching for Suckit rootkit... "; fi if [ ${SYSTEM} != "HP-UX" ] && ( ${strings} ${ROOTDIR}sbin/init | ${egrep} HOME || \ cat ${ROOTDIR}/proc/1/maps | ${egrep} "init." ) >/dev/null 2>&1 then echo "Warning: ${ROOTDIR}sbin/init INFECTED" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi fi ### Volc if [ "${QUIET}" != "t" ];then printn "Searching for Volc rootkit... "; fi if [ -f ${ROOTDIR}usr/bin/volc -o -f ${ROOTDIR}usr/lib/volc ] ; then echo "Warning: Possible Volc rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Gold2 if [ "${QUIET}" != "t" ];then printn "Searching for Gold2 rootkit... "; fi if [ -f ${ROOTDIR}usr/bin/ishit ] ; then echo "Warning: Possible Gold2 rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### TC2 Worm if [ "${QUIET}" != "t" ]; then \ printn "Searching for TC2 Worm default files and dirs... "; fi if [ -d ${ROOTDIR}usr/info/.tc2k -o -d ${ROOTDIR}usr/bin/util -o \ -f ${ROOTDIR}usr/sbin/initcheck -o -f ${ROOTDIR}usr/sbin/ldb ] then echo "Possible TC2 Worm installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ANONOYING Rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for Anonoying rootkit default files and dirs... "; fi if [ -f ${ROOTDIR}usr/sbin/mech -o -f ${ROOTDIR}usr/sbin/kswapd ]; then echo "Possible anonoying rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ZK Rootkit if [ "${QUIET}" != "t" ]; then \ printn "Searching for ZK rootkit default files and dirs... "; fi if [ -f ${ROOTDIR}etc/sysconfig/console/load.zk ]; then echo "Possible ZK rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ShKit if [ "${QUIET}" != "t" ]; then printn "Searching for ShKit rootkit default files and dirs... "; fi if [ -f ${ROOTDIR}lib/security/.config -o -f ${ROOTDIR}etc/ld.so.hash ]; then echo "Possible ShKit rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### AjaKit if [ "${QUIET}" != "t" ]; then printn "Searching for AjaKit rootkit default files and dirs... "; fi if [ -d ${ROOTDIR}lib/.ligh.gh -o -d ${ROOTDIR}dev/tux ]; then echo "Possible AjaKit rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### zaRwT if [ "${QUIET}" != "t" ]; then printn "Searching for zaRwT rootkit default files and dirs... "; fi if [ -f ${ROOTDIR}bin/imin -o -f ${ROOTDIR}bin/imout ]; then echo "Possible zaRwT rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Madalin rootkit if [ "${QUIET}" != "t" ]; then printn "Searching for Madalin rootkit default files... "; fi D=${ROOTDIR}usr/include if [ -f $D/icekey.h -o -f $D/iceconf.h -o -f $D/iceseed.h ]; then echo "Possible Madalin rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### Fu rootkit if [ "${QUIET}" != "t" ]; then printn "Searching for Fu rootkit default files... "; fi if [ -f ${ROOTDIR}sbin/xc -o -f ${ROOTDIR}bin/.lib -o \ -f ${ROOTDIR}usr/include/ivtype.h ]; then echo "Possible Fu rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ### ESRK if [ "${QUIET}" != "t" ]; then printn "Searching for ESRK rootkit default files... "; fi if [ -d "${ROOTDIR}usr/lib/tcl5.3" ]; then echo "Possible ESRK rootkit installed" else if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi ## rootedoor if [ "${QUIET}" != "t" ]; then printn "Searching for rootedoor... "; fi found=0 for i in `$echo $PATH|tr -s ':' ' '`; do if [ -f "${ROOTDIR}${i}/rootedoor" ]; then echo "Possible rootedoor installed in ${ROOTDIR}${i}" found=1 fi done [ "${found}" = "0" ] &&\ if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi ### ### shell history anomalies ### if [ "${QUIET}" != "t" ]; then \ printn "Searching for anomalies in shell history files... "; fi files="" if [ ! -z "${SHELL}" -a ! -z "${HOME}" ]; then files=`${find} ${ROOTDIR}${HOME} -name '.*history' -size 0` [ ! -z "${files}" ] && \ echo "Warning: \`${files}' file size is zero" files=`${find} ${ROOTDIR}${HOME} -name '.*history' \( -links 2 -o -type l \)` [ ! -z "${files}" ] && \ echo "Warning: \`${files}' is linked to another file" fi if [ -z "${files}" ]; then if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi fi } ###################################################################### # util functions # our which(1) loc () { ### usage: loc filename filename_to_return_if_nothing_was_found path thing=$1 shift dflt=$1 shift for dir in $*; do case "$thing" in .) if test -d $dir/$thing; then echo $dir exit 0 fi ;; *) for thisthing in $dir/$thing; do : done if test -f $thisthing; then echo $thisthing exit 0 fi ;; esac done if [ "${ROOTDIR}" = "/" ]; then echo ${dflt} else echo "${ROOTDIR}${dflt}" fi exit 1 } getCMD() { RUNNING=`${ps} ${ps_cmd} | ${egrep} "${L_REGEXP}${1}${R_REGEXP}" | \ ${egrep} -v egrep | ${egrep} -v chkrootkit | _head -1 | \ ${awk} '{ print $5 }'` for i in ${ROOTDIR}${RUNNING} ${ROOTDIR}usr/sbin/${1} `loc ${1} ${1} $pth` do CMD="${i}" if [ -r "${i}" ] then return 0 fi done return 1 } expertmode_output() { echo "###" echo "### Output of: $1" echo "###" eval $1 2>&1 # cat <&1` #EOF return 0 } tnfs () { ## Check if -fstype nfs works findargs="" if find /etc -maxdepth 0 >/dev/null 2>&1; then find /etc ! -fstype nfs -maxdepth 0 >/dev/null 2>&1 && \ findargs="! -fstype nfs " elif find /etc -prune > /dev/null 2>&1; then find /etc ! -fstype nfs -prune > /dev/null 2>&1 && \ findargs="! -fstype nfs " fi } ###################################################################### # trojan functions chk_chfn () { STATUS=${NOT_INFECTED} CMD=`loc chfn chfn $pth` [ ${?} -ne 0 ] && return ${NOT_FOUND} if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi case "${SYSTEM}" in Linux) if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi;; FreeBSD) [ `echo $V | awk '{ if ( $1 >= 5.0) print 1; else print 0 }'` -eq 1 ] && n=1 || n=2 if [ `${strings} -a ${CMD} | \ ${egrep} -c "${GENERIC_ROOTKIT_LABEL}"` -ne $n ] then STATUS=${INFECTED} fi;; esac return ${STATUS} } chk_chsh () { STATUS=${NOT_INFECTED} CMD=`loc chsh chsh $pth` [ ${?} -ne 0 ] && return ${NOT_FOUND} REDHAT_PAM_LABEL="*NOT*" if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi case "${SYSTEM}" in Linux) if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" \ >/dev/null 2>&1 then if ${strings} -a ${CMD} | ${egrep} "${REDHAT_PAM_LABEL}" \ >/dev/null 2>&1 then : else STATUS=${INFECTED} fi fi;; FreeBSD) [ `echo $V | awk '{ if ($1 >= 5.0) print 1; else print 0}'` -eq 1 ] && n=1 || n=2 if [ `${strings} -a ${CMD} | ${egrep} -c "${GENERIC_ROOTKIT_LABEL}"` -ne $n ] then STATUS=${INFECTED} fi;; esac return ${STATUS} } chk_login () { STATUS=${NOT_INFECTED} CMD=`loc login login $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if [ "$SYSTEM" = "SunOS" ]; then TROJED_L_L="porcao|/bin/xstat" if ${strings} -a ${CMD} | ${egrep} "${TROJED_L_L}" >/dev/null 2>&1 ]; then return ${INFECTED} else return ${NOT_TESTED} fi fi GENERAL="^root$" TROJED_L_L="vejeta|^xlogin|^@\(#\)klogin\.c|lets_log|sukasuka|/usr/lib/.ark?|SucKIT" ret=`${strings} -a ${CMD} | ${egrep} -c "${GENERAL}"` if [ ${ret} -gt 0 ]; then case ${ret} in 1) [ "${SYSTEM}" = "OpenBSD" -a `echo $V | ${awk} '{ if ($1 < 2.7 || $1 >= 3.0) print 1; else print 0}'` -eq 1 ] && \ STATUS=${NOT_INFECTED} || STATUS=${INFECTED};; 2) [ "${SYSTEM}" = "FreeBSD" -o ${SYSTEM} = "NetBSD" -o ${SYSTEM} = \ "OpenBSD" -a `echo ${V} | ${awk} '{ if ($1 >= 2.8) print 1; else print 0 }'` -eq 1 ] && STATUS=${NOT_INFECTED} || STATUS=${INFECTED};; 7) [ "${SYSTEM}" = "HP-UX" ] && STATUS=${NOT_INFECTED} || STATUS=${INFECTED};; *) STATUS=${INFECTED};; esac fi if ${strings} -a ${CMD} | ${egrep} "${TROJED_L_L}" 2>&1 >/dev/null then STATUS=${INFECTED} fi return ${STATUS} } chk_passwd () { STATUS=${NOT_INFECTED} CMD=`loc passwd passwd $pth` if [ ! -x ${CMD} -a -x ${ROOTDIR}usr/bin/passwd ]; then CMD="${ROOTDIR}usr/bin/passwd" fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" fi if [ "${SYSTEM}" = "OpenBSD" -o "${SYSTEM}" = "SunOS" -o "${SYSTEM}" \ = "HP-UX" ] then return ${NOT_TESTED} fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}|/lib/security" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_inetd () { STATUS=${NOT_INFECTED} getCMD 'inetd' if [ ! -r ${CMD} -o ${CMD} = '/' ] then return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_syslogd () { STATUS=${NOT_INFECTED} SYSLOG_I_L="/usr/lib/pt07|/dev/pty[pqrs]|/dev/hd[als][0-7]|/dev/ddtz1|/dev/ptyxx|/dev/tux|syslogs\.h" CMD=`loc syslogd syslogd $pth` if [ ! -r ${CMD} ] then return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${SYSLOG_I_L}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_hdparm () { STATUS=${NOT_INFECTED} HDPARM_INFECTED_LABEL="/dev/ida" CMD=`loc hdparm hdparm $pth` if [ ! -r ${CMD} ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${HDPARM_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_gpm () { STATUS=${NOT_INFECTED} GPM_INFECTED_LABEL="mingetty" CMD=`loc gpm gpm $pth` if [ ! -r ${CMD} ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GPM_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_mingetty () { STATUS=${NOT_INFECTED} MINGETTY_INFECTED_LABEL="Dimensioni|pacchetto" CMD=`loc mingetty mingetty $pth` if [ ! -r ${CMD} ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${MINGETTY_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_sendmail () { STATUS=${NOT_INFECTED} SENDMAIL_INFECTED_LABEL="fuck" CMD=`loc sendmail sendmail $pth` if [ ! -r ${CMD} ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${SENDMAIL_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_ls () { STATUS=${NOT_INFECTED} LS_INFECTED_LABEL="/dev/ttyof|/dev/pty[pqrs]|/dev/hdl0|\.tmp/lsfile|/dev/hdcc|/dev/ptyxx|duarawkz|^/prof|/dev/tux|/security|file\.h" CMD=`loc ls ls $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${LS_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_du () { STATUS=${NOT_INFECTED} DU_INFECTED_LABEL="/dev/ttyof|/dev/pty[pqrsx]|w0rm|^/prof|/dev/tux|file\.h" CMD=`loc du du $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${DU_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_named () { STATUS=${NOT_INFECTED} NAMED_I_L="blah|bye" CMD=`loc named named $pth` if [ ! -r "${CMD}" ]; then CMD=`loc in.named in.named $pth` if [ ! -r "${CMD}" ]; then return ${NOT_FOUND} fi fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${NAMED_I_L}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_netstat () { STATUS=${NOT_INFECTED} NETSTAT_I_L="/dev/hdl0/dev/xdta|/dev/ttyoa|/dev/pty[pqrsx]|/dev/cui|/dev/hdn0|/dev/cui221|/dev/dszy|/dev/ddth3|/dev/caca|^/prof|/dev/tux|grep|addr\.h" CMD=`loc netstat netstat $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${NETSTAT_I_L}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_ps () { STATUS=${NOT_INFECTED} PS_I_L="/dev/xmx|\.1proc|/dev/ttyop|/dev/pty[pqrsx]|/dev/cui|/dev/hda[0-7]|\ /dev/hdp|/dev/cui220|/dev/dsx|w0rm|/dev/hdaa|duarawkz|/dev/tux|/security|proc\.h" CMD=`loc ps ps $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${PS_I_L}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_pstree () { STATUS=${NOT_INFECTED} PSTREE_INFECTED_LABEL="/dev/ttyof|/dev/hda01|/dev/cui220|/dev/ptyxx|^/prof|/dev/tux|proc\.h" CMD=`loc pstree pstree $pth` if [ ! -r "${CMD}" ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${PSTREE_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_top () { STATUS=${NOT_INFECTED} TOP_INFECTED_LABEL="/dev/xmx|/dev/ttyop|/dev/pty[pqrsx]|/dev/hdp|/dev/dsx|^/prof/|/dev/tux|^/proc\.h" CMD=`loc top top $pth` if [ ! -r ${CMD} ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${TOP_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_pidof () { STATUS=${NOT_INFECTED} TOP_INFECTED_LABEL="/dev/pty[pqrs]" CMD=`loc pidof pidof $pth` if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${TOP_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_killall () { STATUS=${NOT_INFECTED} TOP_INFECTED_LABEL="/dev/ttyop|/dev/pty[pqrs]|/dev/hda[0-7]|/dev/hdp|/dev/ptyxx|/dev/tux|proc\.h" CMD=`loc killall killall $pth` if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${TOP_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_ldsopreload() { STATUS=${NOT_INFECTED} CMD="${ROOTDIR}lib/libshow.so ${ROOTDIR}lib/libproc.a" if [ "${SYSTEM}" = "Linux" ] then if [ ! -x ./strings-static ]; then printn "can't exec ./strings-static, " return ${NOT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "./strings-static -a ${CMD}" return 5 fi ### strings must be a statically linked binary. if ./strings-static -a ${CMD} > /dev/null 2>&1 then STATUS=${INFECTED} fi else STATUS=${NOT_TESTED} fi return ${STATUS} } chk_basename () { STATUS=${NOT_INFECTED} CMD=`loc basename basename $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi [ "$SYSTEM" != "OSF1" ] && { if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi } return ${STATUS} } chk_dirname () { STATUS=${NOT_INFECTED} CMD=`loc dirname dirname $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_traceroute () { STATUS=${NOT_INFECTED} CMD=`loc traceroute traceroute $pth` if [ ! -r "${CMD}" ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_rpcinfo () { STATUS=${NOT_INFECTED} CMD=`loc rpcinfo rpcinfo $pth` if [ ! -r "${CMD}" ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_date () { STATUS=${NOT_INFECTED} S_L="/bin/.*sh" CMD=`loc date date $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi [ "${SYSTEM}" = "FreeBSD" -a `echo $V | ${awk} '{ if ($1 > 4.9) print 1; else print 0 }'` -eq 1 ] && { N=`${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" | \ ${egrep} -c "$S_L"` if [ ${N} -ne 2 -a ${N} -ne 0 ]; then STATUS=${INFECTED} fi } || { if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" 2>&1 then STATUS=${INFECTED} fi } if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_echo () { STATUS=${NOT_INFECTED} CMD=`loc echo echo $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_env () { STATUS=${NOT_INFECTED} CMD=`loc env env $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_timed () { STATUS=${NOT_INFECTED} CMD=`loc timed timed $pth` if [ ${?} -ne 0 ]; then CMD=`loc in.timed in.timed $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_identd () { STATUS=${NOT_INFECTED} CMD=`loc in.identd in.identd $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_init () { STATUS=${NOT_INFECTED} INIT_INFECTED_LABEL="UPX" CMD=`loc init init $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${INIT_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_pop2 () { STATUS=${NOT_INFECTED} CMD=`loc in.pop2d in.pop2d $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_pop3 () { STATUS=${NOT_INFECTED} CMD=`loc in.pop3d in.pop3d $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_write () { STATUS=${NOT_INFECTED} CMD=`loc write write $pth` WRITE_ROOTKIT_LABEL="bash|elite$|vejeta|\.ark" if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${WRITE_ROOTKIT_LABEL}" | grep -v locale > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_w () { STATUS=${NOT_INFECTED} CMD=`loc w w $pth` W_INFECTED_LABEL="uname -a" if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${W_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_vdir () { STATUS=${NOT_INFECTED} CMD=`loc vdir vdir $pth` VDIR_INFECTED_LABEL="/lib/volc" if [ ! -r ${CMD} ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${VDIR_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_tar () { STATUS=${NOT_INFECTED} CMD=`loc tar tar $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${ls} -l ${CMD}" return 5 fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } rexedcs () { STATUS=${NOT_INFECTED} CMD=`loc in.rexedcs in.rexedcs $pth` if [ "${?}" -ne 0 ] then if [ "${QUIET}" != "t" ]; then echo "not found"; fi return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi STATUS=${INFECTED} return ${STATUS} } chk_mail () { STATUS=${NOT_INFECTED} CMD=`loc mail mail $pth` if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi [ "${SYSTEM}" = "HP-UX" ] && return $NOT_TESTED MAIL_INFECTED_LABEL="sh -i" if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${MAIL_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_biff () { STATUS=${NOT_INFECTED} CMD=`loc biff biff $pth` if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GENERIC_ROOTKIT_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_egrep () { STATUS=${NOT_INFECTED} EGREP_INFECTED_LABEL="blah" CMD=`loc egrep egrep $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${EGREP_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_grep () { STATUS=${NOT_INFECTED} GREP_INFECTED_LABEL="givemer" CMD=`loc grep grep $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" expertmode_output "${ls} -l ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${GREP_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_find () { STATUS=${NOT_INFECTED} FIND_INFECTED_LABEL="/dev/ttyof|/dev/pty[pqrs]|^/prof|/home/virus|/security|file\.h" CMD=`loc find find $pth` if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${FIND_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_rlogind () { STATUS=${NOT_INFECTED} RLOGIN_INFECTED_LABEL="p1r0c4|r00t" CMD=`loc in.rlogind in.rlogind $pth` if [ ! -x "${CMD}" ]; then CMD=`loc rlogind rlogind $pth` if [ ! -x "${CMD}" ]; then return ${NOT_FOUND} fi fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${RLOGIN_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_lsof () { STATUS=${NOT_INFECTED} LSOF_INFECTED_LABEL="^/prof" CMD=`loc lsof lsof $pth` if [ ! -x "${CMD}" ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${LSOF_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_amd () { STATUS=${NOT_INFECTED} AMD_INFECTED_LABEL="blah" CMD=`loc amd amd $pth` if [ ! -x "${CMD}" ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${AMD_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_slogin () { STATUS=${NOT_INFECTED} SLOGIN_INFECTED_LABEL="homo" CMD=`loc slogin slogin $pth` if [ ! -x "${CMD}" ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${SLOGIN_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_cron () { STATUS=${NOT_INFECTED} CRON_INFECTED_LABEL="/dev/hda|/dev/hda[0-7]|/dev/hdc0" CMD=`loc cron cron $pth` if [ "${?}" -ne 0 ]; then CMD=`loc crond crond $pth` fi if [ "${?}" -ne 0 ] then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${CRON_INFECTED_LABEL}" >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_ifconfig () { STATUS=${INFECTED} CMD=`loc ifconfig ifconfig $pth` if [ "${?}" -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi IFCONFIG_NOT_INFECTED_LABEL="PROMISC" IFCONFIG_INFECTED_LABEL="/dev/tux|/session.null" if ${strings} -a ${CMD} | ${egrep} "${IFCONFIG_NOT_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${NOT_INFECTED} fi if ${strings} -a ${CMD} | ${egrep} "${IFCONFIG_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_rshd () { STATUS=${NOT_INFECTED} case "${SYSTEM}" in Linux) CMD="${ROOTDIR}usr/sbin/in.rshd";; FreeBSD) CMD="${ROOTDIR}usr/libexec/rshd";; *) CMD=`loc rshd rshd $pth`;; esac if [ ! -x ${CMD} ] ;then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi RSHD_INFECTED_LABEL="HISTFILE" if ${strings} -a ${CMD} | ${egrep} "${RSHD_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} if ${egrep} "^#.*rshd" ${ROOTDIR}etc/inetd.conf >/dev/null 2>&1 -o \ ${ls} ${ROOTDIR}etc/xinetd.d/rshd >/dev/null 2>&1 ; then STATUS=${INFECTED_BUT_DISABLED} fi fi return ${STATUS} } chk_tcpdump () { STATUS=${NOT_INFECTED} TCPDUMP_I_L="212.146.0.34:1963"; OPT=-an if ${netstat} "${OPT}" | ${egrep} "${TCPDUMP_I_L}"> /dev/null 2>&1; then STATUS=${INFECTED} fi return ${STATUS} } chk_tcpd () { STATUS=${NOT_INFECTED} TCPD_INFECTED_LABEL="p1r0c4|hack|/dev/xmx|/dev/hdn0|/dev/xdta|/dev/tux" [ -r ${ROOTDIR}etc/inetd.conf ] && CMD=`${egrep} '^[^#].*tcpd' ${ROOTDIR}etc/inetd.conf | _head -1 | \ ${awk} '{ print $6 }'` if ${ps} auwx | ${egrep} xinetd | ${egrep} -v grep >/dev/null 2>&1; then CMD=`loc tcpd tcpd $pth` fi [ -z "${CMD}" ] && CMD=`loc tcpd tcpd $pth` [ "tcpd" = "${CMD}" ] && return ${NOT_FOUND}; if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${TCPD_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_sshd () { STATUS=${NOT_INFECTED} SSHD2_INFECTED_LABEL="check_global_passwd|panasonic|satori|vejeta|\.ark|/hash\.zk" getCMD 'sshd' if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${SSHD2_INFECTED_LABEL}" \ > /dev/null 2>&1 then STATUS=${INFECTED} if ${ps} ${ps_cmd} | ${egrep} sshd >/dev/null 2>&1; then STATUS=${INFECTED_BUT_DISABLED} fi fi return ${STATUS} } chk_su () { STATUS=${NOT_INFECTED} SU_INFECTED_LABEL="satori|vejeta|conf\.inv" CMD=`loc su su $pth` if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${SU_INFECTED_LABEL}" > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_fingerd () { STATUS=${NOT_INFECTED} FINGER_INFECTED_LABEL="cterm100|${GENERIC_ROOTKIT_LABEL}" CMD=`loc fingerd fingerd $pth` if [ ${?} -ne 0 ]; then CMD=`loc in.fingerd in.fingerd $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${FINGER_INFECTED_LABEL}" \ > /dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } chk_inetdconf () { STATUS=${NOT_INFECTED} SHELLS="${ROOTDIR}bin/sh ${ROOTDIR}bin/bash" if [ -r ${ROOTDIR}etc/shells ]; then SHELLS="`cat ${ROOTDIR}etc/shells | ${egrep} -v '^#'`"; fi if [ -r ${ROOTDIR}etc/inetd.conf ]; then for SHELL in ${SHELLS}; do cat ${ROOTDIR}etc/inetd.conf | ${egrep} -v "^#" | ${egrep} "^.*stream.*tcp.*nowait.*$SHELL.*" > /dev/null if [ ${?} -ne 1 ]; then if [ "${EXPERT}" = "t" ]; then echo "Backdoor shell record(s) in /etc/inetd.conf: " cat ${ROOTDIR}etc/inetd.conf | ${egrep} -v "^#" | ${egrep} "^.*stream.*tcp.*nowait.*$SHELL.*" fi STATUS=${INFECTED} fi done return ${STATUS} else return ${NOT_FOUND} fi } chk_telnetd () { STATUS=${NOT_INFECTED} TELNETD_INFECTED_LABEL='cterm100|vt350|VT100|ansi-term|/dev/hda[0-7]' CMD=`loc telnetd telnetd $pth` if [ ${?} -ne 0 ]; then CMD=`loc in.telnetd in.telnetd $pth` if [ ${?} -ne 0 ]; then return ${NOT_FOUND} fi fi if [ "${EXPERT}" = "t" ]; then expertmode_output "${strings} -a ${CMD}" return 5 fi if ${strings} -a ${CMD} | ${egrep} "${TELNETD_INFECTED_LABEL}" \ >/dev/null 2>&1 then STATUS=${INFECTED} fi return ${STATUS} } printn () { if `${echo} "a\c" | ${egrep} c >/dev/null 2>&1` ; then ${echo} -n "$1" else ${echo} "${1}\c" fi } # main # ### using regexps, as the `-w' option to grep/egrep is not portable. L_REGEXP='(^|[^A-Za-z0-9_])' R_REGEXP='([^A-Za-z0-9_]|$)' ### default ROOTDIR is "/" ROOTDIR='/' while : do case $1 in -r) shift ROOTDIR=$1;; -p) shift CHKRKPATH=$1;; -d) DEBUG=t;; -x) EXPERT=t;; -q) QUIET=t;; -V) echo >&2 "chkrootkit version ${CHKROOTKIT_VERSION}" exit 1;; -l) echo >&2 "$0: tests: ${TOOLS} ${TROJAN}" exit 1;; -n) tnfs;; -h | -*) echo >&2 "Usage: $0 [options] [test ...] Options: -h show this help and exit -V show version information and exit -l show available tests and exit -d debug -q quiet mode -x expert mode -r dir use dir as the root directory -p dir1:dir2:dirN path for the external commands used by chkrootkit -n skip NFS mounted dirs" exit 1;; *) break esac shift done ### check the external commands needed cmdlist=" awk cut echo egrep find head id ls netstat ps sed strings uname " ### PATH used by loc pth=`echo $PATH | sed -e "s/:/ /g"` pth="$pth /sbin /usr/sbin /lib /usr/lib /usr/libexec ." ### external command's PATH if [ "${CHKRKPATH}" = "" ]; then chkrkpth=${pth} else ### use the path provided with the -p option chkrkpth=`echo ${CHKRKPATH} | sed -e "s/:/ /g"` fi echo=echo for file in $cmdlist; do xxx=`loc $file $file $chkrkpth` eval $file=$xxx case "$xxx" in /* | ./* | ../*) if [ ! -x "${xxx}" ] then echo >&2 "chkrootkit: can't exec \`$xxx'." exit 1 fi ;; *) echo >&2 "chkrootkit: can't find \`$file'." exit 1 ;; esac done SYSTEM=`${uname} -s` VERSION=`${uname} -r` if [ "${SYSTEM}" != "FreeBSD" -a ${SYSTEM} != "OpenBSD" ] ; then V=4.4 else V=`echo $VERSION| ${sed} -e 's/[-_@].*//'| ${awk} -F . '{ print $1 "." $2 $3 }'` fi # head command _head() { if `$echo a | $head -n 1 >/dev/null 2>&1` ; then $head -n `echo $1 | tr -d "-"` else $head $1 fi } # ps command ps_cmd="ax" if [ "$SYSTEM" = "SunOS" ]; then if [ "${CHKRKPATH}" = "" ]; then if [ -x /usr/ucb/ps ]; then ps="/usr/ucb/ps" else ps_cmd="-fe" fi else ### -p is in place: use `-fe' as ps options ps_cmd="-fe" fi fi # Check if ps command is ok if ${ps} ax >/dev/null 2>&1 ; then ps_cmd="ax" else ps_cmd="-fe" fi if [ `${id} | ${cut} -d= -f2 | ${cut} -d\( -f1` -ne 0 ]; then echo "$0 need root privileges" exit 1 fi if [ $# -gt 0 ] then ### perform only tests supplied as arguments for arg in $* do ### check if is a valid test name if echo "${TROJAN} ${TOOLS}"| \ ${egrep} -v "${L_REGEXP}$arg${R_REGEXP}" > /dev/null 2>&1 then echo >&2 "$0: \`$arg': not a known test" exit 1 fi done LIST=$* else ### this is the default: perform all tests LIST="${TROJAN} ${TOOLS}" fi if [ "${DEBUG}" = "t" ]; then set -x fi if [ "${ROOTDIR}" != "/" ]; then ### remove trailing `/' ROOTDIR=`echo ${ROOTDIR} | ${sed} -e 's/\/*$//g'` for dir in ${pth} do if echo ${dir} | ${egrep} '^/' > /dev/null 2>&1 then newpth="${newpth} ${ROOTDIR}${dir}" else newpth="${newpth} ${ROOTDIR}/${dir}" fi done pth=${newpth} ROOTDIR="${ROOTDIR}/" fi if [ "${QUIET}" != "t" ]; then echo "ROOTDIR is \`${ROOTDIR}'" fi for cmd in ${LIST} do if echo "${TROJAN}" | \ ${egrep} "${L_REGEXP}$cmd${R_REGEXP}" > /dev/null 2>&1 then if [ "${EXPERT}" != "t" -a "${QUIET}" != "t" ]; then printn "Checking \`${cmd}'... " fi chk_${cmd} STATUS=$? ### quiet mode if [ "${QUIET}" = "t" ]; then ### show only INFECTED status if [ ${STATUS} -eq 0 ]; then echo "Checking \`${cmd}'... INFECTED" fi continue fi case $STATUS in 0) echo "INFECTED";; 1) echo "not infected";; 2) echo "not tested";; 3) echo "not found";; 4) echo "infected but disabled";; 5) ;; ### expert mode esac else ### external tool if [ "${EXPERT}" != "t" -a "${QUIET}" != "t" ]; then printn "Checking \`$cmd'... " fi ${cmd} fi done ### chkrootkit ends here. chkrootkit-0.46a/chkutmp.c010044400017500001750000000126421032550146400152100ustar00jessenjessen/* * 2004/09/23 - Jeremy Miller * * This utility compares the output from the ps command and tries to find * a matching entry bound to the same tty in the utmp login records. The * idea is to display users that may have wiped themselves from the utmp * log. When analyzing a compromised box, it is assumed you have the * path to a known good 'ps' binary in your PATH. * * LICENSE: This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Changelog: * Ighighi X - Improved speed via break command - 2005/03/27 * */ #if !defined(__sun) && !defined(__linux__) int main () { return 0; } #else #include #include #include #include #include #include #if defined(__sun) #include #else #include #endif #include #define MAXREAD 1024 #define MAXBUF 4096 #define MAXLENGTH 256 #define UT_PIDSIZE 12 #if defined(__sun) #define UTMP "/var/adm/utmpx" #define UT_LINESIZE 12 #define UT_NAMESIZE 8 #define PS_CMD 0 #else #define PS_CMD 1 #define UTMP "/var/run/utmp" #endif struct ps_line { char ps_tty[UT_LINESIZE]; char ps_user[UT_NAMESIZE]; char ps_args[MAXLENGTH]; int ps_pid; }; struct utmp_line { char ut_tty[UT_LINESIZE]; int ut_pid; int ut_type; }; static char *cmd[] = { "ps -ef -o \"tty,pid,ruser,args\"", /* solaris */ "ps ax -o \"tty,pid,ruser,args\"" /* linux */ }; int fetchps(struct ps_line *); int fetchutmp(struct utmp_line *); int fetchps(struct ps_line *psl_p) { FILE *ps_fp; char line[MAXREAD + 1], pid[UT_PIDSIZE]; char *s, *d; struct ps_line *curp = &psl_p[0]; struct ps_line *endp = &psl_p[MAXBUF]; int i, x; i = 0; if ((ps_fp = (popen(cmd[PS_CMD], "r"))) != NULL) { fgets(line, MAXREAD, ps_fp); /* skip header */ while (fgets(line, MAXREAD, ps_fp)) { s = line; if (*s != '\?' && curp <= endp) { /* only interested in lines that * have a tty */ d = curp->ps_tty; for (x = 0; (!isspace(*s)) && (*d++ = *s++) && x <= UT_LINESIZE; x++) /* grab tty */ ; *d = '\0'; while (isspace(*s)) /* skip spaces */ s++; d = pid; for (x = 0; (!isspace(*s)) && (*d++ = *s++) && x <= UT_LINESIZE; x++) /* grab pid */ ; *d = '\0'; curp->ps_pid = atoi(pid); while (isspace(*s)) /* skip spaces */ s++; d = curp->ps_user; for (x = 0; (!isspace(*s)) && (*d++ = *s++) && x <= UT_NAMESIZE; x++) /* grab user */ ; *d = '\0'; d = curp->ps_args; while (isspace(*s)) /* skip spaces */ s++; for (x = 0; (*d++ = *s++) && x <= MAXLENGTH; x++) /* cmd + args */ ; i++; curp++; } } pclose(ps_fp); } else { fprintf(stderr, "\nfailed running 'ps' !\n"); exit(EXIT_FAILURE); } return i; } int fetchutmp(struct utmp_line *utl_p) { #if defined(__sun) struct utmpx ut; #else struct utmp ut; #endif struct utmp_line *curp = &utl_p[0]; struct utmp_line *endp = &utl_p[MAXBUF]; int i, f, del_cnt, sz_ut; i = del_cnt = 0; if ((f = open(UTMP, O_RDONLY)) > 0) { #if defined(__sun) sz_ut = sizeof(struct utmpx); #else sz_ut = sizeof(struct utmp); #endif while (read(f, &ut, sz_ut) > 0 && curp <= endp) { #if !defined(__sun) if (ut.ut_time == 0) del_cnt++; /* ut_time shouldn't be zero */ #endif if (strlen(ut.ut_user) > 0) { strncpy(curp->ut_tty, ut.ut_line, UT_LINESIZE); curp->ut_pid = ut.ut_pid; curp->ut_type = ut.ut_type; i++; curp++; } } close(f); if (del_cnt > 0) printf("=> possibly %d deletion(s) detected in %s !\n", del_cnt, UTMP); } else { fprintf(stderr, "\nfailed opening utmp !\n"); exit(EXIT_FAILURE); } return i; } int main(int argc, char *argv[]) { struct ps_line ps_l[MAXBUF]; /* array of data from 'ps' */ struct utmp_line ut_l[MAXBUF]; /* array of data from utmp log */ int h, i, y, z, mtch_fnd, hdr_prntd; y = fetchps(ps_l); z = fetchutmp(ut_l); hdr_prntd = 0; for (h = 0; h <= y; h++) { /* loop through 'ps' data */ mtch_fnd = 0; for (i = 0; i <= z; i++) { /* try and match the tty from 'ps' to one in utmp */ if (ut_l[i].ut_type == LOGIN_PROCESS /* ignore getty processes with matching pid from 'ps' */ && ut_l[i].ut_pid == ps_l[h].ps_pid) { mtch_fnd = 1; break; } else if (strncmp(ps_l[h].ps_tty, ut_l[i].ut_tty, /* compare the tty's */ strlen(ps_l[h].ps_tty)) == 0) { mtch_fnd = 1; break; } } if (!mtch_fnd) { if (!hdr_prntd) { printf (" The tty of the following user process(es) were not found\n"); printf(" in %s !\n", UTMP); printf("! %-9s %7s %-6s %s\n", "RUID", "PID", "TTY", "CMD"); hdr_prntd = 1; } printf("! %-9s %7d %-6s %s", ps_l[h].ps_user, ps_l[h].ps_pid, ps_l[h].ps_tty, ps_l[h].ps_args); } } exit(EXIT_SUCCESS); } #endif chkrootkit-0.46a/chkwtmp.c010044400017500001750000000042401032550146400152050ustar00jessenjessen/* Copyright (c) DFN-CERT, Univ. of Hamburg 1994 Univ. Hamburg, Dept. of Computer Science DFN-CERT Vogt-Koelln-Strasse 30 22527 Hamburg Germany 02/20/97 - Minimal changes for Linux/FreeBSD port. Nelson Murilo, nelson@pangeia.com.br 09/07/00 - Ports for Solaris Andre Gustavo 12/15/00 - Add -f option Nelson Murilo, nelson@pangeia.com.br 07/08/04 - fix del counter value (Thanks to Dietrich Raisin) Nelson Murilo, nelson@pangeia.com.br 09/12/05 - fix Segfault (Thanks to Jérémie Andréi) Nelson Murilo, nelson@pangeia.com.br */ #include #include #include #include #include #include #include #ifdef SOLARIS2 #include #endif #ifdef __FreeBSD__ #define WTMP_FILENAME "/var/log/wtmp" #else #ifndef WTMP_FILENAME #define WTMP_FILENAME "/var/adm/wtmp" #endif #endif void printit(counter, start, end) int counter; long start,end; { char buffer[30]; printf("%d deletion(s) between ", counter); strcpy(buffer, ctime( (time_t *) &start)); buffer[24]='\0'; printf("%s and %s", buffer, ctime( (time_t *) &end)); } int main(int argc, char*argv[]) { int filehandle; struct utmp utmp_ent; struct timeval mytime; struct timezone dummy; long start_time, act_time; int del_counter, t_del; char wtmpfile[128]; del_counter=t_del=0; start_time=0; gettimeofday(&mytime, &dummy); act_time=mytime.tv_sec; wtmpfile[127]='\0'; memcpy(wtmpfile, WTMP_FILENAME, 127); if ( argc == 3 && !memcmp("-f", argv[1], 2) && *argv[2]) memcpy(wtmpfile, argv[2], 127); if ((filehandle=open(wtmpfile,O_RDONLY)) < 0) { fprintf(stderr, "unable to open wtmp-file %s\n", wtmpfile); return(2); } while (read (filehandle, (char *) &utmp_ent, sizeof (struct utmp)) > 0) { if (utmp_ent.ut_time == 0) del_counter++; else { if (del_counter) { printit(del_counter, start_time, utmp_ent.ut_time); t_del++; del_counter=0; } start_time=utmp_ent.ut_time; } } close(filehandle); if (del_counter) printit(del_counter, start_time, act_time); exit(t_del+del_counter); } chkrootkit-0.46a/README010044400017500001750000000322671033044113300142460ustar00jessenjessen chkrootkit V. 0.46a Nelson Murilo (main author) Klaus Steding-Jessen (co-author) This program locally checks for signs of a rootkit. chkrootkit is available at: http://www.chkrootkit.org/ No illegal activities are encouraged! I'm not responsible for anything you may do with it. This tool includes software developed by the DFN-CERT, Univ. of Hamburg (chklastlog and chkwtmp), and small portions of ifconfig developed by Fred N. van Kempen, . 1. What's chkrootkit? --------------------- chkrootkit is a tool to locally check for signs of a rootkit. It contains: * chkrootkit: a shell script that checks system binaries for rootkit modification. * ifpromisc.c: checks if the network interface is in promiscuous mode. * chklastlog.c: checks for lastlog deletions. * chkwtmp.c: checks for wtmp deletions. * check_wtmpx.c: checks for wtmpx deletions. (Solaris only) * chkproc.c: checks for signs of LKM trojans. * chkdirs.c: checks for signs of LKM trojans. * strings.c: quick and dirty strings replacement. * chkutmp.c: checks for utmp deletions. chkwtmp and chklastlog *try* to check for deleted entries in the wtmp and lastlog files, but it is *not* guaranteed that any modification will be detected. Aliens tries to find sniffer logs and rootkit config files. It looks for some default file locations -- so it is also not guaranteed it will succeed in all cases. chkproc checks if /proc entries are hidden from ps and the readdir system call. This could be the indication of a LKM trojan. You can also run this command with the -v option (verbose). 2. Rootkits, Worms and LKMs detected ------------------------------------ For an updated list of rootkits, worms and LKMs detected by chkrootkit please visit: http://www.chkrootkit.org/ 3. Supported Systems -------------------- chkrootkit has been tested on: Linux 2.0.x, 2.2.x, 2.4.x and 2.6.x, FreeBSD 2.2.x, 3.x, 4.x and 5.x, OpenBSD 2.x and 3.x., NetBSD 1.6.x, Solaris 2.5.1, 2.6, 8.0 and 9.0, HP-UX 11, Tru64, BSDI and Mac OS X. 4. Package Contents ------------------- README README.chklastlog README.chkwtmp COPYRIGHT chkrootkit.lsm Makefile chklastlog.c chkproc.c chkdirs.c chkwtmp.c check_wtmpx.c ifpromisc.c strings.c chkutmp.c chkrootkit 5. Installation --------------- To compile the C programs type: # make sense After that it is ready to use and you can simply type: # ./chkrootkit 6. Usage -------- chkrootkit must run as root. The simplest way is: # ./chkrootkit This will perform all tests. You can also specify only the tests you want, as shown below: Usage: ./chkrootkit [options] [testname ...] Options: -h show this help and exit -V show version information and exit -l show available tests -d debug -q quiet mode -x expert mode -r dir use dir as the root directory -p dir1:dir2:dirN path for the external commands used by chkrootkit -n skip NFS mounted dirs Where testname stands for one or more from the following list: aliens asp bindshell lkm rexedcs sniffer w55808 wted scalper slapper z2 chkutmp amd basename biff chfn chsh cron date du dirname echo egrep env find fingerd gpm grep hdparm su ifconfig inetd inetdconf identd init killall ldsopreload login ls lsof mail mingetty netstat named passwd pidof pop2 pop3 ps pstree rpcinfo rlogind rshd slogin sendmail sshd syslogd tar tcpd tcpdump top telnetd timed traceroute vdir w write For example, the following command checks for trojaned ps and ls binaries and also checks if the network interface is in promiscuous mode. # ./chkrootkit ps ls sniffer The `-q' option can be used to put chkrootkit in quiet mode -- in this mode only output messages with `infected' status are shown. With the `-x' option the user can examine suspicious strings in the binary programs that may indicate a trojan -- all the analysis is left to the user. Lots of data can be seen with: # ./chkrootkit -x | more Pathnames inside system commands: # ./chkrootkit -x | egrep '^/' chkrootkit uses the following commands to make its tests: awk, cut, egrep, find, head, id, ls, netstat, ps, strings, sed, uname. It is possible, with the `-p' option, to supply an alternate path to chkrootkit so it won't use the system's (possibly) compromised binaries to make its tests. To use, for example, binaries in /cdrom/bin: # ./chkrootkit -p /cdrom/bin It is possible to add more paths with a `:' # ./chkrootkit -p /cdrom/bin:/floppy/mybin Sometimes is a good idea to mount the disk from a compromised machine on a machine you trust. Just mount the disk and specify a new rootdir with the `-r' option. For example, suppose the disk you want to check is mounted under /mnt, then: # ./chkrootkit -r /mnt 7. Output Messages ------------------ The following messages are printed by chkrootkit (except with the -x and -q command options) during its tests: "INFECTED": the test has identified a command probably modified by a known rootkit; "not infected": the test didn't find any known rootkit signature. "not tested": the test was not performed -- this could happen in the following situations: a) the test is OS specific; b) the test depends on an external program that is not available; c) some specific command line options are given. (e.g. -r ). "not found": the command to be tested is not available; "Vulnerable but disabled": the command is infected but not in use. (not running or commented in inetd.conf) 8. A trojaned command has been found. What should I do now? ------------------------------------------------------------ Your biggest problem is that your machine has been compromised and this bad guy has root privileges. Maybe you can solve the problem by just replacing the trojaned command -- the best way is to reinstall the machine from a safe media and to follow your vendor's security recommendations. 9. Reports and questions ------------------------ Please send comments, questions and bug reports to nelson@pangeia.com.br and jessen@cert.br. A simple FAQ and Related information about rootkits and security can be found at chkrootkit's homepage, http://www.chkrootkit.org. 10. ACKNOWLEDGMENTS ------------------- See the ACKNOWLEDGMENTS file. 11. ChangeLog ------------- 02/20/1997 - Initial release 02/25/1997 - Version 0.4, formal testing. 03/30/1997 - Version 0.5, suspect files routine added. 06/11/1997 - Version 0.6, minor fixes and Debian compatibility. 06/24/1997 - Version 0.7, FreeBSD compatibility fixed. 08/07/1997 - Version 0.8, yet another FreeBSD compatibility and RedHat PAM fixed. 04/02/1998 - Version 0.9, new r00tkits versions support. 07/03/1998 - Version 0.10, another types of r00tkits supported. 10/15/1998 - Version 0.11, bug found by Alberto Courrege Gomide fixed. 11/30/1998 - Version 0.12, lrk4 support added. 12/26/1998 - Version 0.13, minor fixes for Red Hat and glibc users. 06/14/1999 - Version 0.14, Sun/Solaris initial support added. 04/29/2000 - Version 0.15, lrk5 features added and minor fixes. 07/09/2000 - Version 0.16, new r00tkits types support and contrib patches. 09/16/2000 - Version 0.17, more contrib patches, rootkit types and Loadable Kernel Modules (LKM) trojan checking added. 10/08/2000 - Version 0.18, new rookits types support and many bug fixes. 12/24/2000 - Version 0.19, -r, -p, -l options added. ARK support added. Some bug fixes. 01/18/2001 - Version 0.20, Ramen Worm and latest t0rnkit detection, temporay check for promisc mode disabled on Solaris boxes. 01/19/2001 - Version 0.21, Corrects a bug in the Ramen Worm detection. 01/26/2001 - Version 0.22, chklastlog core dump bug fixed, login and bindshell false positives fixed, cron test improvement. 03/12/2001 - Version 0.23, lrk6, rh[67]-shaper, RSHA and Romanian rootkit detection. Test for shell history file anomalies. More ports added to the bindshell test. 03/15/2001 - Version 0.23a fixes a bug found in the cron and bindshell tests. 03/22/2001 - Version 0.30 lots of new tests added. RK17 and Lion Worm detection. 04/07/2001 - Version 0.31 new tests: gpm, rlogind, mgetty. Adore Worm detection. Some bug fixes. 05/07/2001 - Version 0.32 t0rn v8, LPD Worm, kenny-rk and Adore LKM detection. Some Solaris bug fixes. 06/02/2001 - Version 0.33 new tests added. ShitC, Omega and Wormkit Worm detection. dsc-rootkit detection. Some bug fixes. 09/19/2001 - Version 0.34 new tests added. check_wtmpx.c added. Ducoci rootkit and x.c Worm detection. `-q' option added. 01/17/2002 - Version 0.35 tests added: lsof and ldsopreload. strings.c added. Ports added to the bindshell test. RST.b, duarawkz, knark LKM, Monkit, Hidrootkit, Bobkit, Pizdakit, t0rn v8.0 (variant) detection. 06/15/2002 - Version 0.36 test added: w. chkproc.c additions. Showtee, Optickit, T.R.K, MithRa's Rootkit, George and SucKIT detection. 09/16/2002 - Version 0.37 tests added: scalper and slapper. Scalper Worm, Slapper Worm, OpenBSD rk v1, Illogic and SK rootkit detection. chklastlog.c and chkproc.c improvements. Small chkrootkit bug fix. 12/20/2002 - Version 0.38 chkdirs.c added. chkproc.c improvements. slapper B, sebek LKM, LOC, Romanian rootkit detection. new test added: trojan tcpdump. Minor bug fixes in the chkrootkit script. 01/30/2003 - Version 0.39 chkdirs.c and chkproc.c fixes. bug fixes in the chkrootkit script. (more) Slapper variants detection. 04/03/2003 - Version 0.40 chkproc.c fixes. Tru64 support. small corrections in chkrootkit. New test added: init. New rootkits detected: shv4, Aquatica, ZK. 06/20/2003 - Version 0.41 chkproc.c fixes. New test added: vdir. New worms detected: 55808.A and TC2. New rootkits detected: Volc, Gold2, Anonoying, Suckit (improved), ZK (improved). Minor corrections. 09/12/2003 - Version 0.42 BSDI support for chkdirs.c. chkproc.c fix. New rootkit detected: ShKit. ifpromisc test fixed for Linux 2.4.x kernels. corrections for the -r option. FreeBSD 5.x support. HPUX correction. Extra "\n" removed from chklastlog.c output. 09/18/2003 - Version 0.42a Bug fix release. 09/20/2003 - Version 0.42b Bug fix release. 12/27/2003 - Version 0.43 C++ comments removed from chkproc.c. New rootkits detected: AjaKit and zaRwT. New CGI backdoors detected. ifpromisc.c: better detection of promisc mode on newer Linux kernels. New command line option (-n) to skip NFS mounted dirs. Minor bug corrections. 09/01/2004 - Version 0.44 chkwtmp.c: del counter fixed. chkproc.c: better support for Linux threads. New rootkit detected: Madalin. Lots of minor bug fixes. 02/22/2005 - Version 0.45 chkproc.c: better support for Linux threads. New rootkit detected: Fu, Kenga3, ESRK. New test: chkutmp. -n option improvement. Minor bug fixes. 10/26/2005 - Version 0.46 chkproc.c: more fixes to better support Linux threads. chkutmp.c: improved execution speed. chkwtmp.c: segfault fixed. New rootkit detected: rootedoor. Mac OS X support added. Minor bug fixes. 10/28/2005 - Version 0.46a chkproc.c: bug fix for FreeBSD: chkproc was sending a SIGXFSZ (kill -25) to init, causing a reboot. -------------- Thx for using chkrootkit ---------------- chkrootkit-0.46a/README.chklastlog010044400017500001750000000024531032550144200163760ustar00jessenjessen chklastlog - check lastlog-file for deleted information Copyright (c) DFN-CERT, Univ. of Hamburg 1994 Univ. Hamburg, Dept. of Computer Science DFN-CERT Vogt-Koelln-Strasse 30 22527 Hamburg Germany This program is free software; you can distribute it and/or modify it as long as you retain the DFN-CERT copyright statement. It can be obtained via anonymous FTP from ftp://ftp.cert.dfn.de/pub/tools/admin/chklastlog/chklastlog.tar.Z This program is distributed WITHOUT ANY WARRANTY; without the IMPLIED WARRANTY of merchantability or fitness for a particular purpose. This package contains: README MANIFEST chklastlog.1 chklastlog.c chklastlog.txt To create chklastlog under SunOS 4.x, type: % cc -o chklastlog chklastlog.c To run chklastlog you need read permission on the files /var/adm/wtmp and /var/adm/lastlogin. Normally these files are world-readable and no special privileges are required to run the checker. The following is an example of the output of chklastlog. Running chklastlog on a machine with deleted lastlog-entries, under csh(1): % chklastlog user ley deleted from lastlog! % Running chklastlog on a machine with no deleted lastlog-entries, under csh(1): % chklastlog % chkrootkit-0.46a/strings.c010044400017500001750000000046051032550146600152300ustar00jessenjessen/* * Poor developer's strings. * (c) 2002, Sean D. True, WebReply.Com, Inc. * Use freely, under the Python license * In short: use with or without attribution as you like, but * no warranty of fitness, suitability, or anything else is given! * * ChangeLog: * superfluous printable() function deleted - 2002/02/20 - Nelson Murilo */ #include #include #include #include #include #include #define MAXFILESIZE (4*1024*1024) /* * Many options here. The current choice produces a little more output * than gnu strings */ /* * Try to get the filesize via stat, and get a buffer to match * Naievely allocate a 4MB buffer if we can't * Fails badly if it allocate a buffer big enough to load a file */ unsigned char *filebuf(FILE *pf, int *sz) { struct stat buf; unsigned char *cdata; if (fstat(fileno(pf), &buf) < 0) { perror("fstat"); exit (1); } *sz = buf.st_size; if(*sz == 0) *sz = MAXFILESIZE; if ((cdata = malloc(*sz+1)) == NULL) { perror("malloc"); exit (1); } return cdata; } /* * Find printable strings of 4 or more characters * Always scans entire file (-a option of gnu strings) */ void strings(FILE *pf) { static char printme[1024]; int sz; unsigned char *cdata; int nread; int printmeindex; cdata = filebuf(pf,&sz); nread = fread(cdata, 1, sz, pf); printmeindex = 0; if (nread > 0) { int i; unsigned char c; int isprintable; int iseol; for (i = 0; i < nread; i++) { c = cdata[i]; isprintable = isprint(c); iseol = 0; if (c == 0 || c == '\n' || printmeindex >= sizeof(printme)-1) iseol = 1; if (iseol || !isprintable) { if (printmeindex > 3 && iseol) { printme[printmeindex++] = 0; printf("%s\n", printme); printmeindex = 0; } } else if (isprintable) { printme[printmeindex++] = c; } } } if (printmeindex > 3) { printme[printmeindex++] = 0; printf("%s\n", printme); printmeindex = 0; } free(cdata); } /* * Silently accepts the -a option */ int main(int argc, char **argv) { if (argc > 1) { int i; for (i = 1; i < argc; i++) { FILE *pf; if (strcmp(argv[i], "-a") == 0) continue; if ((pf = fopen(argv[i],"rb")) == NULL) { perror("fopen"); return(1); } strings(pf); } } else { strings(stdin); } return(0); } chkrootkit-0.46a/chkproc.c010044400017500001750000000177071033044115400151700ustar00jessenjessen/* (C) Nelson Murilo - 2004/09/13 Version 0.9 C port from chkproc.pl code from Klaus Steding-Jessen and Cristine Hoepers +little output changes. 2002/03/02 - Segmentation fault in ps for non ASCII user name, by RainbowHat 2002/06/13 Updated by Kostya Kortchinsky - corrected the program return value ; - added a verbose mode displaying information about the hidden process. 2002/08/08 - Value of MAX_PROCESSES was increased to 99999 (new versions of FreeBSD, HP-UX and others), reported by Morohoshi Akihiko, Paul and others. 2002/09/03 - Eliminate (?) false-positives. Original idea from Aaron Sherman. 2002/11/15 - Updated by Kostya Kortchinsky - ported to SunOS. 2003/01/19 - Another Adore based lkm test. Original idea from Junichi Murakami 2003/02/02 - More little fixes - Nelson Murilo 2003/02/23 - Use of kill to eliminate false-positives abandonated, It is preferable false-positives that false-negatives. Uncomment kill() functions if you like it. 2003/06/07 - Fix for NPTL threading mechanisms - patch by Mike Griego 2003/09/01 - Fix for ps mode detect, patch by Bill Dupree and others 2004/04/03 - More fix for linux's threads - Nelson Murilo 2004/09/13 - More and more fix for linux's threads - Nelson Murilo 2005/02/23 - More and more and more fix for linux's threads - Nelson Murilo 2005/10/28 - Bug fix for FreeBSD: chkproc was sending a SIGXFSZ (kill -25) to init, causing a reboot. Patch by Nelson Murilo. Thanks to Luiz E. R. Cordeiro. */ #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__sun) int main (){ return 0; } #else #include #include #include #include #include #include #include #include #if defined(__sun) #include #include #endif #define PS_SUN 0 #define PS_LOL 1 #define PS_COM 2 #define PS_LNX 3 #define PS_MAX 3 #if defined(__sun) #define FIRST_PROCESS 0 #else #define FIRST_PROCESS 1 #endif #define MAX_PROCESSES 99999 #define MAX_BUF 1024 static char *ps_cmds[] = { "ps -edf", "ps auxw", "ps mauxw 2>&1 ", "ps auxw -T|tr -s ' '|cut -d' ' -f2-", }; int psproc [MAX_PROCESSES+1]; int dirproc[MAX_PROCESSES+1]; #if defined(__linux__) int isathread[MAX_PROCESSES+1]; #endif int main(int argc, char **argv) { char buf[MAX_BUF], *p, path[MAX_BUF]; char *pscmd = (char *)0; FILE *ps; DIR *proc = opendir("/proc"); struct dirent *dir; int i, j, retps, retdir, pv, verbose; long ret = 0L; char * tmp_d_name; #if defined(__linux__) int maybeathread; #endif #if defined(__sun) psinfo_t psbuf; #endif pv = verbose = 0; if (!proc) { perror("proc"); exit (1); } for (i = 1; i < argc; i++) { if (!memcmp(argv[i], "-v", 2)) verbose++; else if (!memcmp(argv[i], "-?", 2)) { printf("Usage: %s [-v] [-v] -p \n", argv[0]); return 0; } #if defined(__linux__) else if (!memcmp(argv[i], "-p", 2)) if (i+1 < argc) pv = atoi(argv[++i]); else { printf("Usage: %s [-v] [-v] [-p procps version]\n", argv[0]); return 0; } #endif } #if defined(__sun) pscmd = ps_cmds[PS_SUN]; #elif !defined (__linux__) pscmd = ps_cmds[PS_COM]; #endif #if defined(__linux__) if (pv < 1 || pv > PS_MAX) pv = 1; pscmd = ps_cmds[pv]; /* printf("pv = %d\n\r", pv); /* -- DEBUG */ #endif /* printf("pscmd = %s\n\r", pscmd); /* -- DEBUG */ if (!(ps = popen(pscmd, "r"))) { perror("ps"); exit(errno); } *buf = 0; fgets(buf, MAX_BUF, ps); /* Skip header */ #if defined(__sun) if (!isspace(*buf)) #else if (!isalpha(*buf)) #endif { fgets(buf, MAX_BUF, ps); /* Skip header */ if (!isalpha(*buf) && pv != PS_LNX) { if (pv != PS_LOL) execlp(argv[0], argv[0], "-p 1", NULL); fprintf(stderr, "OooPS!\n"); exit(2); } } if (!memcmp(buf, "ps:", 3) && (pv != PS_LOL)) execlp(argv[0], argv[0], "-p 1", NULL); for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++) { /* Init matrix */ psproc[i] = dirproc[i] = 0; #if defined(__linux__) isathread[i] = 0; #endif } while (fgets(buf, MAX_BUF, ps)) { p = buf; #if defined(__sun) while (isspace(*p)) /* Skip spaces */ p++; #endif while (!isspace(*p)) /* Skip User */ p++; while (isspace(*p)) /* Skip spaces */ p++; /* printf(">>%s<<\n", p); /* -- DEBUG */ ret = atol(p); if ( ret < 0 || ret > MAX_PROCESSES ) { fprintf (stderr, " OooPS, not expected %d value\n", ret); exit (2); } psproc[ret] = 1; } pclose(ps); while ((dir = readdir(proc))) { #if defined(__linux__) maybeathread = 0; #endif tmp_d_name = dir->d_name; if (!strcmp(tmp_d_name, ".") || !strcmp(tmp_d_name, "..")) continue; #if defined(__linux__) if (*tmp_d_name == '.') { /* here we catch the new NTPL threads in linux. They are listed in /proc as PIDs with a period prepended */ tmp_d_name++; maybeathread = 1; } #endif if(!isdigit(*tmp_d_name)) continue; #if defined(__linux__) else if (maybeathread) { isathread[atol(tmp_d_name)] = 1; /* mark it as a linux NTPL thread if it's in the form of "\.[0-9]*" */ if (verbose) printf("%d is a Linux Thread, marking as such...\n", atol(tmp_d_name)); } #endif /* printf("%s\n", tmp_d_name); /* -- DEBUG */ dirproc[atol(tmp_d_name)] = 1; } closedir(proc); /* Brute force */ strcpy(buf, "/proc/"); retps = retdir = 0; for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++) { snprintf(&buf[6], 6, "%d", i); if (!chdir(buf)) { /* if (!dirproc[i] ) /* && !kill(i, 0)) */ if (!dirproc[i] && !psproc[i]) { #if defined(__linux__) if (!isathread[i]) { #endif retdir++; if (verbose) printf ("PID %5d(%s): not in readdir output\n", i, buf); #if defined(__linux__) } #endif } if (!psproc[i] ) /* && !kill(i, 0)) */ { #if defined(__linux__) if(!isathread[i]) { #endif retps++; if (verbose) printf ("PID %5d: not in ps output\n", i); #if defined(__linux__) } #endif } #if defined(__linux__) if(!isathread[i]) { #endif /* if ((!dirproc[i] || !psproc[i]) && !kill(i, 0) && (verbose > 1)) */ if ((!dirproc[i] || !psproc[i]) && (verbose > 1)) { #if defined(__linux__) j = readlink ("./cwd", path, sizeof(path)); path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0; printf ("CWD %5d: %s\n", i, path); j = readlink ("./exe", path, sizeof(path)); path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0; printf ("EXE %5d: %s\n", i, path); #elif defined(__FreeBSD__) j = readlink ("./file", path, sizeof(path)); path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0; printf ("FILE %5d: %s\n", i, path); #elif defined(__sun) if ((j = open("./psinfo", O_RDONLY)) != -1) { if (read(j, &psbuf, sizeof(psbuf)) == sizeof(psbuf)) printf ("PSINFO %5d: %s\n", i, psbuf.pr_psargs); else printf ("PSINFO %5d: unknown\n", i); close(j); } else printf ("PSINFO %5d: unknown\n", i); #endif } #if defined(__linux__) } #endif } } if (retdir) printf("You have % 5d process hidden for readdir command\n", retdir); if (retps) printf("You have % 5d process hidden for ps command\n", retps); #if defined(__linux__) kill(1, 100); /* Check for SIGINVISIBLE Adore signal */ if (kill (1, 25) > 0 && errno == 3) { printf("SIGINVISIBLE Adore found\n"); retdir+= errno; } #endif return (retdir+retps); } #endif