Security Incidents mailing list archives

Re: Recognizing compromised binaries


From: dbrumley () RTFM STANFORD EDU (David Brumley)
Date: Wed, 23 Feb 2000 09:59:23 -0800


We little toolbox's of compiled binaries (some static...not all because
static semantics don't always work, esp. when trying to figure out a name
that goes w/ a process. trivial mod, I know but it's worked great to date)
at: http://security.stanford.edu/binaries/

Some of the directories are restricted per licensing (aka our license w/
sun), but linux is there.  I just do a:
mkdir /tmp/sec
cd /tmp/sec
tar zxvf anti-rootkit.tgz
chmod 500 *
export PATH=/tmp/sec:${PATH}

not fool proof, but often kitty proof.

-david

On Mon, 21 Feb 2000, Dominique Brezinski wrote:

At 08:39 PM 2/18/00 -0800, Stephen Friedl wrote:
vivid, but one small point I've not seen before in this forum. The
bad guy had compromised most of the obvious system binaries (ls,
ps, netstat, etc.) so it was hard to identify even what was wrong.

I recommend making a little tool kit on read-only media (CD_ROM is good)
that you can mount on a suspect system to do this kind of analysis (when
you don't know if anything has happened that warrants serious forensic
analysis).  You should only use statically compiled binaries in this tool
kit, and there are some environmental things to watch out for (I did a
little presentation at BlackHat Briefings last year that you can check out
here: http://www.blackhat.com/html/bh-usa-99/bh3-speakers.html)

Here is the source to a little program that will print out stat info for a
file *or* a directory and its contents (but will not recurse to
subdirectories)--it is probably better than ls for forensic purposes.  My
employer nor myself express any warranty, explicit or implied, of any kind
with regards to the following code or its fitness of use:
--------CUT HERE--------------
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>

char* FixupArg(char*, char*, int);

int main(int argc, char** argv)
{
    char                target[PATH_MAX + 1] = {'\0'};
    struct stat         statInfo;
    struct dirent*      pDirEntryInfo = NULL;
    DIR*                pDir = NULL;

    if (argc != 2)
    {
        printf("Usage: %s <filename or directory>\n", argv[0]);
        exit(1);
    }
    else
    {
      /* Initialize resources */
      if (FixupArg(argv[1], target, PATH_MAX) == NULL) {
        exit(0);
      }
    }

    if (lstat(target, &statInfo)) {
      printf("failed to lstat() file - errno %d\n", errno);
      exit(1);
    }
    printf("\n%s\n", target);
    printf("ctime: %s", asctime(gmtime(&(statInfo.st_ctime))));
    printf("atime: %s", asctime(gmtime(&(statInfo.st_atime))));
    printf("mtime: %s", asctime(gmtime(&(statInfo.st_mtime))));
    printf("owner: %d\ngroup: %d\nsize in bytes: %d\nINode number: %d\nfile gen
number: %d\n", statInfo.st_uid, statInfo.st_gid, statInfo.st_size,
statInfo.st_i
no, statInfo.st_gen);

    if (S_ISDIR(statInfo.st_mode)) {
      /* we have a directory, so recurse through it calling lstat() on each
       * entry as we go.
       */
      pDir = opendir(target);
      if (pDir == NULL) {
        printf("opendir() failed\n");
        exit(1);
      }
      for (pDirEntryInfo = readdir(pDir); \
           pDirEntryInfo != NULL; \
           pDirEntryInfo = readdir(pDir)) {
        char targetFile[PATH_MAX + 1] = {'\0'};

        if (!strncmp(pDirEntryInfo->d_name, ".", PATH_MAX) ||
            !strncmp(pDirEntryInfo->d_name, "..", PATH_MAX)) {
          continue;
        }
        else {
          strncpy(targetFile, target, PATH_MAX);
          strncat(targetFile, "/", PATH_MAX - strlen(targetFile));
          strncat(targetFile,
                  pDirEntryInfo->d_name,
                  PATH_MAX - strlen(targetFile));
        }
        if (lstat(targetFile, &statInfo)) {
          printf("failed lstat() file %s -errno %d\n", targetFile, errno);
          continue;
        }
        else {
          printf("\n%s\n", targetFile);
          printf("ctime: %s", asctime(gmtime(&(statInfo.st_ctime))));
          printf("atime: %s", asctime(gmtime(&(statInfo.st_atime))));
          printf("mtime: %s", asctime(gmtime(&(statInfo.st_mtime))));
          printf("owner: %d\ngroup: %d\nsize in bytes: %d\nINode number:
%d\nfil
e gen number: %d\n", statInfo.st_uid, statInfo.st_gid, statInfo.st_size,
statInf
o.st_ino, statInfo.st_gen);
        }

      } /* end for (readdir()) */
      closedir(pDir);

    } /* end if (S_ISDIR) */
    free(target);

    exit(0);
}


char* FixupArg(char* arg, char* fixedArg, int fixedArgLen)
{
  /* check if the arg looks to be absolute path */
  if (*arg == '/') {
    strncpy(fixedArg, arg, fixedArgLen);
  }
  else {
    /* looks like we have a relative path, so handle it appropriately */
    if (strlen(arg) < PATH_MAX && fixedArgLen >= PATH_MAX) {
      if (realpath(arg, fixedArg) == NULL) {
        printf("relative/absolute path translation failed\n");
        return (NULL);
      }
    }
    else {
      printf("Relative path given is too long or supplied buffer too small\n");
      return (NULL);
    }
  }
  return (fixedArg);
}

----------CUT HERE---------------------

The output looks like this:

dbrez@it[104]>./stat ../rstat

/home/dbrez/src/rstat
ctime: Tue Feb 22 00:57:25 2000
atime: Tue Feb 22 00:57:56 2000
mtime: Tue Feb 22 00:57:25 2000
owner: 6254
group: 229
size in bytes: 4096
INode number: 4015042
file gen number: 0

/home/dbrez/src/rstat/stat
ctime: Tue Feb 22 01:26:28 2000
atime: Tue Feb 22 01:26:28 2000
mtime: Tue Feb 22 01:26:28 2000
owner: 6254
group: 229
size in bytes: 24576
INode number: 4323271
file gen number: 0

/home/dbrez/src/rstat/rstat.c
ctime: Tue Feb 22 01:26:22 2000
atime: Tue Feb 22 01:26:22 2000
mtime: Tue Feb 22 01:26:22 2000
owner: 6254
group: 229
size in bytes: 3319
INode number: 1048607
file gen number: 0

---
Dominique Brezinski           Amazon.com Security
office (206) 266-6900         pager (888) 916-2747
8312 ADAB C5B2 1916 CBD8  150E 37CE 044E F45F B5E4


--
#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#
David Brumley - Stanford Computer Security - dbrumley () Stanford EDU
Phone: +1-650-723-2445    WWW: http://www.stanford.edu/~dbrumley
Fax:   +1-650-725-9121    PGP: finger dbrumley-pgp () sunset Stanford EDU
#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#+--+#
c:\winnt> secure_nt.exe
  Securing NT.  Insert Linux boot disk to continue......
            "I have opinions, my employer does not."



Current thread: