#! /bin/sh
# -*- Shell-script -*-

# $Id: chkrootkit, v 0.14 1999/06/14

# Author: nelson@pangeia.com.br
# (C)1997-2000 Nelson Murilo, Pangeia Informatica, AMS Foundation and others.
# All rights reserved

# Native commands 
TROJAN="chfn chsh cron sshd2 du find su ifconfig inetd killall login ls		
netstat	passwd pidof ps rshd syslogd tcpd top"
# Tools
TOOLS="bindshell z2 wted sniffer aliens"

# Return Codes 
INFECTED=0
NOT_INFECTED=1
NOT_TESTED=2
ERROR=3
INFECTED_BUT_DISABLED=4

# ps Command
PS=`which ps`

# Many trojaned commands have this label
GENERIC_ROOTKIT_LABEL="^/bin/.*sh|bash|elite"

######################################################################
# tools functions

sniffer () {
    echo
    .chkroot/ifpromisc
}

z2 () {
    .chkroot/chklastlog
    if [ $? -eq 0 ]
      then
      echo "Nothing deleted"
    fi
}

wted () {
    .chkroot/chkwtmp
    if [ $? -eq 0 ]
      then
      echo "Nothing deleted"
    fi
}

bindshell () {
    PORT="31337"
    CMD=`which netstat`
    OPT="-an"
    if "${CMD}" "${OPT}" | egrep ${PORT} >/dev/null 2>&1
       then
       echo "INFECTED"
    else
       echo "Not vulnerable" 
    fi
}

aliens () {
   dir="/var/run/.tmp"
   files=`find /dev -type f -exec egrep -l "^[0-5] " {} \;` 
   if [ "${files}" = "" ] 
   then
      if [ -d ${dir} ]
      then
         echo "Suspect direct ${dir} FOUND! Looking for sniffer logs"
         files=`find ${dir}` 
         echo 
         echo ${files}
      else 
         echo "No suspect files"
      fi
   else
      echo 
      echo ${files}
   fi
   printn "Searching for sniffer's logs, please wait MANY minutes..."
   files=`find / -name "tcp.log"` 
   if [ "${files}" = "" ]
   then 
      echo "Nothing found"
   else
      echo 
      echo ${files}
   fi
}

######################################################################
# util functions

pegaCMD() { 
   for i in `${PS} ax | grep " ${1} " | grep -v grep | awk '{ print $5 }'` \
            "/usr/sbin/${1}" `which ${1}` 
      do
      CMD="${i}"
      if [ -r "${i}" ] 
        then
        return
      fi
   done
}

######################################################################
# trojan functions

chfn () {
    STATUS=${NOT_INFECTED}
    CMD=`which chfn`
    case "${SYSTEM}" in
       Linux)
          if strings ${CMD} | egrep "${GENERIC_ROOTKIT_LABEL}" >/dev/null 2>&1
             then
             STATUS=${INFECTED}
          fi;;
       FreeBSD) 
          if [ `strings ${CMD} | egrep -c "${GENERIC_ROOTKIT_LABEL}"` -ne 2 ]
             then
             STATUS=${INFECTED}
          fi;;
    esac 
    return ${STATUS}
}

chsh () {
    STATUS=${NOT_INFECTED}
    CMD=`which chsh`
    REDHAT_PAM_LABEL="*NOT*"
    case "${SYSTEM}" in
       Linux)
          if strings ${CMD} | egrep "${GENERIC_ROOTKIT_LABEL}" >/dev/null 2>&1
             then
             if strings ${CMD} | egrep ${REDHAT_PAM_LABEL} >/dev/null 2>&1
                then 
                :
             else
                STATUS=${INFECTED}
             fi
          fi;;
       FreeBSD) 
          if [ `strings ${CMD} | egrep -c "${GENERIC_ROOTKIT_LABEL}"` -ne 2 ]
             then
             STATUS=${INFECTED}
          fi;;
    esac 
    return ${STATUS}
}

login () {
    STATUS=${NOT_INFECTED}
    CMD=`which login`
    TROJED_LOGIN_LABEL="^root$"
    FREEBSD_LOGIN_LABEL="^@\(#\)klogin\.c"
    if strings ${CMD} | egrep ${TROJED_LOGIN_LABEL} >/dev/null 2>&1
       then
       if [ `strings ${CMD} | egrep -c "${TROJED_LOGIN_LABEL}|${FREEBSD_LOGIN_LABEL}"` -ne 2 ]
        then
          STATUS=${INFECTED}
       fi
    fi
    return ${STATUS}
}

