Tuesday, October 16, 2012

Parallel Programming in Perl using Parallel::ForkManager

最簡單的  Perl 平行處理

使用 Parallel::ForkManager 這個 CPAN module

https://metacpan.org/module/Parallel::ForkManager


use Parallel::ForkManager;
 
$pm = new Parallel::ForkManager($MAX_PROCESSES);
 
foreach $data (@all_data) {
  # Forks and returns the pid for the child:
  my $pid = $pm->start and next;
 
   # do some work with $data in the child process ...
 
  $pm->finish; # Terminates the child process
}


寫了一個 Parallel 的 MD5 Bruteforce Cracker

#!/usr/bin/perl

use 5.012;
use warnings;

# MD5 Hash Bruteforce Kit
# original version by Iman Karim (iman.karim@smail.inf.fh-bonn-rhein-sieg.de)
# http://home.inf.fh-rhein-sieg.de/~ikarim2s/

# modified by xatier (xatierlike @gmail.com)
# Date : 10/15 2012
# This Cracker is by far not the fastest! only used to find "lost" passwords ;)
# run on my ubuntu server :P

my $ver = "02";

use Digest::MD5 qw(md5_hex);
use Time::HiRes qw(gettimeofday);
use Parallel::ForkManager;

# for parallel cracking
our $MAX_PROCESS_NUMBER = 25;

# charset
my $alpha = "";
$alpha .= "abcdefghijklmnopqrstuvwxyz" if ($ARGV[0] =~ "a");
$alpha .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ" if ($ARGV[0] =~ "A");
$alpha .= "1234567890"                 if ($ARGV[0]=~"d");
$alpha .= "~!@#\$%^&*()_+`-=[]\\{}|;':\",./<>?"  if ($ARGV[0]=~"x");


usage() if ($alpha eq "" or $ARGV[3] eq "");

if (length($ARGV[3]) != 32) {
    die "Sorry but it seems that the MD5 is not valid!\n";
};

say "Selected charset for attack =>  '$alpha'";
say "Going to Crack '$ARGV[3]'";
say "length from $ARGV[1] to $ARGV[2]...";
say "Press Enter to continue...";
my $key = <>;
system("mv key.txt key.txt.old");

# go!
for (my $t = $ARGV[1]; $t <= $ARGV[2]; $t++) {
    crack ($t);
}

sub usage {
    say<<EOF;   
    Charset can be: [aAdx]
    a = {'a','b','c',...}
    A = {'A','B','C',...}
    d = {'1','2','3',...}
    x = {'!','\"',' ',...}

    EXAMPLES:
       ./md5crack.pl ad 1 3 900150983cd24fb0d6963f7d28e17f72
            all lowercase Alphas and all digits
            length from 1 and 3 characters.
        ------------------------------
       ./md5crack.pl aA 3 3 900150983cd24fb0d6963f7d28e17f7;
            all lowercase Alphas and all uppercase Alphas;
            exactly 3 characters.
        ------------------------------
       ./md5crack.pl aAdx 1 10 900150983cd24fb0d6963f7d28e17f7;
            nearly every characte;
            length from 1 to 10 character;
EOF
    die "Quitting...\n";
}

sub crack {
    my $CharSet = shift;
    my @RawString = ();
    my @testdata = ();
    my @realbuf = ();
    my $BUFSIZ = $MAX_PROCESS_NUMBER;
    my $data_BUFSIZ = 100;
    my $data_count = 0;
    my $real_count = 0;
    push @RawString, 0 for (0 .. $CharSet - 1);

    do {
        for (my $i = 0; $i < $CharSet; $i++) {
            if ($RawString[$i] > length($alpha)-1) {
                if ($i == $CharSet-1) {
                    crack_parallel([@realbuf]);
                    say "Bruteforcing done with $CharSet Chars. No Results.";
                    return;
                }
                $RawString[$i+1]++;
                $RawString[$i] = 0;
            }
        }

        my $ret = "";
        $ret .= substr($alpha,$RawString[$_], 1) for (0 ..$CharSet-1);

        if ($data_count < $data_BUFSIZ) {
            push @testdata, $ret;
            $data_count++;
        }

        if ($data_count == $data_BUFSIZ) {
            push @realbuf, [@testdata];
            @testdata = ();
            $data_count = 0;
            $real_count++;
        }

        if ($real_count == $BUFSIZ) {
            crack_parallel([@realbuf]);
            @realbuf = ();
            $real_count = 0;
        }

        $RawString[0]++;

    } while ($RawString[$CharSet-1] < length($alpha));
}


sub crack_parallel {
    my $realbuf_ref = shift;

    my $pm = new Parallel::ForkManager($MAX_PROCESS_NUMBER);

    $pm->run_on_finish (
        sub {
            my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $ref) = @_;
            if (defined $ref) {
                say "$ref->[0] ==> $ref->[1]";
                open F, ">", "key.txt";
                say F "$ref->[0] ==> $ref->[1]";
                close F;
                $@ = "";   # shut up, error message!
                die "\n**** Password Cracked! ";
            }
        }
    );

    for my $r (@$realbuf_ref) {
        # paralleize the cracking md5s
        $pm->start and next;
        for my $text (@$r) {
            my $hash = md5_hex($text);
            say "$ARGV[3] != $hash ($text)";
            if ($ARGV[3] eq $hash) {
                $pm->finish(0, [$text, $hash]);
            }
        }
        $pm->finish(0);
    }
    $pm->wait_all_children;
}

No comments:

Post a Comment