#! /usr/bin/perl

###################################
# Pseudo random number generator  #
# jve - may 2008            	  #
###################################
# this is a very basic PRNG that  #
# should work on every windows OS #
###################################

use warnings;
use strict;
use MIME::Base64;
use Win32::OLE qw(in);

my ($ksize,$kbitsize,$stringkey, @key, $val, $outputfile);

$kbitsize="zzz";
$stringkey ="";

while ($kbitsize !~ /^\d/)
{
	print "key size in bits >";
	$kbitsize=<STDIN>;
	chomp $kbitsize;
}

$ksize = $kbitsize / 32;	# we work on 32 bits words

print "output file name>";
$outputfile = <STDIN>;
chomp $outputfile;

# init using rand value and current time
for my $i (0 .. $ksize)
{
	$key[$i] = pack("B32",(chr(0x36),chr(0x3b),chr(0x6e),chr(0x1f)));
	$key[$i] ^=  pack("B32",rand(4294967294))^pack("B32",localtime());
}

# use temp directory
if (-e "C:\\windows\\temp")
{
	opendir WINTMP, "C:\\windows\\temp";
	my @lstdir = readdir WINTMP;
	closedir WINTMP;
	my $i=0;
	foreach my $file (@lstdir)
	{
		chomp $file;
		$key[$i] ^= pack("B32",$file);
		$i++;
	}
}

# use C:\Program Files directory
if (-e "C:\\Program\ Files")
{
	opendir WINTMP, "C:\\Program\ Files";
	my @lstdir = readdir WINTMP;
	closedir WINTMP;
	my $i=0;
	foreach my $file (@lstdir)
	{
		chomp $file;
		$key[$i] ^= pack("B32",$file);
		$i++;
	}
}


# add some random values
for my $i (0 .. $ksize)
{
	$key[$i] ^= pack("B32",rand(4294967294));
}


# get list of windows processes with their sizes and add it to the key
my $strComputer = '.';
my $objWMI = Win32::OLE->GetObject('winmgmts:\\\\' . $strComputer . '\\root\\cimv2');
my $colProcesses = $objWMI->ExecQuery('Select * from Win32_Process ');
foreach my $objProcess (in $colProcesses)
{
	for my $i (0 .. $ksize)
	{
    		$key[$i] ^= pack("B32",$objProcess->Name.$objProcess->WorkingSetSize);
	}
}

# human interaction is helpful too... (sometimes)
print "\nplease input some random junk from the keyboard\n";
for my $i (0 .. 2)
{
	print ">";
	$val= <STDIN>;
	chomp $val;
	for (split(//, $val))
	{
		$key[int(rand($ksize))] ^= pack("B32",$_ x 4);
	}
}

# parse the key in ascii
for my $i (0 .. $ksize)
{
	for ( split(//, $key[$i]) )
	{
		$stringkey .= unpack("A",$_);
	}
}

print encode_base64($stringkey);

unless (-e "$outputfile")
{
	open OUTPUTFILE, ">$outputfile";
	print OUTPUTFILE "====== $kbitsize bits key in base 64 ======\n";

	print OUTPUTFILE encode_base64($stringkey);

	print OUTPUTFILE "\n=======================================";
	close OUTPUTFILE;

	print "\n\n$outputfile successfully created\n";
}
else
{
	print "ERROR: Output file already exist\n";
}

