#!/usr/bin/perl -w # bmc@shmoo.com # license: perl artistic, same as NetPacket, since I c&p some of netpacket to fix a bug in the IP checksum calculations. use strict; use warnings; use Net::Pcap; use NetPacket::Ethernet qw(ETH_TYPE_IP); use NetPacket::IP qw(:flags); use NetPacket::TCP; use NetPacket::UDP; use NetPacket::ICMP; my $err; die "$0 \n" if (scalar(@ARGV) != 2); my ($input, $output) = @ARGV; my $in = Net::Pcap::open_offline($input, \$err) || die "Cant open input file: $err"; my $type = Net::Pcap::datalink_val_to_description(Net::Pcap::datalink($in)); if ($type ne 'Ethernet') { die "This tool is only useful for ethernet. sorry\n"; } my $out = Net::Pcap::dump_open($in, $output) || die Net::Pcap::geterr($in); Net::Pcap::loop($in, -1, \&process, ''); Net::Pcap::close($in); Net::Pcap::dump_close($out); sub process { my ($data, $hdr, $pkt) = @_; my $eth = NetPacket::Ethernet->decode($pkt); if ($eth->{'type'} eq ETH_TYPE_IP) { my $ip = NetPacket::IP->decode($eth->{data}); if ($ip->{'foffset'} == 0 && $ip->{'flags'} != 1) { if ($ip->{proto} == 6) { # TCP my $tcp = NetPacket::TCP->decode($ip->{'data'}); $ip->{data} = $tcp->encode($ip); } elsif ($ip->{proto} == 17) { # UDP my $udp = NetPacket::UDP->decode($ip->{'data'}); $ip->{data} = $udp->encode($ip); } elsif ($ip->{proto} == 1) { # ICMP my $icmp = NetPacket::ICMP->decode($ip->{'data'}); $ip->{data} = $icmp->encode($ip); } else { $ip->{data} = $ip->{data}; # cheak hack } } my $new = substr($pkt, 0, 14) . my_encode($ip); Net::Pcap::dump($out, $hdr, $new); } else { Net::Pcap::dump($out, $hdr, $pkt); } } # because NetPacket::IP is broken... sub my_encode { my ($self) = @_; # adjust the length of the packet $self->{len} = ($self->{hlen} * 4) + length($self->{data}); my $tmp = $self->{hlen} & 0x0f; $tmp = $tmp | (($self->{ver} << 4) & 0xf0); my $offset = $self->{flags} << 13; $offset = $offset | (($self->{foffset} >> 3) & 0x1fff); # convert the src and dst ip my $src_ip = gethostbyname($self->{src_ip}); my $dest_ip = gethostbyname($self->{dest_ip}); # construct header to calculate the checksum my $hdr = pack('CCnnnCCna4a4a*', $tmp, $self->{tos},$self->{len}, $self->{id}, $offset, $self->{ttl}, $self->{proto}, 0, $src_ip, $dest_ip, $self->{options}); $self->{cksum} = NetPacket::htons(NetPacket::in_cksum($hdr)); my $packet = pack('CCnnnCCna4a4a*a*', $tmp, $self->{tos},$self->{len}, $self->{id}, $offset, $self->{ttl}, $self->{proto}, $self->{cksum}, $src_ip, $dest_ip, $self->{options}, $self->{data}); return($packet); }