Skip to content

mr-sk/pyLogCleaner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

pyLogCleaner

Linux Log Cleaner (wtmp, utmp & lastlog)

This python script will scrub (by replacing the current log files with altered ones) the utmp, wtmp & lastlog files. In order to do this we have to know the size and type of structure the data is kept it. We must know the size so we can determine the correct size "chunks" to read, and the structure to determine where (at what numerical index) the data we are searching for is stored. The structure of utmp/wtmp is

    struct utmp {
           short   ut_type;              /* Type of record */
           pid_t   ut_pid;               /* PID of login process */
           char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
           char    ut_id[4];             /* Terminal name suffix,
                                            or inittab(5) ID */
           char    ut_user[UT_NAMESIZE]; /* Username */
           char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
                                            kernel version for run-level
                                            messages */
           struct  exit_status ut_exit;  /* Exit status of a process
                                            marked as DEAD_PROCESS; not
                                            used by Linux init(8) */
           /* The ut_session and ut_tv fields must be the same size when
              compiled 32- and 64-bit.  This allows data files and shared
              memory to be shared between 32- and 64-bit applications. */

       #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
           int32_t ut_session;           /* Session ID (getsid(2)),
                                            used for windowing */
           struct {
               int32_t tv_sec;           /* Seconds */
               int32_t tv_usec;          /* Microseconds */
           } ut_tv;                      /* Time entry was made */
       #else
            long   ut_session;           /* Session ID */
            struct timeval ut_tv;        /* Time entry was made */
       #endif

           int32_t ut_addr_v6[4];        /* Internet address of remote
                                            host; IPv4 address uses
                                            just ut_addr_v6[0] */
           char __unused[20];            /* Reserved for future use */
       };

(taken from kernel.org). In order to break-up this datastructure into an numerically indexed array, we perform the following unpack (in bold)

    def scrubFile(filePath):
      newUtmp = ""
      with open(filePath, "rb") as f:
        bytes = f.read(UTMP_STRUCT_SIZE)
        while bytes != "":
          data = struct.unpack("hi32s4s32s256shhiii36x", bytes)
          if cut(data[4]) != usernameToRemove and cut(data[5]) != hostAddressToRemove:
              newUtmp += bytes
          bytes = f.read(UTMP_STRUCT_SIZE)
      f.close()
      return newUtmp

Which allows us to do the check for the username & address at [4] and [5]. To handle lastlog we again must know the datastructure and size

    struct lastlog
    {
    #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
      int32_t ll_time;
    #else
      __time_t ll_time; // 4
    #endif
    char ll_line[UT_LINESIZE]; // 32
    char ll_host[UT_HOSTSIZE]; // 256
    };
    # which is 292 bytes.

Lastlog is unique in that each entry in the file (the first index) corresponds with a UID. So as we iterate over each entry we check the 'index/id' against the desired UID and if they match, we do not copy that entry from the current lastlog file to the new, doctored file.

    def scrubLastlogFile(filePath, userName):
      pw = pwd.getpwnam(userName)
    uid= pw.pw_uid
      idCount = 0
      newLastlog = ''

      with open(filePath, "rb") as f:
        bytes = f.read(LASTLOG_STRUCT_SIZE)
        while bytes != "":
          data = struct.unpack("hh32s256s", bytes)
          if (idCount != uid):
            newLastlog += bytes
          idCount += 1
          bytes = f.read(LASTLOG_STRUCT_SIZE)
      return newLastlog

That's about it - nothing ground breaking here. At the time there wasn't an open source python implementation of utmp/wtmp/lastlog cleaning, so I wrote one.

About

Linux Log Cleaner (wtmp, utmp & lastlog)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages