#!/usr/bin/perl
#
# implementation of the RC4 algorithm with the 24-bit WEP IV
# as well as an attack on the WEP implementation
#
# -samy kamkar, code@samy.pl

use strict;

my (@S, $i, $j);

die "usage: $0 <hex key> [packets (default: infinite)]\n" unless @ARGV;
my ($key, $times) = @ARGV;
my @key = map { hex($_) } $key =~ /(..)/g;

# the rest of our key, randomness that we try to determine
my $plaintext = "Plaintext";

# loop over times
do
{
	# our KNOWN 24 bit IV. the first 8 bits allows us to determine K[3] for N packets (we use 100 to be more than safe)
	my @IV = (int(rand(256)), int(rand(256)), int(rand(256)));

	# ok, intentionally weakened...takes less packets to pwn
	@IV = (int(rand(20)), 255, int(rand(256)));

	# join our IV and key
	my @K = (@IV, @key);

	# RC4 initialization
	@S = ();
	$i = $j = 0;
	foreach $i (0 .. 255)
	{
		$S[$i] = $i;
	}
	foreach $i (0 .. 255)
	{
		$j = ($j + $S[$i] + $K[$i % @K]) % 256;
		($S[$i], $S[$j]) = ($S[$j], $S[$i]);
	}
	$i = $j = 0;

	my $b;
	foreach my $byte (split(//, $plaintext))
	{
		$b .= unpack("H2", chr(ord($byte) ^ gen_key()));
	}
	print "IV: @IV - cipher: $b\n";

} while (--$times);

sub gen_key
{
	# keystream generator
	$i = ($i + 1) % 256;
	$j = ($j + $S[$i]) % 256;
	($S[$i], $S[$j]) = ($S[$j], $S[$i]);
	my $t = ($S[$i] + $S[$j]) % 256;
	return $S[$t];
}

