您现在的位置是:首页 > 编程 > 

通过chkrootkit学习如何在linux下检测RootKit

2025-07-27 12:54:16
通过chkrootkit学习如何在linux下检测RootKit Rootkit是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身及指定的文件、进程和网络链接等信息,比较多见到的是Rootkit一般都和木马、后门等其他恶意程序结合使用。Rootkit一词更多地是指被作为驱动程序,加载到操作系统内核中的恶意软件。chkrootkit简介chkrootkit是一个linux下检RootKit的脚本,

通过chkrootkit学习如何在linux下检测RootKit

Rootkit是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身及指定的文件、进程和网络链接等信息,比较多见到的是Rootkit一般都和木马、后门等其他恶意程序结合使用。Rootkit一词更多地是指被作为驱动程序,加载到操作系统内核中的恶意软件。

chkrootkit简介

chkrootkit是一个linux下检RootKit的脚本,在某些检测中会调用当前目录的检测程序

:/

下载源码:.tar.gz

解压后执行 make 命令,就可以使用了

一般直接运行,一旦有IFECTED,说明可能被植入了RootKit

代码语言:javascript代码运行次数:0运行复制
./chkrootkit | grep IFECTED

总体流程

首先删除别名,确保接下来的一些操作不会用了被RootKit改变了的别名

代码语言:javascript代码运行次数:0运行复制
### workaround for some Bourne shell implementati
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

一开始会检测一些必要的命令是否可用,可执行,因为检测基于这些命令

代码语言:javascript代码运行次数:0运行复制
cmdlist="
awk
cut
echo
egrep
find
head
id
ls
netstat
ps
sed

strings
uname
"

接下来就是检测ps的参数ax好不好使,好使就使用ax,不好使就用-fe

代码语言:javascript代码运行次数:0运行复制
# Check if ps command is ok
if ${ps} ax >/dev/null 2>&1 ; then
   ps_cmd="ax"
else
   ps_cmd="-fe"
fi

当然还需检测你是否是root,就根据你的id号是否为0

代码语言:javascript代码运行次数:0运行复制
if [ `${id} | ${cut} -d= -f2 | ${cut} -d\( -f1` -ne 0 ]; then
   echo "$0 need root privileges"
   exit 1
fi

接下来就是默认执行所有测试,当然你也可以指定测试的命令

代码语言:javascript代码运行次数:0运行复制
if [ $# -gt 0 ]
then
    ### perform only tests supplied as arguments
    for arg in $*
    do
        ### check if is a valid test name
        if echo "${TROJA} ${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="${TROJA} ${TOOLS}"
fi

接下来只是对是否开启调试模式,用户是否指定了要检测的根目录进行处理

代码语言:javascript代码运行次数:0运行复制
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

最后便是循环调用各个check函数进行处理了

代码语言:javascript代码运行次数:0运行复制
for cmd in ${LIST}
do

    if echo "${TROJA}" | \
    ${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 IFECTED status
            if [ ${STATUS} -eq 0 ]; then
                echo "Checking \`${cmd}'... IFECTED"
            fi
            continue
        fi

        case $STATUS in
        0) echo "IFECTED";;
        1) echo "not infected";;
        2) echo "not tested";;
        ) 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

那么接下来每个check方法到底是怎么检测的呢?接下来

检测方法

通过分析脚本,总结出检测方法如下:

  1. 搜索通用的ROOTKIT特征的字符串
  2. 对某种特定的rootkits,或者命令的特殊的感染特征进行检测
  3. 对某种特定的rootkits的生成的特定文件的检测
  4. 对程序的SUID位的设置进行检测
  5. 对ldsopreload的检测
  6. 查可疑的log文件
  7. 查可疑的php文件
  8. 检测.history文件
  9. 检测有无程序监听了一些可疑的端口
  10. 检测Linux可加载内核模块
  11. 检测有无隐藏进程
  12. 检测目录的软链接异常
  13. 检测网络接口的异常
  14. 检测用户的登录日志
  15. 检测上一次登录
  16. 检测可疑的没有tty记录的进程

