mirror of
https://github.com/hashcat/hashcat
synced 2024-12-09 02:13:10 +01:00
195 lines
4.0 KiB
Perl
Executable File
195 lines
4.0 KiB
Perl
Executable File
#!/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};
|
|
|
|
die("Expected output for mode 1 (expected_cpu) isn't defined for rule: $rule") unless defined $case->{expected_cpu};
|
|
|
|
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_cpu}, $rule . " - mode 1");
|
|
}
|
|
|
|
# Mode 2: GPU mode, using -r
|
|
|
|
sub run_case_mode2
|
|
{
|
|
my $rule = shift;
|
|
|
|
my $case = $cases{$rule};
|
|
|
|
die("Expected output for mode 2 (expected_opencl) isn't defined for rule: $rule") unless defined $case->{expected_opencl};
|
|
|
|
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_opencl}, $rule . " - mode 2");
|
|
}
|
|
|
|
sub run_case_all_mods
|
|
{
|
|
my $rule = shift;
|
|
|
|
my $case = $cases{$rule};
|
|
|
|
run_case_mode1 ($rule) if defined $case->{expected_cpu};
|
|
run_case_mode2 ($rule) if defined $case->{expected_opencl};
|
|
}
|
|
|
|
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/cpu mode, 2 for GPU/opencl mode \n" .
|
|
" run all test cases if [rule] was not specified \n" .
|
|
" run test for both modes if [mode] was not specified \n" .
|
|
" --help will show this help message \n" .
|
|
"\n" .
|
|
"examples: \n" .
|
|
"run all available cases : perl $0 \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;
|
|
}
|