#!/usr/bin/perl -w

# This fantastic piece of code is copyright 2003 Michael Sconzo.
# Feel free to use it as you see fit.  It would be nice if you 
# update it to send me what you added etc.. so I can see if 
# anybody is using this and if so what for.
# questions?  msconzo@tamu.edu

# This program is designed to brute force a javascript 
# implementation like the one at 
# http://www.dynamicdrive.com/dynamicindex9/password.htm
# Simply because there is no good protection for a scheme like
# that one.  So, this was an excercise in some Math, and problem
# solving to keep me on my toes.  So, please don't use this for
# evil.

# Thanks to Ian Lyte <ianlyte@hotmail.com> for helping me test this
# as well as feature requests.  and Jeff B. for checking the code, and
# pointing out that I had a few unecessary steps in here.

use Getopt::Std;
use Algorithm::Permute;

sub usage() {
print STDERR << "EOF";

Usage:
  $0 [-h] [-g extension] <number>

	-h : Help (print this and exit)
	-p : Print all possible permutations
	-g : Generate a file of possible filename with .extension 
        -u : Generate URLs with a base of base 

example: $0 -g html -u http://testing.com/password_directory/ 12345678

EOF
exit;
}

# get command line options
my $opt_string = "hpg:u:";
my %opt;
getopts($opt_string, %opt); 

if (!$ARGV[0]) { usage(); }
my $number = $ARGV[0];

$opt_h = $opt_h;        #used so Getopts quits complaining
usage() if ($opt_h);

my $permute = $opt_p if ($opt_p);

# priority level
my $extension = '';
$extension = ".".$opt_g if ($opt_g);

my $url = '';
$url = $opt_u if ($opt_u);

# upper and lower are the upper and lower bounds of the ascii 
# code characters that you want to check, as it stands now it
# only checks lowercase a-z.  For long strings this could 
# possibly die a horrible death, but it should catch more 
# possible divisions
my $num = $number;
my $upper = 122;
my $lower = 97;
my @letters = ();
my @numbers = ();
my $index = 0;

my $debug = 0;

for (my $i = $lower; $i <= $upper; $i++) {
  if ($num % $i == 0) { $numbers[$index++] = $i; }
}
if ($debug) { print join(" ", @numbers), "\n"; }
$index = 0;

# this does all the division
for (my $j = 0; $j <= $#numbers; $j++) {
  for (my $i = 0; $i <= $#numbers; $i++) {
    while (($num % $numbers[$i]) == 0 && ($num /= $numbers[$i])) {
      if ($debug) {
        print "$i $numbers[$i] $num "; 
        print chr($numbers[$i]), " \n";
      }
    $letters[$index] .= chr($numbers[$i]);
    }
  }
  push (@numbers, shift(@numbers));
  if ($num != 1) { pop(@letters); }
  if ($num == 1) { $index++; }
  $num = $number;
  if ($debug) { print join(" ", @numbers), "\n"; }
}

for (my $i = 0; $i < $index; $i++) { print $letters[$i], "\n"; }

# this does all the permutation(s)
if ($permute) { 
  foreach my $i (@letters) {
    my @l = split(//,$i);
   Algorithm::Permute::permute { print $url.join('',@l)."$extension\n" } @l;  
  }
}
exit;