passwd () {
    STATUS=${NOT_INFECTED}
    CMD=`which passwd`
    if strings ${CMD} | egrep "${GENERIC_ROOTKIT_LABEL}" >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

inetd () {
    STATUS=${NOT_INFECTED}
    pegaCMD 'inetd'
    if [ ! -r ${CMD} ]
       then
       return ${NOT_TESTED}
    fi
    if strings ${CMD} | egrep "${GENERIC_ROOTKIT_LABEL}" >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

syslogd () {
    STATUS=${NOT_INFECTED}
    SYSLOG_INFECTED_LABEL="/dev/pty[pqrs]"
    pegaCMD 'syslogd'
    if [ ! -r ${CMD} ]
       then
       return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${SYSLOG_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

ls () {
    STATUS=${NOT_INFECTED}
    LS_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which ls`
    if strings ${CMD} | grep ${LS_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

du () {
    STATUS=${NOT_INFECTED}
    DU_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which du`
    if strings ${CMD} | grep ${DU_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

netstat () {
    STATUS=${NOT_INFECTED}
    NETSTAT_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which netstat`
    if strings ${CMD} | grep ${NETSTAT_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

ps () {
    STATUS=${NOT_INFECTED}
    PS_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which ps`
    if strings ${CMD} | grep ${PS_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

top () {
    STATUS=${NOT_INFECTED}
    TOP_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which top`
    if [ "${CMD}" = "" ]
       then
        return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${TOP_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}
pidof () {
    STATUS=${NOT_INFECTED}
    TOP_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which pidof`
    if [ "${?}" -ne 0 ]
       then
        return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${TOP_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

killall () {
    STATUS=${NOT_INFECTED}
    TOP_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which killall`
    if [ "${?}" -ne 0 ]
       then
        return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${TOP_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}
find () {
    STATUS=${NOT_INFECTED}
    TOP_INFECTED_LABEL="/dev/pty[pqrs]"
    CMD=`which find`
    if [ "${?}" -ne 0 ]
       then
        return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${TOP_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}
cron () {
    STATUS=${NOT_INFECTED}
    TOP_INFECTED_LABEL="/dev/hda"
    if [ -f /usr/sbin/cron ]; then
          CMD="/usr/sbin/cron"
       else
          CMD=`which cron`
    fi
    if [ "${?}" -ne 0 ]
       then
        return ${NOT_TESTED}
    fi
    if strings ${CMD} | grep ${TOP_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

passwd () {
    STATUS=${NOT_INFECTED}
    CMD=`which passwd`
    if strings ${CMD} | egrep "${GENERIC_ROOTKIT_LABEL}" >/dev/null 2>&1
       then
       STATUS=${INFECTED}
    fi
    return ${STATUS}
}

ifconfig () {
    STATUS=${INFECTED}
    CMD="/sbin/ifconfig"
    IFCONFIG_INFECTED_LABEL="PROMISC"
    if strings ${CMD} | egrep ${IFCONFIG_INFECTED_LABEL} >/dev/null 2>&1
       then
       STATUS=${NOT_INFECTED}
    fi
    return ${STATUS}
}

rshd () {
    STATUS=${NOT_INFECTED}
    case "${SYSTEM}" in
       Linux) CMD="/usr/sbin/in.rshd";;
       FreeBSD) CMD="/usr/libexec/rshd";;
    esac 
    RSHD_INFECTED_LABEL="root"
    if strings ${CMD} | grep ${RSHD_INFECTED_LABEL} > /dev/null 2>&1
    then
        STATUS=${INFECTED}
        if egrep "^#.*rshd" /etc/inetd.conf >/dev/null 2>&1; then
           STATUS=${INFECTED_BUT_DISABLED}
        fi
    fi
    return ${STATUS}
}

tcpd () {
    STATUS=${NOT_INFECTED}
    TCPD_INFECTED_LABEL="hack"

    CMD=`grep tcpd /etc/inetd.conf | head -1| awk '{ print $6 }'`
    [ "" = "${CMD}" ] && return ${NOT_TESTED};
    if strings ${CMD} | grep ${TCPD_INFECTED_LABEL} > /dev/null 2>&1
    then
        STATUS=${INFECTED}
    fi
    return ${STATUS}
}

sshd2 () {
    STATUS=${NOT_INFECTED}
    SSHD2_INFECTED_LABEL="satori"
    CMD="/usr/local/sbin/sshd2"
    if strings ${CMD} | grep ${SSHD2_INFECTED_LABEL} > /dev/null 2>&1
    then
        STATUS=${INFECTED}
        if ps -aux | grep sshd2 >/dev/null 2>&1; then
           STATUS=${INFECTED_BUT_DISABLED}
        fi
    fi
    return ${STATUS}
}

su () {
    STATUS=${NOT_INFECTED}
    SU_INFECTED_LABEL="satori"
    CMD=`which su`
    if strings ${CMD} | grep ${SU_INFECTED_LABEL} > /dev/null 2>&1
    then
        STATUS=${INFECTED}
    fi
    return ${STATUS}
}

printn() {
   if [ `echo "a\c" | grep c >/dev/null 2>&1` ]; then
      echo "${1}\c"
   else
      echo -n $1
   fi
}

# main
#
if [ `id | cut -d= -f2 | cut -d\( -f1` -ne 0 ]; then
   echo "$0 need root privilegies"
   exit -1;
fi
   
while :
do
	case $1 in
        -d)     DEBUG=t;;

	-h | -*) echo >&2 "Usage: $0 [options] [command ...]
Options:
        -h                show this help and exit
        -d                debug"
		exit 1;;
	*)	break
	esac

	shift
done

if [ $# -gt 0 ]
then
    ### check only commands supplied as arguments
    for arg in $*
    do
        ### check if is a trojaned command name
        if echo "${TROJAN} ${TOOLS}"| egrep -vw "$arg" > /dev/null 2>&1
        then
            echo >&2 "$0: \`$arg': not a trojaned command"
            exit 1
        fi
    done
    LIST=$*
else
    ### check all the trojaned commands and hack tools
    LIST="${TROJAN}"
fi

SYSTEM=`uname -s`
VERSION=`uname -r`

for cmd in ${LIST}
do

    if [ "${DEBUG}" = "t" ] ;then
        set -x
    fi

    printn "Checking \`${cmd}'..."
    ${cmd}

    case $? in
    0) echo "INFECTED";;
    1) echo "Not vulnerable";; 
    2) echo "NOT TESTED";;
    3) echo "ERROR: ${ERR}";;
    4) echo "Vulnerable but disabled";;
    esac
done

for cmd in ${TOOLS}
do
   printn "Checking \`$cmd'..."
   ${cmd}
done
