Files
metasploit-gs/data/john/run.linux.x86.any/netntlm.pl
T
Brandon Turner 83d1f8d499 Compile John the Ripper against libssl 1.0.0
We use OpenSSL 1.0.0 in installed environments.  Previously, John the
Ripper was compiled against 0.9.8 which prevented it from running.  This
recompiles the same version (jtr 1.7.8 jumbo 2) against OpenSSL 1.0.0.

[FIXRM #7834]
2013-03-25 17:12:51 -05:00

263 lines
9.4 KiB
Perl

#!/usr/bin/perl
#
#####################################################################
#
# Written by JoMo-Kun <jmk at foofus.net> in 2007
# and placed in the public domain.
#
# The purpose of this script is to aid with cracking a LM/NTLM
# challenge/response set, when part of the password is known. It
# was written with John's NetLM/NetNTLM formats and "halflmchall"
# Rainbow Tables in mind.
#
# Example Scenario:
# Let's assume you've captured LM/NTLM challenge/response set for
# the password Cricket88!. You may be able to crack the first part
# (i.e. CRICKET) using "Half LM" Rainbow Tables. This script will
# use that value as a seed and attempt to crack the second part
# (i.e. "88!") via an incremental brute. It'll then use the NetNTLM
# response hash to crack the case-sensitive version of the entire
# password.
#
#####################################################################
use Getopt::Long;
my $VERSION = "0.2";
my %opt;
my %data;
my $JOHN = "john";
GetOptions (
'seed=s' => \$opt{'seed'},
'file=s' => \$opt{'file'},
'help|h' => sub { ShowUsage(); },
);
sub showUsage {
print "john-netntlm.pl v$VERSION\n\n";
print "JoMo-Kun <jmk\@foofus.net>\n\n";
print "Usage: $0 [OPTIONS]\n";
print " $0\n";
print " --seed [RainbowCrack/HalfLM Response Password]\n";
print " --file [File Containing LM/NTLM challenge/responses (.lc format)]\n";
print " Ex: Domain\\User:::LM response:NTLM response:challenge";
print "\n";
print " Ex:\n";
print " $0 --file capture.lc\n";
print " $0 --seed \"GERGE!!\"--file capture.lc\n";
print "\n";
exit(1);
}
# Main
{
if ( !defined($opt{'file'}) ) { &showUsage; }
# Parse accounts to audit
open(HAND, $opt{'file'}) || die("Failed to open response file: $opt{'file'} -- $!");
@{ $data{'pairs'} } = <HAND>;
close(HAND);
# Load information for any accounts previous cracked
print STDERR "\n\n";
print STDERR "###########################################################################################\n";
open (HAND, "$JOHN -format:netlm -show $opt{'file'} |") || die("Failed to execute john: $!");
print STDERR "The following LM responses have been previously cracked:\n";
while(<HAND>) {
next if ( /\d+ password hashes cracked, \d+ left/ );
last if /^$/;
print "\t$_";
push @{ $data{'cracked-lm'} }, $_;
}
close(HAND);
print STDERR "\nThe following NTLM responses have been previously cracked:\n";
open (HAND, "$JOHN -format:netntlm -show $opt{'file'} |") || die("Failed to execute john: $!");
while(<HAND>) {
next if ( /\d+ password hashes cracked, \d+ left/ );
last if /^$/;
print "\t$_";
push @{ $data{'cracked-ntlm'} }, $_;
}
close(HAND);
mkdir("/tmp/john.$$") || die;
my $tmpconf = &createConf();
my $tmpsession = "/tmp/john.$$/john.session";
my $tmpsessionlog = "/tmp/john.$$/john.session.log";
my $tmplog = "/tmp/john.$$/john.log";
#print STDERR "Created temporary configuration file: $tmpconf\n";
# Crack case-sensitive version of password
my $tmpdict = "/tmp/john.$$/john.dict";
#print STDERR "Created temporary dictionary file: $tmpdict\n";
foreach $credential_set ( @{ $data{'cracked-lm'} } ) {
my ($account,$lmpass,$bar,$netlm,$netntlm,$chall) = split(/:/, $credential_set);
next if ( grep(/^$account:/i, @{ $data{'cracked-ntlm'} }) );
print STDERR "\n\n";
print STDERR "###########################################################################################\n";
print STDERR "Performing NTLM case-sensitive crack for account: $account.\n";
open(HAND, ">$tmpdict") || die("Failed to option file: $tmpdict -- $!");
print HAND "$lmpass";
close(HAND);
open (HAND, "$JOHN -format:netntlm -config:$tmpconf -wordlist:$tmpdict -rules -user:\"$account\" -session:$tmpsession $opt{'file'} |") || die("Failed to execute john: $!");
while(<HAND>) { print; }
close(HAND);
unlink $tmpdict || warn("Failed to unlink $tmpdict -- $!");
}
print STDERR "\n\n";
print STDERR "###########################################################################################\n";
print STDERR "Isolating accounts which have only had their LM response cracked.\n";
foreach $credential_set ( @{ $data{'pairs'} } ) {
$credential_set =~ s/\\/\\\\/g;
my ($account,$foo,$bar,$netlm,$netntlm,$chall) = split(/:/, $credential_set);
if (lc($netlm) eq lc($netntlm)) {
print STDERR "LM response is not unique from NTLM response (skipping):\n\t$credential_set\n";
push @{ $data{'pairs-ntlm'} }, $credential_set;
}
elsif ( @cracked = grep(/^$account:/i, @{ $data{'cracked-ntlm'} }) ) {
print STDERR "Account $account NTLM response previously cracked.\n";
#print "@cracked";
}
else {
print STDERR "Account $account LM response added to cracking list.\n";
push @{ $data{'pairs-lm'} }, $credential_set;
}
}
if ( defined($opt{'seed'}) ) {
print STDERR "\n\n";
print STDERR "###########################################################################################\n";
print STDERR "Testing seed password to determine whether it is the actual password.\n";
open(HAND, ">$tmpdict") || die("Failed to option file: $tmpdict -- $!");
print HAND $opt{'seed'};
close(HAND);
open (HAND, "$JOHN -format:netntlm -config:$tmpconf -wordlist:$tmpdict -rules -session:$tmpsession $opt{'file'} |") || die("Failed to execute john: $!");
while(<HAND>) {
print;
next if (/^guesses: .*time: / || (/^Loaded .* password hash /) || (/^No password hashes loaded/));
my ($account) = $_ =~ / \((.*)\)$/;
# Remove accounts which just cracked from list
my $i = 0;
foreach $credential_set ( @{ $data{'pairs-lm'} } ) {
$account =~ s/\\/_/g;
$credential_set =~ s/\\\\/_/g;
if ( $credential_set =~ /^$account:/ ) {
splice(@{ $data{'pairs-lm'} }, $i, 1);
}
$i++;
}
}
close(HAND);
unlink $tmpdict || warn("Failed to unlink $tmpdict -- $!");
my $tmppasswd = "/tmp/john.$$/john.passwd";
open(HAND, ">$tmppasswd") || die("Failed to open $tmppasswd: $!");
print HAND @{ $data{'pairs-lm'} };
close(HAND);
print STDERR "\n\n";
print STDERR "###########################################################################################\n";
print STDERR "The hashes contained within $tmppasswd have not been cracked.\n";
print STDERR "Executing the following (this could take a while...):\n\n";
print STDERR "john -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd\n";
print STDERR "\n";
print STDERR " *If the passwords successfully crack, use this script again to crack the case-sensitive password\n";
print STDERR " without feeding a seed password\n";
print STDERR"\n\n";
system("$JOHN -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd");
#exec("$JOHN -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd");
unlink $tmppasswd || warn("Failed to unlink $tmppasswd -- $!");
}
else {
print STDERR "\nNo seed supplied for testing.\n";
}
#print STDERR "Removing temporary files and directory\n";
unlink $tmpconf, $tmplog, $tmpsession, $tmpsessionlog || warn("Failed to unlink temporary config files -- $!");
rmdir("/tmp/john.$$") || warn("Failed to delete temporary john directory -- $!");
}
exit(0);
sub createConf {
my $tmpconf = "/tmp/john.$$/john.conf";
open(CONF, ">$tmpconf") || die("Failed to open $tmpconf: $!");
# Define character keyspace
print CONF "[Incremental:LM]\n";
print CONF "File = \$JOHN/lanman.chr\n";
print CONF "MinLen = 1\n";
# John compiled for MaxLen <= 8
if (14 - length($opt{'seed'}) > 8) {
print CONF "MaxLen = 8\n";
} else {
print CONF "MaxLen = ", 14 - length($opt{'seed'}), "\n";
}
print CONF "CharCount = 69\n\n";
# Add external filter to handle uncracked characters
if ($opt{'seed'} ne "") {
my $i; $j;
my @seed = split(//, $opt{'seed'});
print CONF "[List.External:HalfLM]\n";
print CONF "void init()\n";
print CONF "{\n";
print CONF " word[14] = 0;\n";
print CONF "}\n\n";
print CONF "void filter()\n";
print CONF "{\n";
my $len = length($opt{'seed'});
for ($i = 13, $j = 13 - $len; $i>=0; $i--) {
if ($i >= $len) {
print CONF " word[$i] = word[$j];\n";
$j--;
} else {
print CONF " word[$i] = \'$seed[$i]\';\n";
}
}
print CONF "}\n\n";
}
# Add custom wordlist to utilize NTLM hash for character case cracking
print CONF "[List.Rules:Wordlist]\n";
print CONF ":\n";
print CONF "-c T0Q\n";
print CONF "-c T1QT[z0]\n";
print CONF "-c T2QT[z0]T[z1]\n";
print CONF "-c T3QT[z0]T[z1]T[z2]\n";
print CONF "-c T4QT[z0]T[z1]T[z2]T[z3]\n";
print CONF "-c T5QT[z0]T[z1]T[z2]T[z3]T[z4]\n";
print CONF "-c T6QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]\n";
print CONF "-c T7QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]\n";
print CONF "-c T8QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]\n";
print CONF "-c T9QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]\n";
print CONF "-c TAQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]\n";
print CONF "-c TBQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]\n";
print CONF "-c TCQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB]\n";
print CONF "-c TDQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB]T[zC]\n";
close(CONF);
return $tmpconf;
}