Advertisement
opexxx

john-netntlm.pl

Apr 7th, 2014
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 9.75 KB | None | 0 0
  1. #!/usr/bin/perl
  2. #
  3. #####################################################################
  4. #
  5. #   Written by JoMo-Kun <jmk at foofus.net> in 2007
  6. #   and placed in the public domain.
  7. #
  8. #   The purpose of this script is to aid with cracking a LM/NTLM
  9. #   challenge/response set, when part of the password is known. It
  10. #   was written with John's NetLM/NetNTLM formats and "halflmchall"
  11. #   Rainbow Tables in mind.
  12. #
  13. #   Example Scenario:
  14. #   Let's assume you've captured LM/NTLM challenge/response set for
  15. #   the password Cricket88!. You may be able to crack the first part
  16. #   (i.e. CRICKET) using "Half LM" Rainbow Tables. This script will
  17. #   use that value as a seed and attempt to crack the second part
  18. #   (i.e. "88!") via an incremental brute. It'll then use the NetNTLM
  19. #   response hash to crack the case-sensitive version of the entire
  20. #   password.  
  21. #
  22. #####################################################################
  23.  
  24. use Getopt::Long;
  25.  
  26. my $VERSION = "0.2";
  27. my %opt;
  28. my %data;
  29.  
  30. my $JOHN = "john";
  31.  
  32. GetOptions (
  33.   'seed=s'      => \$opt{'seed'},
  34.   'file=s'      => \$opt{'file'},
  35.   'help|h'      => sub { ShowUsage(); },
  36. );
  37.  
  38. sub showUsage {
  39.   print "john-netntlm.pl v$VERSION\n\n";
  40.   print "JoMo-Kun <jmk\@foofus.net>\n\n";
  41.   print "Usage: $0 [OPTIONS]\n";
  42.   print " $0\n";
  43.   print "   --seed [RainbowCrack/HalfLM Response Password]\n";
  44.   print "   --file [File Containing LM/NTLM challenge/responses (.lc format)]\n";
  45.   print "          Ex: Domain\\User:::LM response:NTLM response:challenge";
  46.   print "\n";
  47.   print " Ex:\n";
  48.   print " $0 --file capture.lc\n";
  49.   print " $0 --seed \"GERGE!!\"--file capture.lc\n";
  50.   print "\n";
  51.   exit(1);
  52. }
  53.  
  54. # Main
  55. {
  56.   if ( !defined($opt{'file'}) ) { &showUsage; }
  57.  
  58.   # Parse accounts to audit
  59.   open(HAND, $opt{'file'}) || die("Failed to open response file: $opt{'file'} -- $!");
  60.   @{ $data{'pairs'} } = <HAND>;
  61.   close(HAND);
  62.  
  63.   # Load information for any accounts previous cracked  
  64.   print STDERR "\n\n";
  65.   print STDERR "###########################################################################################\n";  
  66.  
  67.   open (HAND, "$JOHN -format:netlm -show $opt{'file'} |") || die("Failed to execute john: $!");
  68.   print STDERR "The following LM responses have been previously cracked:\n";
  69.   while(<HAND>) {
  70.     next if ( /\d+ password hashes cracked, \d+ left/ );
  71.     last if /^$/;
  72.     print "\t$_";
  73.     push @{ $data{'cracked-lm'} }, $_;
  74.   }
  75.   close(HAND);
  76.  
  77.   print STDERR "\nThe following NTLM responses have been previously cracked:\n";
  78.   open (HAND, "$JOHN -format:netntlm -show $opt{'file'} |") || die("Failed to execute john: $!");
  79.   while(<HAND>) {
  80.     next if ( /\d+ password hashes cracked, \d+ left/ );
  81.     last if /^$/;
  82.     print "\t$_";
  83.     push @{ $data{'cracked-ntlm'} }, $_;
  84.   }
  85.   close(HAND);
  86.  
  87.   mkdir("/tmp/john.$$");
  88.   my $tmpconf = &createConf();
  89.   my $tmpsession = "/tmp/john.$$/john.session";
  90.   my $tmpsessionlog = "/tmp/john.$$/john.session.log";
  91.   my $tmplog = "/tmp/john.$$/john.log";
  92.   #print STDERR "Created temporary configuration file: $tmpconf\n";
  93.  
  94.   # Crack case-sensitive version of password
  95.   my $tmpdict = "/tmp/john.$$/john.dict";
  96.   #print STDERR "Created temporary dictionary file: $tmpdict\n";
  97.  
  98.   foreach $credential_set ( @{ $data{'cracked-lm'} } ) {
  99.     my ($account,$lmpass,$bar,$netlm,$netntlm,$chall) = split(/:/, $credential_set);
  100.     next if ( grep(/^$account:/i, @{ $data{'cracked-ntlm'} }) );
  101.    
  102.     print STDERR "\n\n";
  103.     print STDERR "###########################################################################################\n";  
  104.     print STDERR "Performing NTLM case-sensitive crack for account: $account.\n";
  105.  
  106.     open(HAND, ">$tmpdict") || die("Failed to option file: $tmpdict -- $!");
  107.     print HAND "$lmpass";
  108.     close(HAND);
  109.  
  110.     open (HAND, "$JOHN -format:netntlm -config:$tmpconf -wordlist:$tmpdict -rules -user:\"$account\" -session:$tmpsession $opt{'file'} |") || die("Failed to execute john: $!");
  111.     while(<HAND>) { print; }
  112.     close(HAND);
  113.  
  114.     unlink $tmpdict || warn("Failed to unlink $tmpdict -- $!");
  115.   }
  116.  
  117.   print STDERR "\n\n";
  118.   print STDERR "###########################################################################################\n";  
  119.   print STDERR "Isolating accounts which have only had their LM response cracked.\n";
  120.  
  121.   foreach $credential_set ( @{ $data{'pairs'} } ) {
  122.     $credential_set =~ s/\\/\\\\/g;
  123.     my ($account,$foo,$bar,$netlm,$netntlm,$chall) = split(/:/, $credential_set);
  124.     if (lc($netlm) eq lc($netntlm)) {
  125.       print STDERR "LM response is not unique from NTLM response (skipping):\n\t$credential_set\n";
  126.       push  @{ $data{'pairs-ntlm'} }, $credential_set;
  127.     }
  128.     elsif ( @cracked = grep(/^$account:/i, @{ $data{'cracked-ntlm'} }) ) {
  129.       print STDERR "Account $account NTLM response previously cracked.\n";
  130.       #print "@cracked";
  131.     }
  132.     else {
  133.       print STDERR "Account $account LM response added to cracking list.\n";
  134.       push  @{ $data{'pairs-lm'} }, $credential_set;
  135.     }
  136.   }
  137.  
  138.   if ( defined($opt{'seed'}) ) {
  139.     print STDERR "\n\n";
  140.     print STDERR "###########################################################################################\n";  
  141.     print STDERR "Testing seed password to determine whether it is the actual password.\n";
  142.     open(HAND, ">$tmpdict") || die("Failed to option file: $tmpdict -- $!");
  143.     print HAND $opt{'seed'};
  144.     close(HAND);
  145.    
  146.     open (HAND, "$JOHN -format:netntlm -config:$tmpconf -wordlist:$tmpdict -rules -session:$tmpsession $opt{'file'} |") || die("Failed to execute john: $!");
  147.     while(<HAND>) {
  148.       print;
  149.       next if (/^guesses: .*time: / || (/^Loaded .* password hash /) || (/^No password hashes loaded/));
  150.       my ($account) = $_ =~ / \((.*)\)$/;
  151.      
  152.       # Remove accounts which just cracked from list
  153.       my $i = 0;
  154.       foreach $credential_set ( @{ $data{'pairs-lm'} } ) {
  155.         $account =~ s/\\/_/g;
  156.         $credential_set =~ s/\\\\/_/g;
  157.         if ( $credential_set =~  /^$account:/ ) {
  158.           splice(@{ $data{'pairs-lm'} }, $i, 1);
  159.         }
  160.         $i++;
  161.       }
  162.     }
  163.     close(HAND);
  164.     unlink $tmpdict || warn("Failed to unlink $tmpdict -- $!");
  165.  
  166.     my $tmppasswd = "/tmp/john.$$/john.passwd";
  167.     open(HAND, ">$tmppasswd") || die("Failed to open $tmppasswd: $!");
  168.     print HAND  @{ $data{'pairs-lm'} };
  169.     close(HAND);
  170.  
  171.     print STDERR "\n\n";
  172.     print STDERR "###########################################################################################\n";  
  173.     print STDERR "The hashes contained within $tmppasswd have not been cracked.\n";
  174.     print STDERR "Executing the following (this could take a while...):\n\n";
  175.     print STDERR "john -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd\n";
  176.     print STDERR "\n";
  177.     print STDERR " *If the passwords successfully crack, use this script again to crack the case-sensitive password\n";
  178.     print STDERR " without feeding a seed password\n";
  179.     print STDERR"\n\n";
  180.  
  181.     system("$JOHN -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd");
  182.     #exec("$JOHN -format:netlm -config:$tmpconf -external:HalfLM -incremental:LM -session:$tmpsession $tmppasswd");
  183.  
  184.     unlink $tmppasswd || warn("Failed to unlink $tmppasswd -- $!");
  185.   }
  186.   else {
  187.     print STDERR "\nNo seed supplied for testing.\n";
  188.   }
  189.  
  190.   #print STDERR "Removing temporary files and directory\n";
  191.   unlink $tmpconf, $tmplog, $tmpsession, $tmpsessionlog || warn("Failed to unlink temporary config files -- $!");
  192.   rmdir("/tmp/john.$$") || warn("Failed to delete temporary john directory -- $!");
  193. }
  194.  
  195. exit(0);
  196.  
  197. sub createConf {
  198.   my $tmpconf = "/tmp/john.$$/john.conf";
  199.   open(CONF, ">$tmpconf") || die("Failed to open $tmpconf: $!");
  200.  
  201.   # Define character keyspace
  202.   print CONF "[Incremental:LM]\n";
  203.   print CONF "File = \$JOHN/lanman.chr\n";
  204.   print CONF "MinLen = 1\n";
  205.  
  206.   # John compiled for MaxLen <= 8
  207.   if (14 - length($opt{'seed'}) > 8) {
  208.     print CONF "MaxLen = 8\n";
  209.   } else {
  210.     print CONF "MaxLen = ", 14 - length($opt{'seed'}), "\n";
  211.   }
  212.   print CONF "CharCount = 69\n\n";
  213.  
  214.   # Add external filter to handle uncracked characters
  215.   if ($opt{'seed'} ne "") {
  216.     my $i; $j;
  217.     my @seed = split(//, $opt{'seed'});
  218.    
  219.     print CONF "[List.External:HalfLM]\n";
  220.     print CONF "void init()\n";
  221.     print CONF "{\n";
  222.     print CONF "  word[14] = 0;\n";
  223.     print CONF "}\n\n";  
  224.    
  225.     print CONF "void filter()\n";
  226.     print CONF "{\n";
  227.  
  228.     my $len = length($opt{'seed'});
  229.     for ($i = 13, $j = 13 - $len; $i>=0; $i--) {
  230.       if ($i >= $len) {
  231.         print CONF "  word[$i] = word[$j];\n";
  232.         $j--;
  233.       } else {
  234.         print CONF "  word[$i] = \'$seed[$i]\';\n";
  235.       }
  236.     }
  237.    
  238.     print CONF "}\n\n";
  239.   }
  240.  
  241.   # Add custom wordlist to utilize NTLM hash for character case cracking
  242.   print CONF "[List.Rules:Wordlist]\n";
  243.   print CONF ":\n";
  244.   print CONF "-c T0Q\n";
  245.   print CONF "-c T1QT[z0]\n";
  246.   print CONF "-c T2QT[z0]T[z1]\n";
  247.   print CONF "-c T3QT[z0]T[z1]T[z2]\n";
  248.   print CONF "-c T4QT[z0]T[z1]T[z2]T[z3]\n";
  249.   print CONF "-c T5QT[z0]T[z1]T[z2]T[z3]T[z4]\n";
  250.   print CONF "-c T6QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]\n";
  251.   print CONF "-c T7QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]\n";
  252.   print CONF "-c T8QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]\n";
  253.   print CONF "-c T9QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]\n";
  254.   print CONF "-c TAQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]\n";
  255.   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";
  256.   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";
  257.   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";
  258.  
  259.   close(CONF);
  260.  
  261.   return $tmpconf;
  262. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement