1 | initial version |
I created a perl script to convert the log file to a pcap file with syslog messages. Available here: https://gist.github.com/mdeweerd/47ea977028259ee9a6b6fd8f2356c65d#file-logtopcap-pl .
Version when writing this self-anwser:
#!/bin/perl
# SCRIPT TO CONVERT TEXT LOG TO PCAP FILE
# READS DATES FROM LOG FILE
# WHEN READING FROM PIPE (UNTESTED) WITHOUT DATES,
# THE CURRENT TIMESTAMP IS USED.
#
# 0, 1 or 2 parameters to the script:
# - When 0 parameters: uses STDIN, and writes to file.pcap.
# - When 1 parameters: Depends on extension: either .pcap file or log file.
# - When 2 parameters: One of the files should have the .pcap extension
use File::PCAP::Writer;
use Time::HiRes qw(gettimeofday);
use Time::Piece;
use Date::Parse;
use Socket;
use List::Util qw(sum);
use POSIX qw(locale_h);
use locale;
# Make sure text is in English.
setlocale(LC_CTYPE);
my $fname='file.pcap'; # Default output file name
my $logname=''; # Default log file, when '', use STDIN
# Check CLI paramaters
if(scalar(@ARGV)==2) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
$logname=$ARGV[1];
} elsif( $ARGV[1] =~ /.pcap$/ ) {
$fname=$ARGV[1];
$logname=$ARGV[0];
}
} elsif(scalar(@ARGV)==1) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
} else {
$logname=$ARGV[0];
}
}
# Delete the output file
unlink($fname);
# Open the output file
my $fpw = File::PCAP::Writer->new( {
fname => $fname,
dlt => 1,
} );
# Open the input file
my $fh;
my $timeFromFile=0;
if($logname ne '') {
open( $fh => $logname) || die "Cannot open $logname: $!";
$timeFromFile=1;
} else {
$fh=*STDIN;
$logname="STDIN";
}
# Inform about what we are doing
print "Convert $logname to $fname";
# Do conversion
my $t=0;
my $usec;
while( my $line = <$fh> ) {
chomp;
if(length($line)==0||$line=~/^\s*$/) {
next;
}
#print $t;
if($line=~/^\[([^[]*?)\]\s?(.*)/) {
my $timestr=$1;
$line=$2;
$t=str2time($1,"+0000");
#print $timestr." ".$t;
$usec = 0;
$timeFromFile=1;
} elsif(!$timeFromFile) {
($t, $usec) = gettimeofday();
}
$line="<134>".$line;
#$line=gmtime($t)->strftime("%M %b %H:%M:%S")." ".$line;
#print $line."\n";
$buf=getPacketForText($line);
$blen=$plen=length($buf);
$fpw->packet( 0+$t, $usec, $blen, $plen, $buf );
}
#$fpw->close();
# Helper functions, adapted from https://stackoverflow.com/questions/51061864/sending-spoofed-syslog-messages-in-perl
sub udp_checksum {
# thanks to ikegami in post https://stackoverflow.com/questions/46181281/udp-checksum-function-in-perl
my $packed_src_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $packed_dst_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $udp_packet = shift; # UDP header and data as a string.
my $sum = sum(
IPPROTO_UDP,
length($udp_packet),
map({ unpack('n*', $_) }
$packed_src_addr,
$packed_dst_addr,
$udp_packet."\0", # Extra byte ignored if length($udp_packet) is even.
),
);
while (my $hi = $sum >> 16) {
$sum = ($sum & 0xFFFF) + $hi;
}
return ~$sum & 0xFFFF;
}
sub getPacketForText {
$data=shift;
$src_host = "localhost";
$dst_host = 127.0.0.1;
$src_port = 33333;
$dest_port = 514;
$cksum = 0; #initialise, we will sort this later
#$udp_len is the udp packet length in the udp header. Its just 8 plus the length of the data
#for this test harness we will set the data here too
#$data = "<132> %FWSM-3-106010: Deny inbound tcp src outside:215.251.218.222/11839 dst inside:192.168.1.1/369";
#$data="<132> May 22 08:59:12 pf: 00:00:35.159056 rule 3/0(match): block in on em2: (tos 0x0, ttl 128, id 6204, offset 0, flags [none], proto UDP (17), length 235)";
$udp_len = 8+length($data);
$udp_proto = 17; #17 is the code for udp
#Prepare the udp packet, needed for the checksum to happen, then get the checksum (horrifically complicated, just google it)
$udp_packet = pack("nnnna*", $src_port,$dest_port,$udp_len, $cksum, $data);
$cksum = udp_checksum(inet_aton($src_host),inet_aton($dst_host),$udp_packet);
$zero_cksum = 0;
#test harness checks about host IPs
my $dst_host = (gethostbyname($dst_host))[4]; my $src_host = (gethostbyname($src_host))[4];
# Now lets construct the IP packet
my $ip_ver = 4;
my $ip_len = 5;
my $ip_ver_len = $ip_ver . $ip_len;
my $ip_tos = 00;
my ($ip_tot_len) = $udp_len + 20;
my $ip_frag_id = 19245;
my $ip_frag_flag = "010";
my $ip_frag_oset = "0000000000000";
my $ip_fl_fr = $ip_frag_flag . $ip_frag_oset;
my $ip_ttl = 30;
#H2H2nnB16C2na4a4 for the IP Header part#nnnna* for the UDP Header part.
#To understand these, see the manual of pack function and IP and UDP Header formats
#IP checksum ($zero_cksum is calculated by the kernel. Dont worry about it.)
my ($pkt) = pack("H*","0000000000000000000000000800")
#.pack('H2H2nnB16C2na4a4nnnna*',
.pack('H2H2nnB16C2na4a4nnnna*',
$ip_ver_len,$ip_tos,$ip_tot_len,$ip_frag_id,
$ip_fl_fr,$ip_ttl,$udp_proto,$zero_cksum,$src_host,
$dst_host,$src_port,$dest_port,
$udp_len, $cksum, $data);
##bit that makes the socket and sends the packet
##socket(RAW, AF_INET, SOCK_RAW, 255) || die $!; setsockopt(RAW, 0, 1, 1);
##my ($destination) = pack('Sna4x8', AF_INET, $dest_port, $dst_host);
##send(RAW,$pkt,0,$destination);
replace by return
return $pkt;
}
2 | No.2 Revision |
I created a perl script to convert the log file to a pcap file with syslog messages. Available here: https://gist.github.com/mdeweerd/47ea977028259ee9a6b6fd8f2356c65d#file-logtopcap-pl .
After conversion, I just need to drag & drop the pcap files to wireshark to see them all.
Version when writing at the time of this self-anwser:post - I'll probably add the possibility to apply a timeshift:
#!/bin/perl
# SCRIPT TO CONVERT TEXT LOG TO PCAP FILE
# READS DATES FROM LOG FILE
# WHEN READING FROM PIPE (UNTESTED) WITHOUT DATES,
# THE CURRENT TIMESTAMP IS USED.
#
# 0, 1 or 2 parameters to the script:
# - When 0 parameters: uses STDIN, and writes to file.pcap.
# - When 1 parameters: Depends on extension: either .pcap file or log file.
# - When 2 parameters: One of the files should have the .pcap extension
use File::PCAP::Writer;
use Time::HiRes qw(gettimeofday);
use Time::Piece;
use Date::Parse;
use Socket;
use List::Util qw(sum);
use POSIX qw(locale_h);
use locale;
# Make sure text is in English.
setlocale(LC_CTYPE);
my $fname='file.pcap'; # Default output file name
my $logname=''; # Default log file, when '', use STDIN
# Check CLI paramaters
if(scalar(@ARGV)==2) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
$logname=$ARGV[1];
} elsif( $ARGV[1] =~ /.pcap$/ ) {
$fname=$ARGV[1];
$logname=$ARGV[0];
}
} elsif(scalar(@ARGV)==1) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
} else {
$logname=$ARGV[0];
}
}
# Delete the output file
unlink($fname);
# Open the output file
my $fpw = File::PCAP::Writer->new( {
fname => $fname,
dlt => 1,
} );
# Open the input file
my $fh;
my $timeFromFile=0;
if($logname ne '') {
open( $fh => $logname) || die "Cannot open $logname: $!";
$timeFromFile=1;
} else {
$fh=*STDIN;
$logname="STDIN";
}
# Inform about what we are doing
print "Convert $logname to $fname";
# Do conversion
my $t=0;
my $usec;
while( my $line = <$fh> ) {
chomp;
if(length($line)==0||$line=~/^\s*$/) {
next;
}
#print $t;
if($line=~/^\[([^[]*?)\]\s?(.*)/) {
my $timestr=$1;
$line=$2;
$t=str2time($1,"+0000");
#print $timestr." ".$t;
$usec = 0;
$timeFromFile=1;
} elsif(!$timeFromFile) {
($t, $usec) = gettimeofday();
}
$line="<134>".$line;
#$line=gmtime($t)->strftime("%M %b %H:%M:%S")." ".$line;
#print $line."\n";
$buf=getPacketForText($line);
$blen=$plen=length($buf);
$fpw->packet( 0+$t, $usec, $blen, $plen, $buf );
}
#$fpw->close();
# Helper functions, adapted from https://stackoverflow.com/questions/51061864/sending-spoofed-syslog-messages-in-perl
sub udp_checksum {
# thanks to ikegami in post https://stackoverflow.com/questions/46181281/udp-checksum-function-in-perl
my $packed_src_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $packed_dst_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $udp_packet = shift; # UDP header and data as a string.
my $sum = sum(
IPPROTO_UDP,
length($udp_packet),
map({ unpack('n*', $_) }
$packed_src_addr,
$packed_dst_addr,
$udp_packet."\0", # Extra byte ignored if length($udp_packet) is even.
),
);
while (my $hi = $sum >> 16) {
$sum = ($sum & 0xFFFF) + $hi;
}
return ~$sum & 0xFFFF;
}
sub getPacketForText {
$data=shift;
$src_host = "localhost";
$dst_host = 127.0.0.1;
$src_port = 33333;
$dest_port = 514;
$cksum = 0; #initialise, we will sort this later
#$udp_len is the udp packet length in the udp header. Its just 8 plus the length of the data
#for this test harness we will set the data here too
#$data = "<132> %FWSM-3-106010: Deny inbound tcp src outside:215.251.218.222/11839 dst inside:192.168.1.1/369";
#$data="<132> May 22 08:59:12 pf: 00:00:35.159056 rule 3/0(match): block in on em2: (tos 0x0, ttl 128, id 6204, offset 0, flags [none], proto UDP (17), length 235)";
$udp_len = 8+length($data);
$udp_proto = 17; #17 is the code for udp
#Prepare the udp packet, needed for the checksum to happen, then get the checksum (horrifically complicated, just google it)
$udp_packet = pack("nnnna*", $src_port,$dest_port,$udp_len, $cksum, $data);
$cksum = udp_checksum(inet_aton($src_host),inet_aton($dst_host),$udp_packet);
$zero_cksum = 0;
#test harness checks about host IPs
my $dst_host = (gethostbyname($dst_host))[4]; my $src_host = (gethostbyname($src_host))[4];
# Now lets construct the IP packet
my $ip_ver = 4;
my $ip_len = 5;
my $ip_ver_len = $ip_ver . $ip_len;
my $ip_tos = 00;
my ($ip_tot_len) = $udp_len + 20;
my $ip_frag_id = 19245;
my $ip_frag_flag = "010";
my $ip_frag_oset = "0000000000000";
my $ip_fl_fr = $ip_frag_flag . $ip_frag_oset;
my $ip_ttl = 30;
#H2H2nnB16C2na4a4 for the IP Header part#nnnna* for the UDP Header part.
#To understand these, see the manual of pack function and IP and UDP Header formats
#IP checksum ($zero_cksum is calculated by the kernel. Dont worry about it.)
my ($pkt) = pack("H*","0000000000000000000000000800")
#.pack('H2H2nnB16C2na4a4nnnna*',
.pack('H2H2nnB16C2na4a4nnnna*',
$ip_ver_len,$ip_tos,$ip_tot_len,$ip_frag_id,
$ip_fl_fr,$ip_ttl,$udp_proto,$zero_cksum,$src_host,
$dst_host,$src_port,$dest_port,
$udp_len, $cksum, $data);
##bit that makes the socket and sends the packet
##socket(RAW, AF_INET, SOCK_RAW, 255) || die $!; setsockopt(RAW, 0, 1, 1);
##my ($destination) = pack('Sna4x8', AF_INET, $dest_port, $dst_host);
##send(RAW,$pkt,0,$destination);
replace by return
return $pkt;
}
3 | No.3 Revision |
I created a perl script to convert the log file to a pcap file with syslog messages. Available here: https://gist.github.com/mdeweerd/47ea977028259ee9a6b6fd8f2356c65d#file-logtopcap-pl .
After conversion, I just need to drag & drop the pcap files to wireshark to see them all.
Version at the time of this post - I'll probably add the possibility to apply a timeshift:
#!/bin/perl
# SCRIPT TO CONVERT TEXT LOG TO PCAP FILE
# READS DATES FROM LOG FILE
# WHEN READING FROM PIPE (UNTESTED) WITHOUT DATES,
# THE CURRENT TIMESTAMP IS USED.
#
# 0, 1 or 2 parameters to the script:
# - When 0 parameters: uses STDIN, and writes to file.pcap.
# - When 1 parameters: Depends on extension: either .pcap file or log file.
# - When 2 parameters: One of the files should have the .pcap extension
use File::PCAP::Writer;
use Time::HiRes qw(gettimeofday);
use Time::Piece;
use Date::Parse;
use Socket;
use List::Util qw(sum);
use POSIX qw(locale_h);
use locale;
# Make sure text is in English.
setlocale(LC_CTYPE);
my $fname='file.pcap'; # Default output file name
my $logname=''; # Default log file, when '', use STDIN
# Check CLI paramaters
if(scalar(@ARGV)==2) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
$logname=$ARGV[1];
} elsif( $ARGV[1] =~ /.pcap$/ ) {
$fname=$ARGV[1];
$logname=$ARGV[0];
}
} elsif(scalar(@ARGV)==1) {
if( $ARGV[0] =~ /.pcap$/ ) {
$fname=$ARGV[0];
} else {
$logname=$ARGV[0];
}
}
# Delete the output file
unlink($fname);
# Open the output file
my $fpw = File::PCAP::Writer->new( {
fname => $fname,
dlt => 1,
} );
# Open the input file
my $fh;
my $timeFromFile=0;
if($logname ne '') {
open( $fh => $logname) || die "Cannot open $logname: $!";
$timeFromFile=1;
} else {
$fh=*STDIN;
$logname="STDIN";
}
# Inform about what we are doing
print "Convert $logname to $fname";
# Do conversion
my $t=0;
my $usec;
while( my $line = <$fh> ) {
chomp;
if(length($line)==0||$line=~/^\s*$/) {
next;
}
#print $t;
if($line=~/^\[([^[]*?)\]\s?(.*)/) {
my $timestr=$1;
$line=$2;
$t=str2time($1,"+0000");
#print $timestr." ".$t;
$usec = 0;
$timeFromFile=1;
} elsif(!$timeFromFile) {
($t, $usec) = gettimeofday();
}
$line="<134>".$line;
#$line=gmtime($t)->strftime("%M %b %H:%M:%S")." ".$line;
#print $line."\n";
$buf=getPacketForText($line);
$blen=$plen=length($buf);
$fpw->packet( 0+$t, $usec, $blen, $plen, $buf );
}
#$fpw->close();
# Helper functions, adapted from https://stackoverflow.com/questions/51061864/sending-spoofed-syslog-messages-in-perl
sub udp_checksum {
# thanks to ikegami in post https://stackoverflow.com/questions/46181281/udp-checksum-function-in-perl
my $packed_src_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $packed_dst_addr = shift; # As 4-char string, e.g. as returned by inet_aton.
my $udp_packet = shift; # UDP header and data as a string.
my $sum = sum(
IPPROTO_UDP,
length($udp_packet),
map({ unpack('n*', $_) }
$packed_src_addr,
$packed_dst_addr,
$udp_packet."\0", # Extra byte ignored if length($udp_packet) is even.
),
);
while (my $hi = $sum >> 16) {
$sum = ($sum & 0xFFFF) + $hi;
}
return ~$sum & 0xFFFF;
}
sub getPacketForText {
$data=shift;
$src_host = "localhost";
$dst_host = 127.0.0.1;
$src_port = 33333;
$dest_port = 514;
$cksum = 0; #initialise, we will sort this later
#$udp_len is the udp packet length in the udp header. Its just 8 plus the length of the data
#for this test harness we will set the data here too
#$data = "<132> %FWSM-3-106010: Deny inbound tcp src outside:215.251.218.222/11839 dst inside:192.168.1.1/369";
#$data="<132> May 22 08:59:12 pf: 00:00:35.159056 rule 3/0(match): block in on em2: (tos 0x0, ttl 128, id 6204, offset 0, flags [none], proto UDP (17), length 235)";
$udp_len = 8+length($data);
$udp_proto = 17; #17 is the code for udp
#Prepare the udp packet, needed for the checksum to happen, then get the checksum (horrifically complicated, just google it)
$udp_packet = pack("nnnna*", $src_port,$dest_port,$udp_len, $cksum, $data);
$cksum = udp_checksum(inet_aton($src_host),inet_aton($dst_host),$udp_packet);
$zero_cksum = 0;
#test harness checks about host IPs
my $dst_host = (gethostbyname($dst_host))[4]; my $src_host = (gethostbyname($src_host))[4];
# Now lets construct the IP packet
my $ip_ver = 4;
my $ip_len = 5;
my $ip_ver_len = $ip_ver . $ip_len;
my $ip_tos = 00;
my ($ip_tot_len) = $udp_len + 20;
my $ip_frag_id = 19245;
my $ip_frag_flag = "010";
my $ip_frag_oset = "0000000000000";
my $ip_fl_fr = $ip_frag_flag . $ip_frag_oset;
my $ip_ttl = 30;
#H2H2nnB16C2na4a4 for the IP Header part#nnnna* for the UDP Header part.
#To understand these, see the manual of pack function and IP and UDP Header formats
#IP checksum ($zero_cksum is calculated by the kernel. Dont worry about it.)
my ($pkt) = pack("H*","0000000000000000000000000800")
#.pack('H2H2nnB16C2na4a4nnnna*',
.pack('H2H2nnB16C2na4a4nnnna*',
$ip_ver_len,$ip_tos,$ip_tot_len,$ip_frag_id,
$ip_fl_fr,$ip_ttl,$udp_proto,$zero_cksum,$src_host,
$dst_host,$src_port,$dest_port,
$udp_len, $cksum, $data);
##bit that makes the socket and sends the packet
##socket(RAW, AF_INET, SOCK_RAW, 255) || die $!; setsockopt(RAW, 0, 1, 1);
##my ($destination) = pack('Sna4x8', AF_INET, $dest_port, $dst_host);
##send(RAW,$pkt,0,$destination);
# replace by return
return $pkt;
}