#!/usr/bin/perl -w # # bsvejk -- foofus.net # # How long until the passwords got cracked? Consider the .cel file as # the global history of how long it took for stuff to get cracked. # # If you want a global .cel file there needs to be flocking on the .cel file. use strict; use vars qw(%time %method %user %pass $pwdumpfile $ntlmpotfile $ntlmjohn); #$potsize %pass %output @pwdump $pwdumpfile #$logfile %loginlm1 %loginlm2 %loginntlm %lm1 %lm2 %ntlm %got1 %got2 #$show_hash %pfsize @output %output_log %output_user); $ntlmpotfile = '/h/lib/passwd/data/john/john.pot'; $ntlmjohn = '/usr/sbin/john'; if(not (-e $ntlmpotfile)) { print STDERR "john ntlm potfile doesn't exit at: $ntlmpotfile.\n"; print STDERR "ntlm cracking may not work.\n"; } if(not (-e $ntlmjohn)) { print STDERR "john ntlm binary doesn't exist at: $ntlmjohn.\n"; print STDERR "ntlm cracking won't work.\n"; } use FileHandle; autoflush STDOUT 1; $pwdumpfile = shift; if(not defined($pwdumpfile)) { die "Please specify pwdump file as first argument.\n"; } if(not (-e $pwdumpfile)) { die "pwdump file '$pwdumpfile' must exist.\n"; } my($celfile) = shift || "/h/lib/passwd/data/john/john.cel"; if(not (-e $celfile)) { die "cel file '$celfile' must exist.\n"; } # Here's the cel file: # 0:00:00:29 wordlist p19lga1 $LM$381616803F513ECE GOBLYN # 0:00:00:29 wordlist 000059:2 $LM$F10997E5DB47284A MM8 # 0:00:00:29 wordlist p64emil:1 $LM$1FCCAA918F7AA0A3 TASTEBU sub process_celfile { my($cf) = @_; open CF, $cf or die "Can't open '$cf': $!"; while() { chomp; my($time,$method,$user,$hash,$pass) = split /\t/,$_,5; $hash =~ s/^\$..\$//; $hash = lc($hash); $time{$hash} = $time; $method{$hash} = $method; $user{$hash} = $user; $pass{$hash} = $pass; } #my $np = 'AAD3B435B51404EE'; my $np = lc('AAD3B435B51404EE'); $pass{$np} = ''; $time{$np} = '0:00:00:00'; $method{$np} = 'built-in'; } process_potfile($ntlmpotfile); #process_potfile($potfile); process_celfile($celfile); #process_potfile('/home/bsvejk/src/john-1.6.37/ntpot.pot'); #process_potfile('/home/bsvejk/src/ntlm/john-1.6.37/run/john.pot'); process_pwdump($pwdumpfile); # process_log(); # print_empties() ; sub splitlm { my($lm) = @_; if(length($lm) < 32) { return $lm, ''; } my($lm1, $lm2); $lm1 = substr($lm,0,16); $lm2 = substr($lm,16,16); $lm1 = lc($lm1); $lm2 = lc($lm2); return $lm1, $lm2; } sub timeinsecs { my($t) = @_; my($days,$hours,$mins,$secs) = split(/:/,$t); return $secs + (($days*24+ $hours)*60+$mins)*60; } sub timegt { my($a, $b) = @_; my($ta,$tb) = (timeinsecs($a),timeinsecs($b)); return $ta <=> $tb; } sub process_potfile { my($potfile) = @_; if(not (-r $potfile) or (-s $potfile) <= 0) { return; } open PF, "$potfile" or die "Can't open potfile '$potfile': $!"; while() { chomp; my($hash,$pw) = split /:/,$_,2; next unless ((/^\$LM\$/i) || (/^\$NT\$/i)); $hash =~ s/^\$..\$//; $pass{lc($hash)} = $pw; } } sub process_pwdump { my($pwdumpfile) = @_; # The pw file won't change over time. open PW, $pwdumpfile or die "Can't open pwdumpfile '$pwdumpfile': $!"; my(@pwdump) = (); my @ntwords; foreach (@pwdump) { chomp; next if(/^\s*$/); my($login,$uid,$lm,$nt,@rest) = split /:/; my($lm1,$lm2) = splitlm($lm); if($lm2 eq '') { print STDERR "Error: short lm hash: $login $uid $lm $nt\n"; next; } if(defined $pass{$lm1} and defined $pass{$lm2} and not defined $pass{$nt}) { push @ntwords, $pass{$lm1}.$pass{$lm2}; } } john_get_nt_passwords(@ntwords); my $pwc = my $ntc = my $tlc = my $nthc = 0; foreach (@pwdump) { chomp; next if(/^\s*$/); ++$tlc; my($login,$uid,$lm,$nt,@rest) = split /:/; $nt = lc($nt); my($lm1,$lm2) = splitlm($lm); # output: user,lm,ntlm,time my $passout = ''; my $ntout = ''; if(defined($pass{$lm1}) and defined($pass{$lm2})) { ++$pwc; $passout = $pass{$lm1}.$pass{$lm2}; if(not defined $pass{$nt}) { $ntout = "HARD_NT_PASS:$nt"; ++$nthc; } } else { if(defined $pass{$lm1}) { $passout = '('.$pass{$lm1}.':-)'; } else { if(defined $pass{$lm2}) { $passout = '(-:'.$pass{$lm2}.')'; } } } if(defined($pass{$nt})) { ++$ntc; $ntout = $pass{$nt}; } my $time = 'N/C'; if(defined $time{$lm1} and defined $time{$lm2}) { if(timegt($time{$lm1},$time{$lm2}) > 0) { $time = $time{$lm1}; } else { $time = $time{$lm2} } } elsif(defined $time{$nt}) { $time = $time{$nt}; } print "$login\t$passout\t$ntout\t$time\n"; } print STDERR "Total: $tlc\tHard: $nthc\tNT: $ntc\tLM: $pwc\n"; } sub john_get_nt_passwords { my(@words) = @_; my $nw = scalar(@words); if($nw < 1) { return; } print STDERR "Running john-ntlm on $nw words.\n"; my $tmppw = "/tmp/acpl$$.tmp"; my $tmplog = "/tmp/acpl$$"; open OF, ">$tmppw" or die "Can't open '$tmppw': $!"; my $ctr = 0; my %output; foreach my $passout (@words) { if(not defined $output{$passout}) { print OF join "\n", &allcases($passout); print OF "\n"; ++$ctr; $output{$passout} = 1; } } close OF; if($ctr > 0) { `$ntlmjohn -format:NT -w:$tmppw -session:$tmplog $pwdumpfile 2>&1 /dev/null`; process_potfile($ntlmpotfile); } unlink "$tmppw", "$tmplog.log", "$tmplog.rec"; } sub allcases { my($word) = @_; if(length($word) == 0) { return ''; } my($let, $rest) = split(//,$word,2); my(@rests) = &allcases($rest); my @results; foreach my $rest (@rests) { if(uc($let) eq lc($let)) { push @results, $let.$rest; } else { push @results, uc($let).$rest, lc($let).$rest; } } return @results; }