1#!/usr/bin/env perl 2 3## 4## Author......: See docs/credits.txt 5## License.....: MIT 6## 7 8use strict; 9use warnings; 10 11use Encode; 12use Crypt::RC4; 13use Digest::HMAC_MD5 qw (hmac_md5); 14use Digest::MD4 qw (md4); 15use Digest::MD5 qw (md5_hex); 16use POSIX qw (strftime); 17 18sub module_constraints { [[0, 256], [16, 16], [0, 27], [16, 16], [-1, -1]] } 19 20sub module_generate_hash 21{ 22 my $word = shift; 23 my $salt = shift; 24 my $user_principal_name = shift // "user\@domain.com"; 25 my $checksum = shift; 26 my $edata2 = shift; 27 28 my $k = md4 (encode ("UTF-16LE", $word)); 29 30 my $k1 = hmac_md5 ("\x08\x00\x00\x00", $k); 31 32 my $cleartext_ticket = '7981df3081dca01b3019a003020117a112041071e026814da2' . 33 '3f129f0e67a01b73f79aa11c301a3018a003020100a111180f32303138313033303039353' . 34 '831365aa206020460fdc6caa311180f32303337303931343032343830355aa40703050050' . 35 'c10000a511180f32303138313033303039353831365aa611180f323031383130333030393' . 36 '53831365aa711180f32303138313033303139353831365aa811180f323031383130333131' . 37 '30303433385aa90d1b0b545952454c4c2e434f5250aa20301ea003020101a11730151b066' . 38 'b72627467741b0b545952454c4c2e434f5250'; 39 40 if (defined $checksum) 41 { 42 $checksum = pack ("H*", $checksum); 43 } 44 else 45 { 46 my $nonce = unpack ("H*", random_bytes (8)); 47 48 $cleartext_ticket = $nonce . $cleartext_ticket; 49 50 $checksum = hmac_md5 (pack ("H*", $cleartext_ticket), $k1); 51 } 52 53 my $k3 = hmac_md5 ($checksum, $k1); 54 55 if (defined $edata2) 56 { 57 my $cipher_decrypt = Crypt::RC4->new ($k3); 58 59 my $ticket_decrypt = unpack ("H*", $cipher_decrypt->RC4 (pack ("H*", $edata2))); 60 61 my $check_correct = ((substr ($ticket_decrypt, 16, 4) eq "7981" && substr ($ticket_decrypt, 22, 2) eq "30")) || 62 ((substr ($ticket_decrypt, 16, 2) eq "79") && (substr ($ticket_decrypt, 20, 2) eq "30")) || 63 ((substr ($ticket_decrypt, 16, 4) eq "7982") && (substr ($ticket_decrypt, 24, 2) eq "30")); 64 65 if ($check_correct == 1) 66 { 67 $cleartext_ticket = $ticket_decrypt; 68 } 69 else # validation failed 70 { 71 # fake/wrong ticket (otherwise if we just decrypt/encrypt we end up with false positives all the time) 72 $cleartext_ticket = "0" x (length ($cleartext_ticket) + 16); 73 } 74 } 75 76 my $cipher = Crypt::RC4->new ($k3); 77 78 $edata2 = $cipher->RC4 (pack ("H*", $cleartext_ticket)); 79 80 my $tmp_hash = sprintf ('$krb5asrep$23$%s:%s$%s', $user_principal_name, unpack ("H*", $checksum), unpack ("H*", $edata2)); 81 82 return $tmp_hash; 83} 84 85sub module_verify_hash 86{ 87 my $line = shift; 88 89 my ($hash, $hash2, $word) = split (':', $line); 90 91 return unless defined $hash; 92 return unless defined $hash2; 93 return unless defined $word; 94 95 my @data = split ('\$', $hash); 96 97 return unless scalar @data == 4; 98 99 shift @data; 100 101 my $signature = shift @data; 102 my $algorithm = shift @data; 103 my $user_principal_name = shift @data; 104 105 return unless ($signature eq "krb5asrep"); 106 107 my @data2 = split ('\$', $hash2); 108 109 my $checksum = shift @data2; 110 my $edata2 = shift @data2; 111 112 return unless (length ($checksum) == 32); 113 return unless (length ($edata2) >= 64); 114 115 my $word_packed = pack_if_HEX_notation ($word); 116 117 my $new_hash = module_generate_hash ($word_packed, undef, $user_principal_name, $checksum, $edata2); 118 119 return ($new_hash, $word); 120} 121 1221; 123