#!/usr/bin/perl -w use strict; use Data::Dumper; use IO::Socket::INET; $|++; my %chars; my %bad; my %positions = ( 'first' => sub { return 'GET ' . $_[0] . '/bad.html HTTP/1.0' }, 'middle' => sub { return 'GET /ba' . $_[0] . 'd.html HTTP/1.0' }, 'last' => sub { return 'GET /bad.html' . $_[0] .' HTTP/1.0'}, 'last_space_char_space' => sub { return 'GET /bad.html ' . $_[0] .' HTTP/1.0'}, 'last_space_char' => sub { return 'GET /bad.html ' . $_[0] .'HTTP/1.0'}, 'last_space' => sub { return 'GET /bad.html' . $_[0] .'HTTP/1.0'}, 'first_space' => sub { return 'GET' . $_[0] .'/bad.html HTTP/1.0'}, 'dot' => sub { return 'GET /bad' . $_[0] .'.html HTTP/1.0'}, ); for (my $c = 0; $c <= 255; $c++) { foreach my $pos (keys %positions) { my $got = get(&{$positions{$pos}}(chr($c))); if (!$got) { $bad{$c}{$pos} = 1; } elsif ($got =~ /I am a bad bad man/i) { $chars{$c}{$pos} = 1; } } } foreach my $c (sort {$a <=> $b} keys %chars) { my $char = chr($c); print "$c "; if ($char =~ /[[:print:]]/) { print "( $char ) "; } print ': ' . join(', ', sort keys %{ $chars{$c} } ) . "\n"; } foreach my $c (sort {$a <=> $b} keys %bad) { my $char = chr($c); print "BAD $c "; if ($char =~ /[[:print:]]/) { print "( $char ) "; } print ': ' . join(', ', sort keys %{ $bad{$c} } ) . "\n"; } sub get { my ($string) = @_; my $sock = setup(); while (!$sock) { $sock = setup(); print ".\n";} print $sock $string . "\r\n\r\n" || die "ACK $! $?"; local $/; my $response; eval { local $SIG{ALRM} = sub { die "alarm clock restart" }; alarm 2; $response = <$sock>; alarm 0; }; if ($@) { if ($@ !~ /alarm clock restart/) { die; } else { return; } } return $response; } sub setup { my ($host) = $ARGV[0]; die "no host specified\n" if (!$host); my $sock = IO::Socket::INET->new(PeerPort => 80, PeerAddr => $ARGV[0], Proto => 'tcp', Timeout => 30); if (!$sock) { warn "can't connect, trying again...\n"; return; } return ($sock); }