Wednesday, January 16, 2008

Perl Password Cracker For Linux and Unix

As you may recall, from a few postings ago, we took a look at wrapping a popular password cracker in Unix and/or Linux shell scripting for ease of use.

In today's post, we're actually going to do the password cracking ourselves!

This code has been tested on Solaris Unix and RedHat Linux and is 100 percent guaranteed to be somewhat entertaining ;) Again, I feel obligated to note that this software is for recreational use only and is actually intended to help system administrators find weak passwords in order to maximize security (In tomorrow's post, we'll look at a way to help with generating new passwords that will have everyone on your watch begging to be able to create their own ;)

This script makes use of Perl's built-in crypt function, which works in much the same way as the standard Unix or Linux crypt function does. Since we haven't yet figured out how to break the level of encryption you, hopefully, have on your systems, this program could also be considered a password guesser.

I wrote this up so that it can be invoked simply by its name, like so:

./pwdcheck

and requires no argument. This version prompts for input. It could be easily modified to accept command line arguments, but I left that alone for now, since it's not the main aim of the script. This script is also very simple, as I wanted to demonstrate the shell script concept of password guessing in its purest form. If you choose to try and find a single password you would type the name in when prompted. For a list of passwords, you would type in the name of the list (absolute or relative) with passwords in it (one to a line). Then the script will check your /etc/shadow file for any passwords that match your guess.

It's no lie that this method of password cracking is far less sophisticated than the methods used by products like John The Ripper, etc. However, it does demonstrate how the crypt function works and what really goes on at the guts of all of those types of programs (JTR, for instance, uses fastcrypt and does its own word manipulation outside of the "guessing" routine).

Hope you enjoy this and find some use for it. Tomorrow, we'll look at a script that will produce random passwords (great for helping out with system administration) that you can use for input to this script.

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License


#!/usr/bin/perl
#
# pwdcheck - Simple password checker.
# Works with password file input, one
# password per line, or one password
# at a time. Must be root to execute!
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
#

print "Will you be checking one password or a list of them? [P or L]\n";
chomp($answer=<stdin>);
$answer=~ tr/A-Z/a-z/;
if ($answer eq "p") {
print "password to check?\n";
chomp($guess=<stdin>);
print "Do you keep your password entries in passwd,\n";
print "shadow, or another file? [P, S or O]\n";
chomp($reply=<stdin>);
$reply=~ tr/A-Z/a-z/;
if ($reply eq "s") {
open(SHADOW, "</etc/shadow");
} elsif ($reply eq "p") {
open(SHADOW, "</etc/passwd");
} elsif ($reply eq "o") {
print "What's the absolute pathname of the file?\n";
chomp($pathname=<stdin>);
if ( -f $pathname) {
open(SHADOW, "<$pathname");
} else {
print "I don't think it's there...\n";
exit;
}
} else {
print "Can't find that anywhere...\n";
exit;
}
@SHADOW=<SHADOW>;
foreach $LINE (@SHADOW) {
@line=split(/:/, $LINE);
$passwd{$line[1]} = $line[0];
}
foreach $PART (@SHADOW) {
@stab=split(/:/, $PART);
if (crypt($guess, $stab[1]) eq $stab[1]) {
print "Got $guess for user $passwd{$stab[1]}!\n";
$yes = 1;
}
}
if ( $yes eq 1) {
exit;
} else {
print "...Doesn't look like it...\n";
}
} elsif ($answer eq "l") {
print "Name of word file?\n";
chomp($passfile=<stdin>);
print "Absolute pathname of passwd, shadow or\n";
print "other relevant file?\n";
chomp($shadow=<stdin>);
open(SHADOW, "<$shadow");
@SHADOW=<SHADOW>;
foreach $LINE (@SHADOW) {
@line=split(/:/, $LINE);
$passwd{$line[1]} = $line[0];
}
close(SHADOW);
open(PWDFILE, "<$passfile");
@passfile=<PWDFILE>;
foreach $guess (@passfile) {
$guess=~ s/\s//g;
print "Checking for $guess ...\n";
open(SHADOW, "<shadow");
foreach $PART (@SHADOW) {
@stab=split(/:/, $PART);
if (crypt($guess, $stab[1]) eq $stab[1]) {
print "Got $guess for user $passwd{$stab[1]}!\n";
open(PD, ">>Passwords");
print PD "Login: $passwd{$stab[1]}\t\tPassword: $guess\n";
close(PD);
}
close(SHADOW);
}
}
} else {
print "Which part didn't you get?\n";
}
exit;


, Mike