下面对上面这些方法结合脚本代码进行简单说明

搜索通用的ROOTKIT特征的字符串

搜索的是下面的比较通用的ROOTKIT字符串

代码语言:javascript代码运行次数:0运行复制
# Many trojaned commands have this label
GEERIC_ROOTKIT_LABEL="^/bin/.*sh$|bash|elite$|vejeta|\.ark|iroffer"

可以看到前两个都是shell相关的,相关的示例代码如下:

代码语言:javascript代码运行次数:0运行复制
chk_chfn () {
    STATUS=${OT_IFECTED}
    CMD=`loc chfn chfn $pth`
    [ ${?} -ne 0 ] &&  return ${OT_FOUD}

    if [ "${EXPERT}" = "t" ]; then
        expertmode_output "${strings} -a ${CMD}"
        return 5
    fi

    case "${SYSTEM}" in
       Linux)
          if ${strings} -a ${CMD} | ${egrep} "${GEERIC_ROOTKIT_LABEL}" \
             >/dev/null 2>&1
          then
             STATUS=${IFECTED}
          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 "${GEERIC_ROOTKIT_LABEL}"` -ne $n ]
          then
             STATUS=${IFECTED}
          fi;;
    esac
    return ${STATUS}
}

程序针对Linux和FreeBSD系统分开处理,都是通过strings获取二进制程序中的字符串,再使用egrep命令去正则匹配,匹配成功就将返回值STATUS设置为IFECTED这个常量(这个在文件开头处定义了)

对某种特定的rootkits,或者命令的特殊的感染特征进行检测

比如这个amd命令的某个感染特征

代码语言:javascript代码运行次数:0运行复制
chk_amd () {
    STATUS=${OT_IFECTED}
    AMD_IFECTED_LABEL="blah"
    CMD=`loc amd amd $pth`
    if [ ! -x "${CMD}" ]; then
         return ${OT_FOUD}
    fi
    if [ "${EXPERT}" = "t" ]; then
        expertmode_output "${strings} -a ${CMD}"
        return 5
    fi
    if ${strings} -a ${CMD} | ${egrep} "${AMD_IFECTED_LABEL}" >/dev/null 2>&1
    then
       STATUS=${IFECTED}
    fi
    return ${STATUS}
}

下面这个检测crontab的nobody用户,并且定时任务中有数字的, 可能是Lupper.Worm 当然还是有CROTAB_I_L这个特殊的检测

代码语言:javascript代码运行次数:0运行复制
chk_crontab () {
    STATUS=${OT_IFECTED}
    CROTAB_I_L="crontab.*666"

    CMD=`loc crontab crontab $pth`

    if [ ! -r ${CMD} ]
       then
        return ${OT_FOUD}
    fi

    if [ "${EXPERT}" = "t" ]; then
        expertmode_output "${CMD} -l -u nobody"
        return 5
    fi
    # slackware's crontab have a bug
    if  ( ${CMD} -l -u nobody | $egrep [0-9] ) >/dev/null 2>&1 ; then
        ${echo} "Warning: crontab for nobody found, possible Lupper.Worm... "
	if ${CMD} -l -u nobody 2>/dev/null  | ${egrep} $CROTAB_I_L >/dev/null 2>&1
	   then
           STATUS=${IFECTED}
	fi
    fi
    return ${STATUS}
}

对Ramen Worm进行特征匹配

代码语言:javascript代码运行次数:0运行复制
if ${egrep} "^asp" ${ROOTDIR}etc/ >/dev/null 2>&1; then
    echo "Warning: Possible Ramen Worm installed in "
    STATUS=${IFECTED}
fi
对某种特定的rootkits生成的特定文件的检测

如下面的HiDrootkit和t0rn

代码语言:javascript代码运行次数:0运行复制
### 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/ -o \
    -d ${ROOTDIR}usr/info/.t0rn ]
then
  echo "Possible t0rn rootkit installed"
else
  if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi
fi
对程序的SUID位的设置进行检测代码语言:javascript代码运行次数:0运行复制
chk_basename () {
   STATUS=${OT_IFECTED}
   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} "${GEERIC_ROOTKIT_LABEL}" > /dev/null 2>&1
   then
       STATUS=${IFECTED}
   fi

   [ "$SYSTEM" != "OSF1" ] &&
   {
      if ${ls} -l ${CMD} | ${egrep} "^...s" > /dev/null 2>&1
      then
         STATUS=${IFECTED}
      fi
   }
   return ${STATUS}
}

这个除了检测有无关键字,还检测SUID位有无设置

对ldsopreload的检测代码语言:javascript代码运行次数:0运行复制
chk_ldsopreload() {
   STATUS=${OT_IFECTED}
   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 ${OT_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=${IFECTED}
      fi
   else
     STATUS=${OT_TESTED}
   fi
   return ${STATUS}
}

检测是否有libshow.so,libproc.a,有就说明感染了恶意so文件

可以看到为了保险起见,作者使用的是自己目录下静态编译的strings进行检测

查可疑的log文件

例子如下:

代码语言:javascript代码运行次数:0运行复制
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
查可疑的php文件

查一些可疑的php文件

代码语言:javascript代码运行次数:0运行复制
###
### Suspect PHP files
###
if [ "${QUIET}" != "t" ]; then
    printn "Searching for suspect PHP files... "; fi
    files="`${find} ${ROOTDIR}tmp ${ROOTDIR}var/tmp ${findargs} -name '*.php' 2> /dev/null`"
if [ `echo abc | head -n 1` = "abc" ]; then
    fileshead="`${find} ${ROOTDIR}tmp ${ROOTDIR}var/tmp ${findargs} -type f -exec head -n 1 {} \; | $egrep '#!.*php' 2> /dev/null`"
else
    fileshead="`${find} ${ROOTDIR}tmp ${ROOTDIR}var/tmp ${findargs} -type f -exec head -1 {} \; | grep '#!.*php' 2> /dev/null`"
fi
if [ "${files}" = "" -a "${fileshead}" = "" ]; then
    if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi
else
     echo
     echo "${files}"
     echo "${fileshead}"
fi
检测.history文件

看看history有没有被清空了,或者软连接到其他地方了

代码语言:javascript代码运行次数:0运行复制
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} ${findargs} -name '.*history' -size 0`
      [ ! -z "${files}" ] && \
        echo "Warning: \`${files}' file size is zero"
      files1=`${find} ${ROOTDIR}${HOME} ${findargs} -name '.*history' \( -links 2 -o -type l \)`
      [ ! -z "${files1}" ] && \
        echo "Warning: \`${files1}' is linked to another file"
   fi
   if [ -z "${files}" -a -z "${files1}" ]; then
      if [ "${QUIET}" != "t" ]; then echo "nothing found"; fi
   fi
