Snort_AIPreproc/htdocs/pcap.cgi

133 lines
2.7 KiB
Perl
Executable File

#!/usr/bin/env perl
use strict;
use warnings;
use MIME::Base64;
use Env qw(QUERY_STRING DOCUMENT_ROOT);
sub url_decode {
my $str = shift;
$str =~ s/%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;;
return $str;
}
sub print_pcap_header {
my $out = shift;
# pcap magic_number
print $out pack ( 'L', 0xa1b2c3d4 );
# pcap version_major
print $out pack ( 'S', 0x2 );
# pcap version_minor
print $out pack ( 'S', 0x4 );
# pcap thiszone
print $out pack ( 'l', 0x0 );
# pcap sigfigs
print $out pack ( 'L', 0x0 );
# pcap snaplen
print $out pack ( 'L', 0xffff );
# pcap network
print $out pack ( 'L', 0x1 );
}
sub print_packet {
my ( $out, $packet ) = @_;
# ts_sec
print $out pack ( 'L', $packet->{'time'} );
# ts_usec
print $out pack ( 'L', 0x0 );
my $pkt_data = decode_base64 ( url_decode ( $packet->{'content'} ));
my $hex = unpack ( 'H*', $pkt_data );
my @pairs = $hex =~ /([a-fA-F0-9]{2})/g;
# If this is not an IP packet, trust what the client has told you as packet length
if (( $pairs[0] ne '45' && $pairs[1] ne '00' ) || ( @pairs < 5 ))
{
# incl_len
print $out pack ( 'L', $packet->{'length'} + 12 );
# orig_len
print $out pack ( 'L', $packet->{'length'} + 12 );
} else {
# Otherwise, the length of the packet is the one specified in the IP header
my $length = hex ( $pairs[2].$pairs[3] );
# If the lengths differ (IP length and actual length of the stream received), pad
# the end of the packet with some 0's so that its length matches the one
# specified in the IP header
if ( $length > ( length ( $hex ) / 2 ))
{
my $pad_size = $length - ( length ( $hex ) / 2 );
$hex .= '00' for ( 0..$pad_size-1 );
$pkt_data = pack ( 'H*', $hex );
}
# Add the length of a pseudo-ethernet header
$length += 14;
# incl_len
print $out pack ( 'L', $length );
# orig_len
print $out pack ( 'L', $length );
}
# pseudo ethernet header
print $out pack ( 'H*', 0 x24 );
# ethernet type (IP)
print $out pack ( 'S', 0x8 );
# packet content
print $out $pkt_data;
}
$QUERY_STRING =~ /packets=([0-9]+)/;
my $packets_num = $1;
my %packets = ();
for ( my $i=0; $i < $packets_num; $i++ )
{
$QUERY_STRING =~ /packet_len$i=([0-9]+)/;
my $length = $1;
$QUERY_STRING =~ /time$i=([0-9]+)/;
my $time = $1;
$QUERY_STRING =~ /packet$i=(.+?)(&|$)/;
my $content = $1;
$packets{$i} = {
'length' => $length,
'time' => $time,
'content' => $content
};
}
print "Content-Type: application/pcap\n\n";
# open my $out, "> $DOCUMENT_ROOT/out.pcap";
open my $out, ">&STDOUT";
binmode $out;
print_pcap_header $out;
for ( my $i=0; $i < $packets_num; $i++ )
{
print_packet $out, $packets{$i};
}
close $out;
# print "Content-Type: text/html\\n\\n";
# print "<meta http-equiv=\\"refresh\\" content=\\"0;url=/out.pcap\\">\\n";