diff --git a/tools/rules-test-cases.yaml b/tools/rules-test-cases.yaml new file mode 100644 index 000000000..1dec1ed2c --- /dev/null +++ b/tools/rules-test-cases.yaml @@ -0,0 +1,796 @@ +--- +:: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + AbCd + abcd + ABCD + +l: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abcd + abcd + abcd + +u: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + ABCD + ABCD + ABCD + +c: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + Abcd + Abcd + Abcd + +C: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aBCD + aBCD + aBCD + +t: + input: | + AbCd + abcd + ABCD + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aBcD + ABCD + abcd + +T5: + input: | + AbCde + abcdef + ABCDEFg + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + AbCde + abcdeF + ABCDEfg + +r: + input: | + AbCd + abcd + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + dCbA + dcba + +d: + input: | + 3abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 3abc3abc + +ddd: + input: | + 3ab + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 3ab3ab3ab3ab3ab3ab3ab3ab + +p0: + input: | + 3abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 3abc + +p3: + input: | + 3abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 3abc3abc3abc3abc + +f: + input: | + 3abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 3abccba3 + +'{': + input: | + 3abc + a + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abc3 + a + +'}': + input: | + 3abc + a + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + c3ab + a + +$1$2: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abc12 + +^1^2: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 21abc + +'[': + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + + bc + +']': + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + + ab + +D3: + input: | + abc + abcd + abcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abc + abc + abce + +x14: + input: | + a + abc + abcde + abcdef + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc + bcde + bcde + +O22: + input: | + a + ab + abc + abcd + abcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abc + ab + abe + +O04: + input: | + a + abc + abcd + abcde + abcdef + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc + + e + ef + +i3!: + input: | + a + abc + abcd + abcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc! + abc!d + abc!de + +o3!: + input: | + a + abc + abcd + abcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc + abc! + abc!e + +'''4': + input: | + a + abc + abcd + abcde + abcdef + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + 123456790abcdefghijklmnopqrstuvwxyz + 123456790abcdefghijklmnopqrstuvwxyzA + 123456790abcdefghijklmnopqrstuvwxyzAB + 123456790abcdefghijklmnopqrstuvwxyzABC + 123456790abcdefghijklmnopqrstuvwxyzABCDEF + + expected_output: | + a + abc + abcd + abcd + abcd + +sab: + input: | + 123b + a123ba + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 123b + b123bb + +saa: + input: | + 123b + a123ba + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 123b + a123ba + +'@a': + input: | + 123b + aaa + a123ba + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 123b + + 123b + +z0: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abc + +z3: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aaaabc + +Z0: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abc + +Z3: + input: | + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abcccc + +q: + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aa + aabbcc + +qqq: + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aaaaaaaa + aaaaaaaabbbbbbbbcccccccc + +uMlX134: + mode: 1 + input: | + a + abc + abcd + abcdef + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + abcdBCD + abcdBCDef + +uMl4: + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aA + abcABC + +uMl6: + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + Aa + ABCabc + +<0: + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + +<1: + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + +'>0': + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc + +'>2': + mode: 1 + input: | + a + ab + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + ab + abc + +'!a': + mode: 1 + input: | + 1 + ab + abc + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + 1 + bcde + +/a: + mode: 1 + input: | + 1 + ab + abc + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + ab + abc + +(a: + mode: 1 + input: | + 1 + ab + bac + abc + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + ab + abc + +)c: + mode: 1 + input: | + 1 + ab + bac + abc + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + bac + abc + +=2c: + mode: 1 + input: | + 1 + ab + bac + abc + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + bac + abc + +'%2a': + mode: 1 + input: | + a + aa + aaa + aaaa + bcde + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + aaa + aaaa + +Q: + mode: 1 + input: | + a + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abc + +rMrQ: + mode: 1 + input: | + ab + abcba + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + ab + +k: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ba + bac + +K: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ba + acb + +'*24': + input: | + a + ab + abc + abcd + abcde + abcdef + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abc + abcd + abedc + abedcf + +L2: + input: | + a + ab + ab! + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abB + +R2: + input: | + a + ab + abB + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + ab! + ++2: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abd + +-2: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abb + +.2: + input: | + a + ab + abc + abcd + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abc + abdd + +',2': + input: | + a + ab + abc + abcd + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + ab + abb + abbd + +y2: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrst + 123456790abcdefghijklmnopqrstu + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abab + ababc + 12123456790abcdefghijklmnopqrst + +Y2: + input: | + a + ab + abc + 123456790abcdefghijklmnopqrst + 123456790abcdefghijklmnopqrstu + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + a + abab + abcbc + 123456790abcdefghijklmnopqrstst + +E: + input: | + a bc + ab c + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + A Bc + Ab C + Abc + +e-: + input: | + a-bc + ab-c + abc + 123456790abcdefghijklmnopqrstuvw + 123456790abcdefghijklmnopqrstuvwx + + expected_output: | + A-Bc + Ab-C + Abc diff --git a/tools/test_rules.pl b/tools/test_rules.pl new file mode 100644 index 000000000..7247196c8 --- /dev/null +++ b/tools/test_rules.pl @@ -0,0 +1,194 @@ +#!/usr/bin/env perl + +## +## Author......: See docs/credits.txt +## License.....: MIT +## + +use strict; +use warnings; +use Digest::MD5 qw (md5_hex); +use File::Basename qw (dirname); +use YAML::XS "LoadFile"; +use Test::More; + +# Use `eq_or_diff` from Test::Differences if it's available for an easier to read comparison +# between expected and actual output. +# Fall back to `is` from Test::More if it isn't available. + +BEGIN +{ + if (!eval q{ use Test::Differences; 1 }) + { + *eq_or_diff = \&is; + } +} + + +my $hashcat = "./hashcat"; +my $OPTS = "--stdout --force"; +my $CURRENT_DIR = dirname (__FILE__); +my $OUT_DIR = $CURRENT_DIR . "/". "rules-test"; + +mkdir $OUT_DIR || die $! unless -d $OUT_DIR; + +# Make sure to cleanup on forced exit +$SIG{INT} = \&cleanup_and_exit; + +my %cases = load_cases (); + +if (scalar @ARGV > 2 || defined $ARGV[0] && $ARGV[0] eq '--help') +{ + usage_die (); +} +elsif (scalar @ARGV == 1) +{ + my $rule = $ARGV[0]; + + die ("No test case was found for rule: $rule") unless exists $cases{$rule}; + + run_case_all_mods ($rule); +} +elsif (scalar @ARGV == 2) +{ + my $rule = $ARGV[0]; + my $mode = $ARGV[1]; + + die ("No test case was found for rule: $rule") unless exists $cases{$rule}; + + if ($mode == 1) + { + run_case_mode1 ($rule); + } + elsif ($mode == 2) + { + run_case_mode2 ($rule); + } + else + { + die ("Invalid mode: $mode. Mode can be either 1 or 2."); + } +} +else +{ + run_case_all_mods ($_) for (sort keys %cases); +} + +cleanup (); + +done_testing (); + + +# Mode 1: host mode, using -j + +sub run_case_mode1 +{ + my $rule = shift; + + my $case = $cases{$rule}; + my $input_file = input_to_file ($case, $rule); + + my $quoted_rule = quotemeta ($rule); + my $actual_output = qx($hashcat $OPTS -j $quoted_rule $input_file); + + eq_or_diff ($actual_output, $case->{expected_output}, $rule . " - mode 1"); +} + +# Mode 2: GPU mode, using -r + +sub run_case_mode2 +{ + my $rule = shift; + + my $case = $cases{$rule}; + my $input_file = input_to_file ($case, $rule); + my $rule_file = rule_to_file ($rule); + + my $quoted_rule = quotemeta ($rule); + my $actual_output = qx($hashcat $OPTS -r $rule_file $input_file); + + eq_or_diff ($actual_output, $case->{expected_output}, $rule . " - mode 2"); +} + +sub run_case_all_mods +{ + my $rule = shift; + + my $case = $cases{$rule}; + + if (defined $case->{mode}) + { + run_case_mode1 ($rule) if $case->{mode} == 1; + run_case_mode2 ($rule) if $case->{mode} == 2; + } + else + { + run_case_mode1 ($rule); + run_case_mode2 ($rule); + } +} + +sub input_to_file +{ + my $case = shift; + my $rule = shift; + + my $file_name = $OUT_DIR . "/" . rule_file_name ($rule); + open my $fh, ">", $file_name || die $!; + print $fh $case->{input}; + close $fh; + + return $file_name; +} + +sub rule_to_file +{ + my $rule = shift; + + my $file_name = $OUT_DIR . "/" . rule_file_name ($rule, "rule"); + open my $fh, ">", $file_name || die $!; + print $fh $rule; + close $fh; + + return $file_name; +} + +sub rule_file_name +{ + my $rule = shift; + my $ext = shift || "in"; + + return sprintf ("rule-%s.%s", md5_hex ($rule), $ext); +} + +sub usage_die +{ + die ("usage: $0 [rule] [mode] \n" . + " [mode]: 1 for host mode, 2 for GPU mode \n" . + " If [rule] was not specified, run all test cases \n" . + " If [mode] was not specified, run test for all modes \n" . + "\n" . + "examples: \n" . + "run i3! case on modes 1 & 2 : perl $0 i3! \n" . + "run O04 case on mode 1 : perl $0 O04 1 \n" . + "run sab case on mode 2 : perl $0 sab 2 \n"); +} + +sub load_cases +{ + my $file_path = $CURRENT_DIR . "/" . "rules-test-cases.yaml"; + return %{ LoadFile($file_path) }; +} + +sub cleanup +{ + unlink <$OUT_DIR/*.in $OUT_DIR/*.rule>; + rmdir $OUT_DIR; +} + +sub cleanup_and_exit +{ + cleanup (); + done_testing (); + exit 0; +}