检测有无程序监听了一些可疑的端口

检测代码如下:

代码语言:javascript代码运行次数:0运行复制
bindshell () {
PORT="114|145|465|511|600|1008|1524|1999|1978|2881|049|1|879|4000|469|5190|5665|6667|10008|1221|212|2774|2964|0999|16|17|7998|45454|47017|47889|60001|7222"
   OPT="-an"
   PI=""
   if [ "${ROOTDIR}" != "/" ]; then
     echo "not tested"
     return ${OT_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 "IFECTED PORTS: ($PI)"
   else
      if [ "${QUIET}" != "t" ]; then echo "not infected"; fi
   fi
}
检测Linux可加载内核模块代码语言:javascript代码运行次数:0运行复制
lkm ()
{
    prog=""
    if [  \( "${SYSTEM}" = "Linux"  -o \( "${SYSTEM}" = "FreeBSD" -a \
       `echo ${V} | ${awk} '{ if ($1 > 4. || $1 < 6.0) print 1; else print 0 }'` -eq 1 \) \) -a "${ROOTDIR}" = "/" ]; then
      [  -x ./chkproc -a "`find /proc | wc -l`" -gt 1 ] && prog="./chkproc"
      [  -x ./chkdirs ] && prog="$prog ./chkdirs"
      if [ "$prog" = "" ]; then
         echo "not tested: can't exec $prog"
         return ${OT_TESTED}
      fi

      if [ "${EXPERT}" = "t" ]; then
         [ -r /proc/$KALLSYMS ] &&  ${egrep} -i "adore|sebek" < /proc/$KALLSYMS 2>/dev/null
         [ -d /proc/knark ] &&  ${ls} -la /proc/knark 2> /dev/null
         PV=`$ps -V 2>/dev/null| $cut -d " " -f  |${awk} -F . '{ print $1 "." $2 $ }' | ${awk} '{ if ($0 > .19) print ; else if ($0 < 2.015) 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/$KALLSYMS ] && \
      if `${egrep} -i adore < /proc/$KALLSYMS >/dev/null 2>&1`; then
         echo "Warning: Adore LKM installed"
      fi

      ### sebek LKM (Adore based)
      [ -r /proc/$KALLSYMS ] && \
      if `${egrep} -i sebek < /proc/$KALLSYMS >/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  |${awk} -F . '{ print $1 "." $2 $ }' | ${awk} '{ if ($0 > .19) print ; 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
      dirs="/tmp"
      for i in /usr/share /usr/bin /usr/sbin /lib; do
         [ -d $i ] && dirs="$dirs $i"
      done
      if ./chkdirs $dirs;  then
         if [ "${QUIET}" != "t" ]; then echo "chkdirs: nothing detected"; fi
      else
	    echo "chkdirs: Warning: Possible LKM Trojan installed"
      fi
   else
         if [ "${QUIET}" != "t" ]; then echo "chkproc: not tested"; fi
   fi
}

loadable kernel module (LKM),这个是检测内核模块的 ,看看有无adore,sebek这些内核模块

之后调用chkproc,chkdirs进行检测,这两个下面检测有无隐藏进程,会说到

检测有无隐藏进程

这个代码在中,它通过暴力递归,看看有没有/proc目录存在,而ps查不出来的进程,那么就说明有进程隐藏了

代码语言:javascript代码运行次数:0运行复制
 /* Brute force */
   strcpy(buf, "/proc/");
   retps = retdir = 0;
   for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++)
   {
      // snprintf(&buf[6], 6, "%d", i);
       snprintf(&buf[6], 8, "%d", i);
      if (!chdir(buf))
      {
         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
	 }
检测目录的软链接异常

chkdirs比较的是父目录的软链接数和子目录的个数

正常情况下,父目录的软链接数 = 子目录的个数 + 2

代码语言:javascript代码运行次数:0运行复制
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 *)ULL;
  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;
	}

	strncpy(dl->dil_name, finfo->d_name, sizeof(dl->dil_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);
检测网络接口的异常代码语言:javascript代码运行次数:0运行复制
 sniffer () {
    if [ "${ROOTDIR}" != "/" ]; then
      echo "not tested"
      return ${OT_TESTED}
    fi

    if [ "$SYSTEM" = "SunOS" ]; then
       return ${OT_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 ${OT_TESTED}
    else
      [ "${QUIET}" != "t" ] && ./ifpromisc -v || ./ifpromisc -q
    fi
}

这个是对网络接口的检测,看看有无开启网卡混杂模式(英语:promiscuous mode)

而PF_PACKET可以操作链路层的数据,可以读取和发送链路层的数据包

代码语言:javascript代码运行次数:0运行复制
 ./ifpromisc -v
ens: PF_PACKET(/sbin/dhclient)
virbr0: not promisc and no PF_PACKET sockets
docker0: not promisc and no PF_PACKET sockets
br-47ad88588a: not promisc and no PF_PACKET sockets
检测用户的登录日志

检测用户的登录相关的log文件

SunOS使用的是check_wtmpx,比较的文件是/var/adm/wtmp,/var/adm/wtmpx,check_wtmpx部分代码,比较这两个文件的一些差异,比如下面的比较uid

代码语言:javascript代码运行次数:0运行复制
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;
}

其他linux检测的是var/log/wtmp或者var/adm/wtmp chkwtmp部分代码,查看有无删除了登录时间

代码语言:javascript代码运行次数:0运行复制
gettimeofday(&mytime, &dummy);
       act_time=_sec;
       wtmpfile[127]='\0';
       memcpy(wtmpfile, WTMP_FILEAME, 127);
       if ( argc ==  && !memcmp("-f", ar[1], 2) && *ar[2])
          memcpy(wtmpfile, ar[2], 127);

	if ((filehandle=open(wtmpfile,O_RDOLY)) < 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((int) t_del+del_counter);
检测上一次登录

使用chklastlog程序检测,下面是部分代码,用户的数据通过getpwent函数获取,其实就是通过/etc/passwd获取,检测基于两点

1、通过比较MAX_ID,与当前的遍历的用户的id,看看id是否大于环境变量MAX_ID 2、看看是否有这样的情况:用户名出现在lastlog,wtmp文件中,而在/etc/passwd中没有的

代码语言:javascript代码运行次数:0运行复制
if ( !nonuser(utmp_ent) && strncmp(utmp_ent.ut_line, "ftp", ) &&
	 (uid=localgetpwnam(localpwd,utmp_ent.ut_name)) != ULL )
		{
			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",
							ULL != localpwd->uname[slot] ?
							(char*)localpwd->uname[slot] : "(null)");
					   else
						  printf("deleted user uid(%d) not in passwd\n", *uid);
					   ++status;
					}
					userid[*uid]=TRUE;
				}
	}
	   }
}
检测可疑的没有tty记录的进程

