use strict; use warnings; use Convert::Binary::C qw( ); use IO::Socket; use Net::IP qw( ); use Data::Hexdumper; use constant QUERY_MAGIC => 0x0defaced; use constant QTYPE_FINGERPRINT => 1; die "usage: p0fq.pl p0f_socket src_ip src_port dst_ip dst_port" unless @ARGV == 5; my $c = Convert::Binary::C->new( LongSize => 4, ShortSize => 2, Alignment => 4, ByteOrder => 'BigEndian', ); eval { $c->parse_file("p0f-query.h") }; if ($@) { die "Parse error: $@"; } # Convert the IPs and pack the request message my $src = Net::IP->new( $ARGV[1] ) or die( Net::IP::Error() ); my $dst = Net::IP->new( $ARGV[3] ) or die( Net::IP::Error() ); print "src ip:", ($src->ip()), "\n", "dst ip:", ($dst->ip()), "\n"; my $query = $c->pack( 'p0f_query', { magic => QUERY_MAGIC, type => QTYPE_FINGERPRINT, id => 0x12345678, src_ad => $src->intip(), dst_ad => $dst->intip(), src_port => $ARGV[2], dst_port => $ARGV[4], } ); print "query:\n", hexdump( data => $query, ); # Open the connection to p0f my $sock = IO::Socket::UNIX->new( Peer => $ARGV[0], Type => SOCK_STREAM, ) or die "Could not create socket: $!\n"; # Ask p0f print $sock $query; my $response = <$sock>; # yuck! close $sock; print "response:\n", hexdump( data => $response, ); # Extract the response from p0f my $data = $c->unpack( 'p0f_response', $response ); die "Bad response magic.\n" if $data->{magic} != QUERY_MAGIC; die "P0f did not honor our query.\n" if $data->{type} == 1; die "This connection is not (no longer?) in the cache.\n" if $data->{type} == 2; # Display result print "Genre : " . $data->{genre} . "\n"; print "Details : " . $data->{detail} . "\n"; print "Distance : " . $data->{dist} . " hops\n"; print "Link : " . $data->{link} . "\n"; print "Uptime : " . $data->{uptime} . " hrs\n"; #### src ip:192.168.1.2 dst ip:192.168.1.1 query: 0x0000 : 0D EF AC ED 01 00 00 00 12 34 56 78 00 00 00 00 : .........4Vx.... 0x0010 : 00 00 00 00 00 00 01 BB : ........ response: 0x0000 : 0D EF AC ED 12 34 56 78 02 00 00 00 00 00 00 00 : .....4Vx........ 0x0010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0020 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0030 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0040 : 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 : ................ 0x0050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ 0x0080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................ This connection is not (no longer?) in the cache.