检测的是/var/run/utmp或者/var/adm/utmpx,方法是比较的是ps命令与/var/run/utmp文件之间的差别

代码语言:javascript代码运行次数:0运行复制
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 == LOGI_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);
}

比如下面的检测结果,而我的/var/run/utmp中是没有tty7这个tty的记录的

代码语言:javascript代码运行次数:0运行复制
Checking `chkutmp'...  The tty of the following user process(es) were not found
 in /var/run/utmp !
! RUID          PID TTY    CMD
! root         1076 tty7   /usr/lib/xorg/Xorg -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2018-10-09,如有侵权请联系 cloudcommunity@tencent 删除进程字符串linux程序登录

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1207408.html

相关标签:无
上传时间: 2025-07-24 13:35:52

上一篇:没有libc6

下一篇:CTF PWN专用虚拟机

留言与评论(共有 12 条评论)
本站网友 如何注册商标
19分钟前 发表
fullpath);检测网络接口的异常代码语言:javascript代码运行次数:0运行复制 sniffer () { if [ "${ROOTDIR}" != "/" ]; then echo "not tested" return ${OT_TESTED} fi if [ "$SYSTEM" = "SunOS" ]; then return ${OT_TESTED} fi if [ "${EXPERT}" = "t" ]; then expertmode_output "./ifpromisc" -v return 5 fi if [ ! -x ./ifpromisc ]; then echo "not tested
本站网友 慢钱
13分钟前 发表
Rootkit一词更多地是指被作为驱动程序
本站网友 今日白金价
29分钟前 发表
&lastlog_ent
本站网友 4466kk
13分钟前 发表
(char *) &utmp_ent
本站网友 食品公司下载
3分钟前 发表
"opendir(%s)
本站网友 uqc
19分钟前 发表
方法是比较的是ps命令与/var/run/utmp文件之间的差别代码语言:javascript代码运行次数:0运行复制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 == LOGI_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
本站网友 吸血虫图片
16分钟前 发表
not in readdir output\n"
本站网友 铰链安装
30分钟前 发表
8
本站网友 通用电气能源
12分钟前 发表
) && (uid=localgetpwnam(localpwd
本站网友 伦敦时间现在几点
10分钟前 发表
&statinfo)) { fprintf(stderr
本站网友 昆明房网
25分钟前 发表
Possible LKM Trojan installed" fi dirs="/tmp" for i in /usr/share /usr/bin /usr/sbin /lib; do [ -d $i ] && dirs="$dirs $i" done if ./chkdirs $dirs; then if [ "${QUIET}" != "t" ]; then echo "chkdirs